在计算误差导数时,我使用了以下方法,但不确定为什么这样做是正确的。
double errorDerivative = (-output * (1-output) *(desiredOutput - output));
当我去掉第一个输出前的负号时,算法失败并达到最大轮次限制。我认为这是正确的,因为从这个例子中可以看到http://homepages.gold.ac.uk/nikolaev/311imlti.htm没有使用负号运算符。
double errorDerivative2 = (output * (1-output) *(desiredOutput - output));
我目前正在查看并修改一个使用随机梯度下降的现有反向传播实现,我希望将其改为使用标准的反向传播算法。目前,它看起来是这样的。
public void applyBackpropagation(double expectedOutput[]) { // 错误检查,归一化值 ]0;1[ /*for (int i = 0; i < expectedOutput.length; i++) { double d = expectedOutput[i]; if (d < 0 || d > 1) { if (d < 0) expectedOutput[i] = 0 + epsilon; else expectedOutput[i] = 1 - epsilon; } }*/ int i = 0; for (Neuron n : outputLayer) { System.out.println("neuron"); ArrayList<Connection> connections = n.getAllInConnections(); for (Connection con : connections) { double output = n.getOutput(); System.out.println("最终输出是 "+output); double ai = con.leftNeuron.getOutput(); System.out.println("ai 输出是 "+ai); double desiredOutput = expectedOutput[i]; double errorDerivative = (-output * (1-output) *(desiredOutput - output)); double errorDerivative2 = (output * (1-output) *(desiredOutput - output)); System.out.println("误差导数是 "+errorDerivative); System.out.println("我的误差导数是 "+(output * (1-output) *(desiredOutput - output))); double deltaWeight = -learningRate * errorDerivative2; double newWeight = con.getWeight() + deltaWeight; con.setDeltaWeight(deltaWeight); con.setWeight(newWeight + momentum * con.getPrevDeltaWeight()); } i++; } // 更新隐藏层的权重 for (Neuron n : hiddenLayer) { ArrayList<Connection> connections = n.getAllInConnections(); for (Connection con : connections) { double output = n.getOutput(); double ai = con.leftNeuron.getOutput(); double sumKoutputs = 0; int j = 0; for (Neuron out_neu : outputLayer) { double wjk = out_neu.getConnection(n.id).getWeight(); double desiredOutput = (double) expectedOutput[j]; double ak = out_neu.getOutput(); j++; sumKoutputs = sumKoutputs + (-(desiredOutput - ak) * ak * (1 - ak) * wjk); } double partialDerivative = output * (1 - output) * ai * sumKoutputs; double deltaWeight = -learningRate * partialDerivative; double newWeight = con.getWeight() + deltaWeight; con.setDeltaWeight(deltaWeight); con.setWeight(newWeight + momentum * con.getPrevDeltaWeight()); } } }
回答:
抱歉,我没有时间审查你的代码,你需要提出更具体的问题,然后我才能帮助你。
errorDerivative2 能够工作的原因可能是你使用了这样的权重更新规则:deltaW = learningRate*errorDerivative2*input
通常,你所说的 ‘errorDerivative2’ 被称为 delta,对于使用 sigmoid 传输函数的神经元,它被定义为:-output * (1-output) *(desiredOutput - output)
权重更新规则为:deltaW = -learningRate*delta*input
所以,基本原因是你在 errorDerivative2
上没有使用负号,因为你在另一个地方也省略了一个负号..