Visual Studio 2017 - Изменение значений экземпляра класса ведет себя странно - PullRequest
0 голосов
/ 21 мая 2018

Использование Visual Studio 2017, C #

Итак, у меня есть класс, который хранит данные в нескольких двумерных или трехмерных массивах из другого метода.Однако, когда я фактически изменяю одно из значений (и только одно из значений), изменение любых других значений в экземпляре класса также изменяет это значение.Ничто не является статичным, и ничего не происходит между изменением одного значения и изменением другого.

Класс;

public class TestResults
{
    public int finalResult;
    public float[,] activations;
    public float[,] magnitudes;
    public float[, ,] weights;
    public float[,] biases;
    public int actual;

    public TestResults(int newF, float[,] newAct, float[,] newMag, float[, ,] newW, float[,] newB, int newA)
    {
        finalResult = newF;
        activations = newAct;
        magnitudes = newMag;
        weights = newW;
        biases = newB;
        actual = newA;
    }
}

Проблемный сценарий (

for (int l = 1; l < 4; l++)
            {
                for (int i = 0; i < nodeCounts[l]; i++)
                {
                    float newValue = 0;
                    for (int j = 0; j < nodeCounts[l - 1]; j++)
                    {
                        float inputValue = nodes[l - 1, j].value;
                        float newMag = (inputValue * nodes[l, i].weights[j]);

                        newValue += newMag;

                        //Update test results
                        result.weights[l, i, j] = nodes[l, i].weights[j];
                    }
                    nodes[l, i].value = Squish(newValue + nodes[l, i].bias);

                    //Update test results
                    result.activations[l, i] = nodes[l, i].value; //This value right here is what is causing the issues. Debugging showed that the value is correct (equal to nodes[l, i].value) right after this line, but after the next line the value changes, and it changes again after the next.
                    result.magnitudes[l, i] = newValue;
                    result.biases[l, i] = nodes[l, i].bias;

                    float debug = result.activations[l, i];
                }
            }

Короче говоря, значение

result.activations[l, i]

должно оставаться эквивалентным

nodes[l, i].value

... но по какой-то причине это не так. Если это помогает, значение nodes[l, i].value всегда между 0 и 1 (отладка показывает, что это работает правильно), и все же значение result.activations[l, i] всегда заканчивается как отрицательное целое число (типичное значение result.biases[l, i]). Я попытался изменить все типы значений надесятичное число (в этом состоянии они являются числами с плавающей точкой), но результат был таким же.

Я уничтожил кнопку поиска Google, чтобы обнаружить, что никто до этого не сталкивался с этой проблемой. На данный момент я начинаюЯ думаю, что это ошибка самой Visual Studio. Любая помощь в решении этой проблемы будет признательна. Перезапуск Visual Studio и моего ноутбука ничего не сделал. Спасибо, Райан Г.

РЕДАКТИРОВАТЬ: Вотполный метод, в том числе тЦикл я выделил ранее в этом вопросе.Надеюсь, это даст лучший контекст.

TestResults TestNetwork(byte[] image, int[] nodeCounts, Node[ , ] nodes, int actual)
        {
            float[,] resultsFloats = new float[nodeCounts.Count(), nodes.GetLength(1)];
            TestResults result = new TestResults(0, resultsFloats, resultsFloats, new float[nodeCounts.Count(), nodes.GetLength(1), nodes.GetLength(1)], resultsFloats, 0);

            int finalResult = 0;

            //Match image values to input nodes

            for(int i = 0; i < nodeCounts[0]; i++)
            {
                nodes[0, i].value = (float)image[i] / 255;

                //Update test results
                result.activations[0, i] = nodes[0, i].value;
            }

            //Calculate values for second, third, and fourth layers

            for (int l = 1; l < 4; l++)
            {
                for (int i = 0; i < nodeCounts[l]; i++)
                {
                    float newValue = 0;
                    for (int j = 0; j < nodeCounts[l - 1]; j++)
                    {
                        float inputValue = nodes[l - 1, j].value;
                        float newMag = (inputValue * nodes[l, i].weights[j]);

                        newValue += newMag;

                        //Update test results
                        result.weights[l, i, j] = nodes[l, i].weights[j];
                    }
                    nodes[l, i].value = Squish(newValue + nodes[l, i].bias);

                    //Update test results
                    result.activations[l, i] = nodes[l, i].value;
                    result.magnitudes[l, i] = newValue;
                    result.biases[l, i] = nodes[l, i].bias;

                    float debug = result.activations[l, i];
                }
            }
            //Decide result

            float mag = -1;
            for (int i = 0; i < 10; i++)
            {
                if (nodes[nodeCounts.Count() - 1, i].value > mag)
                {
                    finalResult = i;
                    mag = nodes[nodeCounts.Count() - 1, i].value;
                }
            }

            result.finalResult = finalResult;
            result.actual = actual;

            return result;
        }

Узел - это просто еще один класс, в котором мне нужно хранить больше данных.Как видно в верхней части функции, когда инициализируется экземпляр TestResults, для каждого из массивов выделяется память, используя другие значения.

РЕДАКТИРОВАТЬ 2: Просто запустил еще один тест:

TestResults dTR = new TestResults(0, new float[2, 2], new float[2, 2], new float[2, 2, 2], new float[2, 2], 0);
            dTR.activations[0, 0] = 1;
            dTR.magnitudes[0, 0] = 2;
            dTR.biases[0, 0] = 3;

            Console.WriteLine(dTR.activations[0, 0] + ", " + dTR.magnitudes[0, 0] + ", " + dTR.biases[0, 0]);

Выводит «1, 2, 3», как и должно быть.Я не понимаю, чем это отличается от моего проблемного кода.

ОБНОВЛЕНИЕ: После того, как я сдался и захотел спать, я понял, что основная проблема заключалась в том, что result.activations[l, i] менялитак как я менял значения после того, как я уже изменил свое значение.Итак, пытаясь сделать очевидное, я просто помещаю строку, где я изменяю ее значение, после строк, где я изменяю все остальные значения.Работал как шарм.

Я вижу, что это решение с клейкой лентой, и я хочу понять, почему это все еще происходит, поэтому я обновлю этот пост позже, когда попробую некоторые изПредлагаемые исправления в ответах.

1 Ответ

0 голосов
/ 21 мая 2018

Я думаю, что ваша проблема в том, что вы не выделяете память для своих массивов.

В конструкторе вы должны выделять память для своих массивов.Что-то вроде:

public TestResults()
{
    activations = new float[10,10];
    magnitudes = new float[10,10];
    weights = new float[10,10,10];
    biases = new float[10,10];
}

В приведенном выше коде вы выделяете 10 «пробелов», если хотите, для каждого многомерного массива.В противном случае вы перезаписываете свою память, так как она не была выделена.

Кроме того, то, как вы сейчас это делаете, не будет работать, потому что входные параметры вашего конструктора передаются по значению, поэтому есливы действительно хотите создать их экземпляры вне конструктора и передать их, вам нужно сделать их ссылками с ключевым словом ref.

Если вы хотите упростить свою жизнь, используйте списки и дайте им расти.динамически, как может потребоваться в вашем коде, не беспокоясь об этом.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...