Обратное распространение не работает: нейронная сеть Java

Я создал простую нейронную сеть с 3 слоями в соответствии с этим примером Python: Ссылка (PS: вам нужно прокрутить вниз, пока не дойдете до части 2)

Это моя реализация кода Java:

private void trainNet()
{
    // INPUT is a 4*3 matrix
    // SYNAPSES is a 3*4 matrix
    // SYNAPSES2 is a 4*1 matrix
    // 4*3 matrix DOT 3*4 matrix => 4*4 matrix: unrefined test results
    double[][] layer1 = sigmoid(dot(inputs, synapses), false);

    // 4*4 matrix DOT 4*1 matrix => 4*1 matrix: 4 final test results
    double[][] layer2 = sigmoid(dot(layer1, synapses2), false);

    // 4*1 matrix - 4*1 matrix => 4*1 matrix: error of 4 test results
    double[][] layer2Error = subtract(outputs, layer2);

    // 4*1 matrix DOT 4*1 matrix => 4*1 matrix: percentage of change of 4 test results
    double[][] layer2Delta = dot(layer2Error, sigmoid(layer2, true));

    // 4*1 matrix DOT 3*1 matrix => 4*1 matrix
    double[][] layer1Error = dot(layer2Delta, synapses2);

    // 4*1 matrix DOT 4*4 matrix => 4*4 matrix: percentage of change of 4 test results
    double[][] layer1Delta = dot(layer1Error, sigmoid(layer1, true));

    double[][] transposedInputs = transpose(inputs);
    double[][] transposedLayer1 = transpose(layer1);

    //  4*4 matrix DOT 4*1 matrix => 4*1 matrix: the updated weights
    // Update the weights
    synapses2 = sum(synapses2, dot(transposedLayer1, layer2Delta));

    // 3*4 matrix DOT 4*4 matrix => 3*4 matrix: the updated weights
    // Update the weights
    synapses = sum(synapses, dot(transposedInputs, layer1Delta));

    // Test each value of two 4*1 matrices with each other
    testValue(layer2, outputs);
}

Функции точки, суммы, вычитания и транспонирования я создал сам, и я уверен, что они отлично справляются со своей задачей.

Первая партия входных данных дает мне ошибку около 0,4, что нормально, потому что веса имеют случайное значение. При втором прогоне допустимая погрешность меньше, но лишь на очень небольшую величину (0,001).

После 500 000 пакетов (всего 2 000 000 тестов) сеть так и не выдала правильного значения! Поэтому я попытался использовать еще большее количество партий. Используя 1 000 000 пакетов (всего 4 000 000 тестов), сеть генерирует колоссальные 16 900 правильных результатов.

Кто-нибудь может сказать мне, что происходит?

Это были используемые веса:

Первый слой:

  • 2.038829298171684 2.816232761170282 1.6740269469812146 1.634422766238497
  • 1.5890997594993828 1.7909325329112222 2.101840236824494 1.063579126586681
  • 3.761238407071311 3.757148454039234 3.7557450538398176 3.6715972104291605

Второй слой:

  • -0.019603811941904248
  • 218.38253323323553
  • 53.70133275445734
  • -272.83589796861514

    РЕДАКТИРОВАТЬ: Спасибо lsnare за то, что указал мне, что использование библиотеки было бы намного проще!

Для тех, кто заинтересован, вот рабочий код с использованием библиотеки math.nist.gov/javanumerics:

private void trainNet()
{
    // INPUT is a 4*3 matrix
    // SYNAPSES is a 3*4 matrix
    // SYNAPSES2 is a 4*1 matrix
    // 4*3 matrix DOT 3*4 matrix => 4*4 matrix: unrefined test results
    Matrix hiddenLayer = sigmoid(inputs.times(synapses), false);

    // 4*4 matrix DOT 4*1 matrix => 4*1 matrix: 4 final test results
    Matrix outputLayer = sigmoid(hiddenLayer.times(synapses2), false);

    // 4*1 matrix - 4*1 matrix => 4*1 matrix: error of 4 test results
    Matrix outputLayerError = outputs.minus(outputLayer);

    // 4*1 matrix DOT 4*1 matrix => 4*1 matrix: percentage of change of 4 test results
    Matrix outputLayerDelta = outputLayerError.arrayTimes(sigmoid(outputLayer, true));

    // 4*1 matrix DOT 1*4 matrix => 4*4 matrix
    Matrix hiddenLayerError = outputLayerDelta.times(synapses2.transpose());

    // 4*4 matrix DOT 4*4 matrix => 4*4 matrix: percentage of change of 4 test results
    Matrix hiddenLayerDelta = hiddenLayerError.arrayTimes(sigmoid(hiddenLayer, true));

    //  4*4 matrix DOT 4*1 matrix => 4*1 matrix: the updated weights
    // Update the weights
    synapses2 = synapses2.plus(hiddenLayer.transpose().times(outputLayerDelta));

    // 3*4 matrix DOT 4*4 matrix => 3*4 matrix: the updated weights
    // Update the weights
    synapses = synapses.plus(inputs.transpose().times(hiddenLayerDelta));

    // Test each value of two 4*1 matrices with each other
    testValue(outputLayer.getArrayCopy(), outputs.getArrayCopy());
}

person Caske2000    schedule 09.12.2016    source источник
comment
Можете ли вы добавить в свои функции точки, суммы, вычитания, транспонирования и сигмовидной только для пояснения?   -  person CraigR8806    schedule 09.12.2016


Ответы (1)


Как правило, при написании кода, включающего сложные математические или числовые вычисления (например, линейную алгебру), лучше использовать существующие библиотеки, написанные экспертами в данной области, а не писать собственные функции. Стандартные библиотеки дают более точные результаты и, скорее всего, более эффективны. Например, в блоге, на который вы ссылаетесь, автор использует библиотеку numpy для вычисления скалярных произведений и перестановки матриц. Для Java вы можете использовать Java Matrix Package (JAMA), разработанный NIST: http://math.nist.gov/javanumerics/jama/
Например, чтобы транспонировать матрицу:

double[4][3] in = {{0,0,1},{0,1,1},{1,0,1},{1,1,1}};
Matrix input = new Matrix(in);
input = input.transpose();

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

person lsnare    schedule 09.12.2016
comment
Я не могу отблагодарить вас за указание на это мне! Проблема заключалась в том, что мои методы работали, но недостаточно проверяли ошибки, чтобы матрицу mn можно было умножить на матрицу pq (p ≠ n). - person Caske2000; 09.12.2016
comment
Рад помочь! Я столкнулся с подобными проблемами при попытке реализовать матричные операции самостоятельно :) - person lsnare; 09.12.2016