弹性传播的实现

时间:2013-04-09 10:33:06

标签: neural-network

目前我正在尝试为我的网络实施Resilient Propagation。我是基于encog实现这样做的,但有一件事我不明白:

对于RPROP而言,

The documentation和iRPROP +表示更改> 0:weightChange = -sign(gradient)* delta

第298行和第366行中的

The source code没有减号!

因为我认为两者在某种情况下都是正确的:为什么两者之间存在差异?

关于渐变:我在输出层使用tanh作为激活。这是梯度的正确计算吗?

gradientOutput = (1 - lastOutput[j] * lastOutput[j]) * (target[j] - lastOutput[j]);

2 个答案:

答案 0 :(得分:3)

在重新阅读相关论文并查阅教科书后,我认为此时的编辑文档不正确。为什么不通过在源代码中临时添加减号来试试呢?如果您使用相同的初始权重,您应该收到完全相同的结果,因为文档是正确的。但最后,重要的是你如何使用weightUpdate变量。如果文档的作者用于从权重中减去weightUpdate而不是添加它,那么这将起作用。

编辑:我在原始答案中重新审视了有关渐变计算的部分。

首先,这里简要说明如何设想输出图层中权重的渐变。首先,计算输出与目标值之间的误差。

你现在要做的是“责备”前一层中活跃的神经元。想象一下输出神经元说“嗯,我这里有错误,谁负责?”。负责任的是前一层的神经元。根据输出与目标值相比太小或太大,它将增加或减少前一层中每个神经元的权重,具体取决于它们的活动程度。

x是隐藏层中神经元的激活。

o是输出神经元的激活。

φ是输出神经元的激活函数,φ'是它的导数。

Edit2 :更正了以下部分。增加了反向传播的矩阵式计算。

每个输出神经元j的错误是:

(1)δ out,j =φ'(o j )(t - o j

连接隐藏神经元i和输出神经元j的权重的梯度:

(2)grad i,j = x i out,j

每个隐藏神经元i的反向传播误差,权重为w:

(3)δ hid,i =φ'(x)*Σw i,j out,j

通过重复应用公式2和3,您可以反向传播到输入图层。

关于一个培训样本

写入循环

每个输出神经元j的错误是:

for(int j=0; j < numOutNeurons; j++) {
  errorOut[j] = activationDerivative(o[j])*(t[j] - o[j]);
}

连接隐藏神经元i和输出神经元j的权重的梯度:

for(int i=0; i < numHidNeurons; i++) {
  for(int j=0; j < numOutNeurons; j++) {
    grad[i][j] = x[i] * errorOut[j]        
  }      
}

每个隐藏神经元的反向传播错误i:

for(int i=0; i < numHidNeurons; i++) {
  for(int j=0; j < numOutNeurons; j++) {
    errorHid[i] = activationDerivative(x[i]) * weights[i][j] * errorOut[j]        
  }      
}

在没有卷积的完全连接的多层感知器或类似的东西中,您可以使用标准矩阵操作,这要快得多。

假设您的每个样本都是输入矩阵中的一行,而列是其属性,您可以通过网络传播输入,如下所示:

activations[0] = input;
for(int i=0; i < numWeightMatrices; i++){
  activations[i+1] = activations[i].dot(weightMatrices[i]);
  activations[i+1] = activationFunction(activations[i+1]);
}
然后

反向传播:

n = numWeightMatrices;
error = activationDerivative(activations[n]) * (target - activations[n]);
for (int l=n-1; l >= 0; l--){
  gradient[l] = activations[l].transposed().dot(error);
  if (l > 0) {
     error = error.dot(weightMatrices[l].transposed());
     error = activationDerivative(activations[l])*error;
  }
}

我在上面的解释中省略了偏倚神经元。在文献中,建议将偏倚神经元建模为每个激活矩阵中的附加列,其总是1.0。您将需要处理一些切片分配。使用矩阵反向传播循环时,不要忘记在每一步之前将偏差位置的误差设置为0!

答案 1 :(得分:0)

private float resilientPropagation(int i, int j){
    float gradientSignChange = sign(prevGradient[i][j]*gradient[i][j]);
    float delta = 0;
    if(gradientSignChange > 0){
        float change = Math.min((prevChange[i][j]*increaseFactor), maxDelta);
        delta = sign(gradient[i][j])*change;
        prevChange[i][j] = change;
        prevGradient[i][j] = gradient[i][j];
    }
    else if(gradientSignChange < 0){
        float change = Math.max((prevChange[i][j]*decreaseFactor), minDelta);
        prevChange[i][j] = change;
        delta = -prevDelta[i][j];
        prevGradient[i][j] = 0;
    }
    else if(gradientSignChange == 0){
        float change = prevChange[i][j];
        delta = sign(gradient[i][j])*change;
        prevGradient[i][j] = gradient[i][j];
    }
    prevDelta[i][j] = delta;
    return delta;       
}


gradient[i][j] = error[j]*layerInput[i];
weights[i][j]= weights[i][j]+resilientPropagation(i,j);