用反向传播算法实现感知器

Aar*_*ron 5 backpropagation neural-network

我试图用反向传播实现一个双层感知器来解决奇偶校验问题.网络有4个二进制输入,第一层有4个隐藏单元,第二层有1个输出.我使用作为参考,但遇到了收敛问题.

首先,我将注意到我使用sigmoid函数进行激活,因此衍生物(根据我的理解)sigmoid(v)*(1 - sigmoid(v)).因此,在计算delta值时使用.

所以,基本上我设置网络并运行几个时期(遍历每个可能的模式 - 在这种情况下,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
Run Code Online (Sandbox Code Playgroud)

输出层的反向传播:

error = desired - output.value  
outputDelta = error * output.value * (1 - output.value)
Run Code Online (Sandbox Code Playgroud)

隐藏层的反向传播:

for each hidden neuron h:  
error = outputDelta * weight connecting h to output  
hiddenDelta[i] = error * h.value * (1 - h.value)
Run Code Online (Sandbox Code Playgroud)

更新权重:

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
Run Code Online (Sandbox Code Playgroud)

这个过程当然是通过时代循环的,并且体重变化仍然存在.所以,我的问题是,是否有任何理由在第二个时代之后权重保持不变?如果有必要,我可以发布我的代码,但此刻我希望有一些明显的东西我可以忽略.谢谢大家!

编辑:这是链接到我的代码由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

sar*_*old 4

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

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
Run Code Online (Sandbox Code Playgroud)

我认为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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

  1. 替换这些行:

            h.weights[i] = learningRate * outputDelta[i] * h.value;
            x.weights[i] = learningRate * hiddenDelta[i] * x.value;
    
    Run Code Online (Sandbox Code Playgroud)

    用这些行:

            h.weights[i] += learningRate * outputDelta[i] * h.value;
            x.weights[i] += learningRate * hiddenDelta[i] * x.value;
    
    Run Code Online (Sandbox Code Playgroud)

    +=代替=。)

  2. 替换这些行:

            h.weights[i] = learningRate * outputDelta[i] * h.value;
            x.weights[i] = learningRate * hiddenDelta[i] * x.value;
    
    Run Code Online (Sandbox Code Playgroud)

    用这些行:

            h.weights[i] *= learningRate * outputDelta[i];
            x.weights[i] *= learningRate * hiddenDelta[i];
    
    Run Code Online (Sandbox Code Playgroud)

    (忽略该并简单地缩放现有权重。学习率应该1.05代替.05此更改。)