我创建了一个程序,可以创建任意大小/长度的灵活神经网络,但是我正在使用XOR设置的简单结构(前馈,Sigmoid激活,反向传播,无批处理)对其进行测试。
编辑:以下是我没有提供足够信息的原始问题的全新方法
编辑2:我开始在-2.5到2.5之间权重,并修复了我的代码中忘记了一些负面因素的问题。现在,对于所有情况,收敛为0,或者对于所有情况,收敛为1,而不是0.5
一切都按照我认为的方式工作,但是它趋向于0.5,而不是在0和1的输出之间振荡。我已经完全通过并手工计算了整个前馈/计算增量误差/后向支撑的设置./等,它与我从程序中得到的匹配。我还尝试过通过更改学习率/动量来优化它,以及增加网络的复杂性(更多神经元/层)。
因此,我假设我的方程式之一是错误的,或者在我的神经网络中我还有其他误解。以下是我对每个步骤都遵循的方程式的逻辑:
我有一个带有两个输入和一个偏置的输入层,一个带有2个神经元和一个偏置的隐藏层,以及带有1个神经元的输出。
取两个输入神经元和偏向神经元各自的输入,然后将它们乘以它们各自的权重,然后将它们加在一起作为隐藏层中两个神经元中每个神经元的输入。
取得每个隐藏神经元的输入,使其通过Sigmoid激活函数(参考文献1),并将其用作神经元的输出。
取隐藏层中每个神经元的输出(偏差为1),将它们乘以各自的权重,然后将这些值添加到输出神经元的输入中。
通过Sigmoid激活函数传递输出神经元的输入,并将其用作整个网络的输出。
计算输出神经元的Delta误差(参考2)
计算2个隐藏神经元各自的Delta误差(参考3)
计算每个权重的梯度(参考4)(从头开始并向后计算)
计算每个重量的增量重量(参考5),并将其添加到其值中。
通过更改输入和预期输出重新开始过程(参考文献6)
以下是对方程式/过程的引用的详细信息(这可能是我的问题所在!):
x是神经元的输入:(1/(1 + Math.pow(Math.E, (-1 * x))))
-1*(actualOutput - expectedOutput)*(Sigmoid(x) * (1 - Sigmoid(x))//Same sigmoid used in reference 1
SigmoidDerivative(Neuron.input)*(The sum of(Neuron.Weights * the deltaError of the neuron they connect to))
ParentNeuron.output * NeuronItConnectsTo.deltaError
learningRate*(weight.gradient) + momentum*(Previous Delta Weight)
我有一个arrayList,其中的值依次为0,1,1,0
。它采用第一对(0,1)
,然后期望为1
。对于第二次,它使用第二对(1,1)
并期望0
。它只是不断迭代每个新集合的列表。也许以这种系统的方式训练它会导致问题?
就像我之前说过的那样,他们之所以认为我不认为这是代码问题,是因为它与我用纸和铅笔计算出的结果完全匹配(如果出现编码错误,则不会发生)。
另外,当我第一次初始化权重时,会给它们一个介于0和1之间的随机double值。本文建议这样做可能会导致问题:Neural Network with backpropogation not converging
可以吗?我使用了n ^(-1/2)规则,但是并没有解决它。
如果我可以更具体,或者您想要其他代码,请告诉我,谢谢!
最佳答案
这是错的
SigmoidDerivative(Neuron.input)*(((Neuron.Weights *它们连接的神经元的deltaError的总和))
首先是乙状结肠激活(g)
第二个是乙状结肠激活的导数
private double g(double z) {
return 1 / (1 + Math.pow(2.71828, -z));
}
private double gD(double gZ) {
return gZ * (1 - gZ);
}
不相关的注释:您使用的(-1 * x)表示法确实很奇怪,只需使用-x
从如何表达ANN步骤的角度看,您的实现似乎很差。尝试着重于实现Forward / BackPropogation,然后实现UpdateWeights方法。
创建一个矩阵类
这是我的Java实现,非常简单,有些粗糙。我使用Matrix类使其背后的数学代码看起来非常简单。
如果您可以用C ++编写代码,则可以使运算符重载,这将使更容易编写可理解的代码。
https://github.com/josephjaspers/ArtificalNetwork/blob/master/src/artificalnetwork/ArtificalNetwork.java
这是算法(C ++)
所有这些代码都可以在我的github上找到(神经网络既简单又功能齐全)
每层都包含偏置节点,这就是为什么存在偏移的原因
void NeuralNet::forwardPropagation(std::vector<double> data) {
setBiasPropogation(); //sets all the bias nodes activation to 1
a(0).set(1, Matrix(data)); //1 to offset for bias unit (A = X)
for (int i = 1; i < layers; ++i) {
// (set(1 -- offsets the bias unit
z(i).set(1, w(i - 1) * a(i - 1));
a(i) = g(z(i)); // g(z ) if the sigmoid function
}
}
void NeuralNet::setBiasPropogation() {
for (int i = 0; i < activation.size(); ++i) {
a(i).set(0, 0, 1);
}
}
outLayer D = A-Y(y是输出数据)
hiddenLayers d ^ l =(w ^ l(T)* d ^ l + 1)*:gD(a ^ l)
d =导数向量
W =权重矩阵(长度=连接,宽度=特征)
a =激活矩阵
gD =导数函数
^ l =不具备权力(这仅表示在l层)
=点积
*:=相乘(将每个元素“直通”相乘)
cpy(n)返回偏移n的矩阵副本(忽略n行)
void NeuralNet::backwardPropagation(std::vector<double> output) {
d(layers - 1) = a(layers - 1) - Matrix(output);
for (int i = layers - 2; i > -1; --i) {
d(i) = (w(i).T() * d(i + 1).cpy(1)).x(gD(a(i)));
}
}
解释这些代码可能会使图像混乱,因此我发送此链接(我认为是很好的来源),其中还包含对BackPropagation的解释,可能比我自己的解释更好。
http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html
void NeuralNet::updateWeights() {
// the operator () (int l, int w) returns a double reference at that position in the matrix
// thet operator [] (int n) returns the nth double (reference) in the matrix (useful for vectors)
for (int l = 0; l < layers - 1; ++l) {
for (int i = 1; i < d(l + 1).length(); ++i) {
for (int j = 0; j < a(l).length(); ++j) {
w(l)(i - 1, j) -= (d(l + 1)[i] * a(l)[j]) * learningRate + m(l)(i - 1, j);
m(l)(i - 1, j) = (d(l + 1)[i] * a(l)[j]) * learningRate * momentumRate;
}
}
}
}
关于java - XOR神经网络(FF)收敛到0.5,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39523744/