我正在尝试通过反向传播实现两层感知器,以解决奇偶校验问题。网络有4个二进制输入,第一层有4个隐藏单元,第二层有1个输出。我正在使用this作为引用,但是在收敛方面遇到了问题。
首先,我将注意到我正在使用Sigmoid函数进行激活,因此(从我的理解中)导数为Sigmoid(v)*(1-sigmoid(v))。因此,用于计算增量值。
因此,基本上,我设置了网络并运行了几个纪元(遍历每种可能的模式-在这种情况下,输入的是16种模式)。在第一个时期之后,权重会稍有变化。在第二秒之后,权重不会改变并保持不变,所以无论我运行多少个纪元。我现在使用的学习率为0.1,偏差为+1。
下面是伪代码中的网络训练过程(根据我检查过的消息源,我认为这是正确的):
前馈步骤:
v = SUM[weight connecting input to hidden * input value] + bias
y = Sigmoid(v)
set hidden.values to y
v = SUM[weight connecting hidden to output * hidden value] + bias
y = Sigmoid(v)
set output value to y
输出层的反向传播:
error = desired - output.value
outputDelta = error * output.value * (1 - output.value)
隐藏层的反向传播:
for each hidden neuron h:
error = outputDelta * weight connecting h to output
hiddenDelta[i] = error * h.value * (1 - h.value)
更新权重:
for each hidden neuron h connected to the output layer
h.weight connecting h to output = learningRate * outputDelta * h.value
for each input neuron x connected to the hidden layer
x.weight connecting x to h[i] = learningRate * hiddenDelta[i] * x.value
当然,该过程在各个时期之间循环,并且权重变化持续存在。因此,我的问题是,在第二个时期之后,权重保持恒定有什么原因吗?如有必要,我可以发布代码,但是目前,我希望我可以忽略一些明显的事情。谢谢大家!
编辑:这是sarnold建议的到我的代码的链接:
MLP.java:http://codetidy.com/1903
Neuron.java:http://codetidy.com/1904
Pattern.java:http://codetidy.com/1905
input.txt:http://codetidy.com/1906
最佳答案
我想我发现了问题。有趣的是,我发现的内容在您的高级描述中可见,但是我只发现代码中看起来很奇怪的内容。一,说明:
我相信h.weight
应该相对于先前的重量进行更新。您的更新机制仅根据学习率,输出增量和节点的值进行设置。类似地,还根据学习率,隐藏增量和节点的值来设置x.weight
:
/*** Weight updates ***/
// update weights connecting hidden neurons to output layer
for (i = 0; i < output.size(); i++) {
for (Neuron h : output.get(i).left) {
h.weights[i] = learningRate * outputDelta[i] * h.value;
}
}
// update weights connecting input neurons to hidden layer
for (i = 0; i < hidden.size(); i++) {
for (Neuron x : hidden.get(i).left) {
x.weights[i] = learningRate * hiddenDelta[i] * x.value;
}
}
我不知道什么是正确的解决方案。但我有两个建议:
h.weights[i] = learningRate * outputDelta[i] * h.value;
x.weights[i] = learningRate * hiddenDelta[i] * x.value;
这些行:
h.weights[i] += learningRate * outputDelta[i] * h.value;
x.weights[i] += learningRate * hiddenDelta[i] * x.value;
(
+=
而不是=
。) h.weights[i] = learningRate * outputDelta[i] * h.value;
x.weights[i] = learningRate * hiddenDelta[i] * x.value;
这些行:
h.weights[i] *= learningRate * outputDelta[i];
x.weights[i] *= learningRate * hiddenDelta[i];
(忽略该值,仅调整现有权重即可。对于此更改,学习率应为
1.05
而不是.05
。)关于backpropagation - 用反向传播算法实现感知器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9169280/