弹性反向传播中的错误?

我在正确实现弹性传播方面遇到了困难。我已经实现了反向传播算法来训练神经网络,对于XOR网络,它按预期工作,大约需要600个周期将误差降至1%以下。现在我尝试为相同的问题实现弹性传播(http://en.wikipedia.org/wiki/Rprop),在最初的几个周期内,误差迅速下降到23%,但随后上升到50%并停留在那里。
我按照http://www.heatonresearch.com/book/introduction-neural-network-math.html中的描述精确实现了它,但那是一个令人困惑的描述:它与维基百科的Rprop页面以及由同一作者编写的encog中的实现不同,据我所知。我还尝试了不同来源的不同实现,但都没有成功。

不同来源之间的某些差异包括:

  • 在计算权重变化时使用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();}@Overridepublic 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;}

相同的方法在普通的反向传播中运行良好:

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

回答:

RPROP算法有几种不同的变体。自从书籍出版以来,Encog已经进行了修改以支持更多变体。书籍专注于Reidmiller论文中定义的经典RPROP。后续论文提出了其他算法。这解释了Encog的优化RPROP算法与书中描述的某些差异。

查看您上面的代码,我有一些建议可能会有所帮助。我主要不确定您的最终else子句。您有”double weightChange = 0″,这将不起作用。我认为您需要删除double。您还需要为“零”设定一些容忍度。梯度的变化很少会精确地达到零,所以我会为else子句设定一个关于零的范围,可能从-0.00001到+0.00001。然后确保您实际上将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

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

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注