Artificial intelligence 弹性反向传播中的Bug?

Artificial intelligence 弹性反向传播中的Bug?,artificial-intelligence,neural-network,backpropagation,encog,Artificial Intelligence,Neural Network,Backpropagation,Encog,我正在努力正确地实现弹性传播。我已经实现了反向传播算法来训练神经网络,它的工作原理与XOR网络的预期一样,即大约需要600个纪元才能将误差降至1%以下。现在,我尝试为同样的问题实现弹性传播(),在最初的几个时期,错误迅速下降到23%,但随后上升到50%,并保持不变 我完全按照中的描述实现了它,但这是一个令人费解的描述:它不同于wikipedia Rprop页面和encog中的实现,据我所知,encog是由与本书相同的作者编写的。 我还尝试了来自不同来源的不同实现,但没有任何效果。 不同来源之间的

我正在努力正确地实现弹性传播。我已经实现了反向传播算法来训练神经网络,它的工作原理与XOR网络的预期一样,即大约需要600个纪元才能将误差降至1%以下。现在,我尝试为同样的问题实现弹性传播(),在最初的几个时期,错误迅速下降到23%,但随后上升到50%,并保持不变
我完全按照中的描述实现了它,但这是一个令人费解的描述:它不同于wikipedia Rprop页面和encog中的实现,据我所知,encog是由与本书相同的作者编写的。 我还尝试了来自不同来源的不同实现,但没有任何效果。

不同来源之间的一些差异:

使用signum(CurrentPartialDelivative)代替signum(CurrentPartialDelivative*PreviousPartialDelivative)计算权重变化
  • 使用上一次重量变化,而不是新重量变化的新更新值
  • 首先计算重量变化,然后计算新的更新值 正确的实施方式是什么?随后,根据该书实施:

    public ResilientPropagation() {
        initialUpdateValue = 0.01;
        deltaMaximum = 50;
        deltaMinimum = 0.000001;
        negativeEta = 0.5;
        positiveEta = 1.2;
        double zeroTolerance = 0.0000000000000001;
        signum = new Signum(zeroTolerance);
    
        init();
    }
    
    @Override
    public double calculateWeightChange(Synapse synapse, double partialDerivative) {
        if (!synapseValues.containsKey(synapse)){
            double initialPartialDerivative = 0;
            synapseValues.put(synapse, new SynapseValues(initialUpdateValue, initialPartialDerivative));
        }
    
        SynapseValues values = synapseValues.get(synapse);
        double signChange = signum.value(values.lastPartialDerivative * partialDerivative);
        values.lastPartialDerivative = partialDerivative;
        double weightChange = 0;
        if (signChange > 0){
            newUpdateValue = Math.min(positiveEta * values.updateValue, deltaMaximum);
            weightChange = -1*newUpdateValue;
        } else if (signChange < 0){
            newUpdateValue = Math.max(negativeEta * values.updateValue, deltaMinimum);
            weightChange = newUpdateValue;
        } else {
            newUpdateValue = values.updateValue;
            double weightChange = 0;
        }
        values.updateValue = newUpdateValue;
        return weightChange;
    }
    

    RPROP算法有几种不同的变体。自本书出版以来,Encog已被修改以支持更多的功能。这本书的重点是经典的RPROP,正如Reimiller的一篇论文所定义的那样。随后的论文提出了额外的算法。这就解释了Encog的优化RPROP算法与书中描述的算法之间的一些差异

    看看上面的代码,我有一些建议可能会有所帮助。大多数情况下,我对你最后的else条款没有把握。您有“double weightChange=0”,这将不起任何作用。我想你得把这双鞋拆了。您还需要为“零”设置一些公差。梯度的变化很少精确地达到零,所以我会建立一些关于零的范围,可能-0.00001到+0.00001,以便else子句触发。然后确保您实际将weightChange设置为零

    我从自己的rprop实现中记得的另一个问题是,用于反向传播的梯度的符号是用于反向传播的梯度的逆符号。您可以尝试翻转RPROP的梯度符号,这在我的Encog实现中是必要的

    RPROP的这个实现可能对您有用,它是典型的Reimiller实现。它确实工作正常,误差收敛


    不确定这是否有帮助。在不运行代码的情况下,我看到的就是这些。

    thx以获取帮助。问题是我没有改变梯度符号。关于你的答案还有一些其他的注意事项:我确实有一个零容忍度,你可以在上面的构造函数中看到它(它的大小来自你的书10^-16),如果signumValue=0,权重变化必须为零(根据你的书和维基百科,编码不同)。最后但并非最不重要的一点:赞美你的书,它们真的很有帮助,特别是对这个领域的新手,准确地描述你必须做什么,并展示它如何工作的具体例子。
    @Override
    public double calculateWeightChange(Synapse synapse, double partialDerivative) {
        double previousChange = previousWeightChange.get(synapse) != null ? previousWeightChange.get(synapse) : 0;
        double weightChange = learningRate * partialDerivative + momentum * previousChange;
        previousWeightChange.put(synapse, weightChange);
        return weightChange;
    }