【问题标题】:Implementing a perceptron with backpropagation algorithm使用反向传播算法实现感知器
【发布时间】:2012-08-17 23:28:51
【问题描述】:

我正在尝试使用反向传播实现两层感知器来解决奇偶校验问题。该网络有 4 个二进制输入,第一层有 4 个隐藏单元,第二层有 1 个输出。我使用this 作为参考,但在收敛方面遇到问题。

首先,我会注意到我使用 sigmoid 函数进行激活,因此导数是(据我了解)sigmoid(v) * (1 - sigmoid(v))。因此,在计算 delta 值时使用它。

所以,基本上我设置了网络并运行了几个 epoch(遍历每个可能的模式——在这种情况下,16 个输入模式)。在第一个 epoch 之后,权重略有变化。在第二个之后,无论我运行多少个 epoch,权重都不会改变并保持不变。我现在使用 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

【问题讨论】:

  • 几年前我在我的神经网络课程中遇到了一个非常相似的错误:在数十次迭代中值不会改变,然后一切都会在没有明显挑衅的情况下转到NaN 输出。错误最终只是某处的一条错误线,我花了几个小时才发现。您可能应该发布您的代码选择,也许其他人也可以在您的程序中发现我认为的单行错误。 :)
  • 谢谢,我刚刚更新了我的帖子

标签: backpropagation neural-network


【解决方案1】:

我想我发现了问题;有趣的是,我发现的内容在您的高级描述中可见,但我只发现代码中看起来很奇怪。一、说明:

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

我相信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;
        }
    }

我不知道正确的解决方法是什么;但我有两个建议:

  1. 替换这些行:

            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;
    

    += 而不是=。)

  2. 替换这些行:

            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。)

【讨论】:

  • 是的,应该是 += 。我不敢相信我错过了这样的事情。感谢您花时间帮助我,非常感谢!
猜你喜欢
  • 2017-07-12
  • 2014-01-10
  • 2012-04-18
  • 2017-05-12
  • 1970-01-01
  • 2017-09-28
  • 2013-03-04
  • 2019-09-28
相关资源
最近更新 更多