2016-09-16 138 views
0

我创建了一个程序,允许我创建灵活的任意大小/长度的神经网络,但是我使用XOR设置的简单结构来测试它(前馈,乙状结肠激活,反向传播,不配料)。XOR神经网络(FF)收敛到0.5

编辑:下面是一个全新的方法我原来的问题,其并没有提供足够的信息

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

一切的工作正是我THINK应该的方式,但它是0输出和之间的融合,而不是摆向0.5的方向, 1.我已经完全掌握并计算了一个完整的前馈/计算增量误差/后向支持/等的设置,并且它与我从程序中获得的结果相匹配。我也尝试通过改变学习速率/动量来优化它,并且增加网络中的复杂性(更多神经元/层)。因此,我假定我的任一方程是错误的,或者在我的神经网络中有其他一些误解。以下是我遵循的每一步公式的逻辑:

我有一个输入层,有两个输入和一个偏差,一个隐藏2个神经元和一个偏差,以及一个带1个神经元的输出。

  1. 采取输入从两个输入神经元和神经元偏压的,然后通过各自的权重相乘它们,然后一起添加它们作为输入用于每个隐藏层的两个神经元的。
  2. 取出每个隐藏的神经元的输入,将其通过乙状结肠激活功能(参考)并将其用作神经元的输出。
  3. 取隐藏层中每个神经元的输出(偏差为1),将它们乘以它们各自的权重,并将这些值添加到输出神经元的输入。
  4. 通过Sigmoid激活函数传递输出神经元的输入,并将其用作整个网络的输出。
  5. 计算为输出神经元
  6. 德尔塔错误(参考)计算德尔塔错误(参考)对于每个2个隐藏神经元
  7. 计算的梯度(参考)对于每个重量(从结束和工作开始)
  8. 计算每个权重的Delta Weight(参考),并将其加到其值中。
  9. 在由启动过程与更改输入和预期输出(参考)

下面是公式/过程(这些引用这可能是我的问题的细节!):

  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。它只是遍历每个新集合的列表。也许以这种系统的方式进行培训会导致问题?

就像我之前说,他们的理由,我不认为这是一个代码问题,是因为它匹配的正是我曾与纸和铅笔(如果有一个编码错误,就不会发生)来计算。

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

如果我可以更具体或想要其他代码让我知道,谢谢!

+1

简短的摘要:我有一大堆的代码,我没有表现,因为我敢肯定它是正确的。但有些东西不起作用。怎么了? – Henry

+0

@亨利是的,我很抱歉,但我不知道从哪里开始。它是三个类的组合,每个类都有几百行代码。然而,一个朝0.5的神经网络是一个非常具体的问题,我希望有人至少有一个方向让我开始寻找。我会添加我的deltaerror和梯度代码,因为这不太长 – MarshallD

+0

@Henry我只是完全重新提供了更多的信息和解释区域的问题。希望你可以重新评估?谢谢! – MarshallD

回答

1

这是错误的

SigmoidDerivative(Neuron.input)*((Neuron.Weights的总和*神经元的deltaError它们连接到)) 首先被激活乙状结肠(克) 第二是衍生物的乙状结肠激活

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


下面是

所有这些代码可以在我的github中发现的算法(C++)(神经网是简单和泛函) 每个层包括偏置节点,这就是为什么有偏移

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 6升=(W^L(T)* d^L + 1)*:Gd(上一^升)

d =衍生物矢量

W =权重矩阵(长度=连接,宽度=特征)

一个激活=矩阵

的gD =衍生物功能

^L = IS NOT功率(这只是意味着在层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; 
      } 
     } 
    } 
} 
+0

感谢您的回答!然而,在执行g和gD之后,我仍然有类似的问题。现在它更快地收敛很多,但它仍然只有1或只有0,然后不久后进入NaN(0和1)。 – MarshallD

+0

对于迟到的回复,抱歉抱歉。关于你在融合当地最低标准方面的问题。这实际上发生在所有神经网络中。 例如,如果您将所有权重设置为与随机初始化相反的常数,那么在遍历数据集时,每个权重会在相同方向上非常轻微地调整(“移动”)。 这就是当你陷入局部最小值时发生的情况。许多神经网络甚至需要多次重新运行,直到找到足够的最小值(无论是局部最优还是最优)。 – Jjoseph

+0

如果不是一致地优化,您可以向隐藏层添加更多节点。您可以测试这是如何通过Xor网络2-2-1增加优化机会的,相比之下可能是2-10-1(节点的增加减少了他们的权重开始变得接近彼此的机会) 您得到的事实南方误差意味着你的三角洲很可能没有被正确计算,或者你有一个负面的符号,你可能忘记了或者错误地添加了(如果错误接近0,那么权重应该几乎没有变化)。您可以尝试使用舍入方法处理此问题。 – Jjoseph