弹性反向传播中的错误?

时间:2014-12-06 17:01:59

标签: artificial-intelligence neural-network backpropagation encog

我正在努力正确实施Resilient Propagation。我已经实现了反向传播算法来训练神经网络,并且它按照XOR-Net的预期工作,即大约需要600个Epoch才能将误差降低到1%以下。现在我尝试对同样的问题实施弹性传播(http://en.wikipedia.org/wiki/Rprop),并且前几个时期错误迅速下降到23%但随后提高到50%并保持在那里。
我完全按照http://www.heatonresearch.com/book/introduction-neural-network-math.html中的描述实现了它,但这是一个令人费解的描述:它与维基百科的Rprop-Page和来自同一作者的书中的实现不同,就我而言知道。 我也已经尝试过不同来源的不同实现,但没有任何效果。

各种来源之间的一些差异:

  • 使用signum(currentPartialDerivative)代替signum(currentPartialDerivative * previousPartialDerivative)计算体重变化
  • 使用最后一次体重变化,而不是新体重变化的新更新值
  • 首先计算体重变化,然后计算新的更新值

实现这个的正确方法是什么?随后按照书中的实施:

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;
}

正常的反向传播的相同方法可以正常工作:

@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;
}

1 个答案:

答案 0 :(得分:1)

RPROP算法有几种不同的变体。自本书出版以来,Encog已被修改为支持更多。本书侧重于经典的RPROP,由Reidmiller的论文定义。随后的论文提出了额外的算法。这解释了Encog的优化RPROP算法与本书描述的内容之间的一些差异。

查看上面的代码,我有一些建议可能有所帮助。大多数情况下,我不确定你的最后一个条款。你有&#34; double weightChange = 0&#34;,它什么都不做。我认为你需要删除双倍。你还需要为什么&#34;零&#34;建立一些容忍度。是。渐变的变化很少会精确地达到零,所以我会建立一个大约零的范围,可能是-0.00001到+0.00001,因为要触发的else子句。然后确保你实际上将weightChange设置为零。

我从自己的rprop实现中回忆起的另一个问题是,用于反向传播的梯度的符号是用于反向传播的梯度的反转符号。您可以尝试翻转RPROP的渐变符号,这在我的Encog实现中是必需的。

这种RPROP实现可能对您有用,它是经典的Reidmiller实现。它运行正常,误差收敛。

https://github.com/encog/encog-java-core/blob/master/src/main/java/org/encog/neural/freeform/training/FreeformResilientPropagation.java

不确定这是否有帮助。没有运行代码,这就是我所看到的。