Java 简单神经网络的奇异收敛性
我一直在努力用Java构建一个简单的NN。我在这个项目上断断续续地工作了几个月,我想完成它。我的主要问题是,我不知道如何正确地实现反向传播(所有源代码都使用Python、数学术语,或者过于简单地解释这个想法)。今天我试着自己推断意识形态,我使用的规则是: 权重更新=错误*西格莫迪竞争(错误)*权重本身Java 简单神经网络的奇异收敛性,java,neural-network,convergence,Java,Neural Network,Convergence,我一直在努力用Java构建一个简单的NN。我在这个项目上断断续续地工作了几个月,我想完成它。我的主要问题是,我不知道如何正确地实现反向传播(所有源代码都使用Python、数学术语,或者过于简单地解释这个想法)。今天我试着自己推断意识形态,我使用的规则是: 权重更新=错误*西格莫迪竞争(错误)*权重本身 误差=输出-实际值;(最后一层) 错误=SigmoidePrivative(来自上一层的错误)*将此神经元附加到给出错误的神经元的权重(中间层) 我的主要问题是输出收敛到一个平均值,我的第二个问题
误差=输出-实际值;(最后一层)
错误=SigmoidePrivative(来自上一层的错误)*将此神经元附加到给出错误的神经元的权重(中间层) 我的主要问题是输出收敛到一个平均值,我的第二个问题是权重更新到一个非常奇怪的值。(可能是权重问题导致了收敛) 我想训练的是:对于输入1-9,预期输出是:(x*1.2+1)/10。这只是我随机想到的一条规则。我正在使用结构为1-1-1(3层,1个网络/层)的NN。在下面的链接中,我附加了两次运行:一次我使用的是遵循规则(x*1.2+1)/10的训练集,另一次我使用的是(x*1.2+1)/100。除以10,第一个权重趋于无穷大;除以100后,第二个权重趋于0。我一直在尝试调试它,但我不知道应该查找什么,也不知道出了什么问题。任何建议都将不胜感激。提前谢谢大家,祝大家度过美好的一天 按照上面的规则,我有一个训练样本1->9和它们各自的输出,我运行它们10万次。我每100个纪元记录一次错误,因为用更少的数据点绘图更容易,而9的每个预期输出仍然有1000个数据点。反向传播和权重更新代码:
//for each layer in the Dweights array
for(int k=deltaWeights.length-1; k >= 0; k--)
{
for(int i=0; i<deltaWeights[k][0].length; i++) // for each neuron in the layer
{
if(k == network.length-2) // if we're on the last layer, we calculate the errors directly
{
outputErrors[k][i] = outputs[i] - network[k+1][i].result;
errors[i] = outputErrors[k][i];
}
else // otherwise the error is actually the sum of errors feeding backwards into the neuron currently being processed * their respective weight
{
for(int j=0; j<outputErrors[k+1].length; j++)
{ // S'(error from previous layer) * weight attached to it
outputErrors[k][i] += sigmoidDerivative(outputErrors[k+1][j])[0] * network[k+1][i].emergingWeights[j];
}
}
}
for (int i=0; i<deltaWeights[k].length; i++) // for each neuron
{
for(int j=0; j<deltaWeights[k][i].length; j++) // for each weight attached to that respective neuron
{ // error S'(error) weight connected to respective neuron
deltaWeights[k][i][j] = outputErrors[k][j] * sigmoidDerivative(outputErrors[k][j])[0] * network[k][i].emergingWeights[j];
}
}
}
// we use the learning rate as an order of magnitude, to scale how drastic the changes in this iteration are
for(int k=deltaWeights.length-1; k >= 0; k--) // for each layer
{
for (int i=0; i<deltaWeights[k].length; i++) // for each neuron
{
for(int j=0; j<deltaWeights[k][i].length; j++) // for each weight attached to that respective neuron
{
deltaWeights[k][i][j] *= 1; // previously was learningRate; MSEAvgSlope
network[k][i].emergingWeights[j] += deltaWeights[k][i][j];
}
}
}
return errors;
致:
outputErrors[k][i] = sigmoidDerivative(outputErrors[k+1][j])[0] * network[k+1][i].emergingWeights[j]* outputErrors[k+1][j];
所以我保留了输出错误本身的符号。这修复了第一个权重中的无穷大趋势。现在,在/10跑时,第一个权重趋于0,在/100跑时,第二个权重趋于0。还是希望有人能为我收拾残局(我发现您的代码存在一些问题,例如体重更新不正确。我还强烈建议您通过引入方法来组织代码清理程序 反向传播通常很难有效地实现,但形式定义很容易翻译成任何语言。我不建议您查看学习神经网络的代码。请查看数学并尝试理解这一点。这使您能够更灵活地从头实现一个 我可以通过在伪代码中描述向前和向后传递来给您一些提示 作为一种表示法,我对输入使用
I
,对隐藏层使用j
,对输出层使用k
。然后输入层的偏差是bias\u I
。对于连接一个节点到另一个节点的权重,权重是w\u mn
。激活是a(x)
及其导数a'(x)
向前传球:
for each n of j
dot = 0
for each m of i
dot += m*w_mn
n = a(dot + bias_i)
相同的方法适用于输出层k
和隐藏层j
。因此,对于此步骤,只需将j
替换为k
,将i
替换为j
向后传球:
for each n of j
dot = 0
for each m of i
dot += m*w_mn
n = a(dot + bias_i)
计算输出节点的增量:
for each n of k
d_n = a'(n)(n - target)
这里,target
是预期的输出,n
是当前输出节点的输出。dun
是此节点的增量。
这里需要注意的一点是,logistic函数和tanh函数的导数包含原始函数的输出,不必重新计算这些值。
逻辑函数是f(x)=1/(1+e^(-x))
及其导数f'(x)=f(x)(1-f(x))
。由于每个输出节点n
处的值先前是用f(x)
计算的,因此可以简单地将n(1-n)
作为导数。在上述情况下,这将计算delta如下:
d_n = n(1-n)(n - target)
for each n of j
for each m of k
w_nm -= learning_rate*n*d_m
以相同的方式,计算隐藏节点的增量
for each n of j
d_n = 0
for each m of k
d_n += d_m*w_jk
d_n = a'(n)*d_n
下一步是使用梯度执行权重更新。这是通过一种称为梯度下降的算法完成的。无需详细说明,这可以通过以下方式完成:
d_n = n(1-n)(n - target)
for each n of j
for each m of k
w_nm -= learning_rate*n*d_m
上面的层也是如此。只需将j
替换为i
,将k
替换为j
要更新偏差,只需将连接节点的增量相加,乘以学习率,然后从特定偏差中减去该乘积。谢谢你的回答!我会慢慢浏览你的帖子,并用你的版本更新我的实现。我会用“官方”回复你然后评论。当然。如果你对我的答案有任何疑问,请告诉我。如果我发现错误,我会让你知道并相应地更新答案。快速问题:我记得在网上看到更新应该在每个历元之后进行。因此,对于我的9个示例数据集,我计算了每个示例的权重更新,并得到了平均uPATEM的基础上,然后应用它在一个时代的结束。目前,我正在更新每一个例子后的权重,这是一个问题?另一个问题:在隐藏层的增量代码,你正在做:d'n= a’(x)*dnn。你的意思是“(n))(在中间层的当前神经元的激活的衍生物)?当您更新使用的权重时:w_nm-=学习率md_m此处的“m”表示神经元m的输入(来自输出层)?