Нейронная сеть Завышение выработки рукописных цифр

Итак, я пытаюсь создать свою собственную нейронную сеть. Что-то действительно простое.

Мой ввод — база данных рукописных цифр MNIST.
Ввод: 28 * 28 нейронов (изображения).
Выход: 10 нейронов (0/1/2/3/4/5/6/7/8/9).
Моя сеть выглядит следующим образом: 28 * 28 -> 15 -> 10.

Проблема остается в моем предполагаемом результате. Действительно, кажется, у меня есть градиентный взрыв.

Вывод, предоставленный моей сетью, находится здесь: https://pastebin.com/EFpBGAZd

Как видите, первый расчетный результат неверен. Так что моя сеть корректирует вес благодаря обратному распространению. Но, похоже, он не обновляет вес правильно. Действительно, расчетный объем производства слишком высок по сравнению со вторым по величине значением.
Таким образом, первый расчетный результат остается лучшим расчетным выходом для следующего обучения (13 в моем примере).

Мой код обратного распространения:

VOID BP(NETWORK &Network, double Target[OUTPUT_NEURONS]) {
double DeltaETotalOut = 0;
double DeltaOutNet = 0;
double DeltaErrorNet = 0;
double DeltaETotalWeight = 0;
double Error = 0;
double ErrorTotal = 0;
double OutputUpdatedWeights[OUTPUT_NEURONS*HIDDEN_NEURONS] = { 0 };
unsigned int _indexOutput = 0;
double fNetworkError = 0;

//Calculate Error
for (int i = 0; i < OUTPUT_NEURONS; i++) {
fNetworkError += 0.5*pow(Target[i] - Network.OLayer.Cell[i].Output, 2);
}
Network.Error = fNetworkError;//Output Neurons
for (int i = 0; i < OUTPUT_NEURONS; i++) {
DeltaETotalOut = -(Target[i] - Network.OLayer.Cell[i].Output);
DeltaOutNet = ActivateSigmoidPrime(Network.OLayer.Cell[i].Output);

for (int j = 0; j < HIDDEN_NEURONS; j++) {
OutputUpdatedWeights[_indexOutput] = Network.OLayer.Cell[i].Weight[j] - 0.5 * DeltaOutNet*DeltaETotalOut* Network.HLayer.Cell[j].Output;
_indexOutput++;
}
}

//Hidden Neurons
for (int i = 0; i < HIDDEN_NEURONS; i++) {
ErrorTotal = 0;
for (int k = 0; k < OUTPUT_NEURONS; k++) {
DeltaETotalOut = -(Target[k] - Network.OLayer.Cell[k].Output);
DeltaOutNet = ActivateSigmoidPrime(Network.OLayer.Cell[k].Output);
DeltaErrorNet = DeltaETotalOut * DeltaOutNet;
Error = DeltaErrorNet * Network.OLayer.Cell[k].Weight[i];
ErrorTotal += Error;
}

DeltaOutNet = ActivateSigmoidPrime(Network.HLayer.Cell[i].Output);
for (int j = 0; j < INPUT_NEURONS; j++) {
DeltaETotalWeight = ErrorTotal * DeltaOutNet*Network.ILayer.Image[j];
Network.HLayer.Cell[i].Weight[j] -= 0.5 * DeltaETotalWeight;
}
}

//Update Weights
_indexOutput = 0;
for (int i = 0; i < OUTPUT_NEURONS; i++) {
for (int j = 0; j < HIDDEN_NEURONS; j++) {
Network.OLayer.Cell[i].Weight[j] = OutputUpdatedWeights[_indexOutput];
_indexOutput++;
}
}}

Как я могу решить эту проблему?
Я не работал над скрытым слоем и смещениями, это из-за этого?
Спасибо

-1

Решение

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

После быстрого просмотра вашего кода, я очень удивлен, что вы вычислили отрицательный дельта-термин? Вы используете ReLU или любую сигмовидную функцию? Я совершенно уверен, что это еще не все. Но я бы посоветовал вам держаться подальше от MNIST, пока у вас не будет сети для решения XOR.

Я написал резюме в псевдокоде о том, как реализовать Backpropagation в псевдокоде. Я уверен, что вы сможете легко перевести его на C ++.

Странное схождение в простой нейронной сети

0

Другие решения

По моему опыту нейронные сети действительно должны быть реализованы с матричными операциями. Это сделает ваш код быстрее и проще для отладки.

Способ отладки обратного распространения заключается в использовании конечной разницы. Для функции потери J(theta) мы можем приблизить градиент в каждом измерении с (J(theta + epsilon*d) - J(theta))/epsilon с d горячий вектор, представляющий одно измерение (обратите внимание на сходство с производной).

https://en.wikipedia.org/wiki/Finite_difference_method

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector