XOR神经网络(FF)收敛到0.5

时间:2016-09-16 04:28:05

标签: java neural-network xor

我创建了一个程序,允许我创建任意大小/长度的灵活神经网络,但是我使用XOR设置的简单结构对其进行测试(前馈,Sigmoid激活,反向传播) ,没有批处理)。

编辑:以下是我原始问题的一种全新方法,它没有提供足够的信息

编辑2:我的体重在-2.5和2.5之间,并在我的代码中修复了一个问题,我忘记了一些否定。现在它对于所有情况收敛为0或对所有情况收敛为1,而不是0.5

一切都按照我 THINK 的方式完成,但它会向0.5收敛,而不是在0和1的输出之间振荡。我已经完全通过并手工计算了整个前馈/计算delta错误/后支柱等的设置,它与我从程序中得到的相匹配。我也尝试通过改变学习速度/动量来优化它,以及增加网络的复杂性(更多的神经元/层)。

因此,我认为我的方程式中的任何一个都是错误的,或者我的神经网络中存在其他一些误解。以下是我遵循每个步骤的方程逻辑:

我的输入层有两个输入和一个偏置,一个隐藏有2个神经元和一个偏置,一个输出有一个神经元。

  1. 从两个输入神经元和偏置神经元中的每一个获取输入,然后将它们乘以各自的权重,然后将它们作为隐藏层中两个神经元中每个神经元的输入相加。
  2. 获取每个隐藏神经元的输入,通过 Sigmoid激活函数(参考 1 )并将其用作神经元的输出。
  3. 获取隐藏层中每个神经元的输出(偏差为1),将它们乘以各自的权重,并将这些值添加到输出神经元的输入中。
  4. 通过Sigmoid激活功能传递输出神经元的输入,并将其用作整个网络的输出。
  5. 计算输出神经元的 Delta Error (参考 2
  6. 为2个隐藏神经元
  7. 中的每一个计算 Delta Error (参考 3
  8. 计算每个重量的渐变(参考 4 )(从结束和返工开始)
  9. 计算每个重量的 Delta Weight (参考 5 ),并将其添加到其值中。
  10. 通过更改输入和预期输出开始此过程(参考 6
  11. 以下是对方程式/过程的引用的具体细节(这可能是我的问题所在!):

    1. x是神经元的输入:(1/(1 + Math.pow(Math.E, (-1 * x))))
    2. -1*(actualOutput - expectedOutput)*(Sigmoid(x) * (1 - Sigmoid(x))//Same sigmoid used in reference 1
    3. SigmoidDerivative(Neuron.input)*(The sum of(Neuron.Weights * the deltaError of the neuron they connect to))
    4. ParentNeuron.output * NeuronItConnectsTo.deltaError
    5. learningRate*(weight.gradient) + momentum*(Previous Delta Weight)
    6. 我按顺序在其中有一个值为0,1,1,0的arrayList。它需要第一对(0,1),然后需要1。第二次,它需要第二对(1,1),并期望0。它只是在每个新集的列表中进行迭代。或许以这种系统的方式训练它会导致问题吗?
    7. 就像我之前说过的那样,他们之所以认为我不认为它的代码问题是因为它与我用纸和笔计算的完全一致(如果有的话,这不会发生。编码错误)。

      当我第一次初始化我的权重时,我给它们一个0到1之间的随机双值。本文认为这可能会导致问题:Neural Network with backpropogation not converging 可能是吗? 我使用了n ^( - 1/2)规则,但没有修复它。

      如果我可以更具体或您想要其他代码,请告诉我,谢谢!

1 个答案:

答案 0 :(得分:1)

这是错误的

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

您从如何表达人工神经网络的步骤开始实施似乎很差。尝试着重于实现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 =不是力量(这仅仅意味着在第一层)

  • = dotproduct

*:=乘(将每个元素乘以“到”)

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