Я делаю свою первую сверточную нейронную сеть и пытаюсь узнать, как работает обратное распространение. Я нашел страницу википедии о обратном распространении: https://en.wikipedia.org/wiki/Backpropagation и ввел формулы в конце «Поиск производной от ошибки» в моем коде, и, похоже, он работает с нейронной сетью с 1 выходной слой, но не более 1 выходного слоя.
Я думаю, что вычисление производной выходного слоя неверно, но я не знаю, какова правильная формула.
Я использую База данных MNIST в качестве тренировочный набор, поэтому у меня есть нейронная сеть с 28 * 28
входными нейронами, скрытым слоем 28
нейронов и выходным слоем 10
, (0-9).
Это то, что мое обратное распространение код выглядит для каждого нейрона:
if (layer == structure.size() - 1) {
// This must be the differentiated error / loss function (I think)
// I think this is the problem. I have tried to replace "loss" with the expected output of each neuron,
//but it did not work either.
double derivative = (currentNeuron.out - loss) * currentNeuron.out
* (1 - currentNeuron.out);
currentNeuron.derivatives = new double[] { derivative };
} else {
// Set the derivative for every weigth of a neuron
double[] derivatives = new double[currentNeuron.weights.length];
for (int weight = 0; weight < currentNeuron.weights.length; weight++) {
// Calculate the derivative of one weight
// Calculate the weighted sum including all derivatives of the neuron in l + 1
double weightedSumDerivatives = 0;
for (int nextNeuronDerivative = 0; nextNeuronDerivative < structure.get(layer + 1)
.get(weight).derivatives.length; nextNeuronDerivative++) {
weightedSumDerivatives += currentNeuron.weights[nextNeuronDerivative]
* structure.get(layer + 1).get(weight).derivatives[nextNeuronDerivative];
}
double derivative = weightedSumDerivatives * currentNeuron.out * (1 - currentNeuron.out);
derivatives[weight] = derivative;
}
currentNeuron.derivatives = derivatives;
}
Вот так выглядит мой класс нейронов:
public class Neuron {
protected double[] weights;
protected double out;
protected double derivatives[];
public Neuron(double[] weights) {
this.weights = weights;
}
}
Потери рассчитываются следующим образом:
double loss = 0;
for(int i = 0; i < out.length; i++) {
loss += Math.pow(out[i] - correctAnswer[i], 2);
}
loss /= out.length;
correctAnswer - это массив длиной 10, где каждый элемент равен 0, за исключением правильного ответа 1
Как мне изменить функцию потери?
Заранее спасибо
Редактировать : Как вы можете видеть в моем коде, я не изменяю веса нейронов непосредственно после их вычисления, но я применяю все изменения после того, как все производные вычислены. Если это тоже не так, пожалуйста, скажите мне.
Я даже пытался тренировать нейронную сеть по всему набору (60000 изображений), но он все равно дал ту же тра sh, что и раньше