使用反向传播训练的神经网络解决了 AND , Or 但没有解决 XOR

Neural Network trained using back propagation solves AND , Or but doesn't solve XOR

我已经实施反向传播算法来训练我的神经网络。它完美地解决了 AND & OR,但是当我尝试训练解决 XOR 时,总错误率真的很高。

异或网络的网络拓扑结构为:输入层2个神经元,隐藏层2个神经元,输出层1个神经元。

我使用 sigmoid 作为我的激活函数,并使用加权和作为输入。

这是我负责反向传播的代码部分:

  protected void updateOutputLayer(double[] outputErr)
    {

        double delta;
        Neuron neuron;
        double errorDerivative;
        for ( int i=0;i<this.getNeuralNetwork().getOutputLayer().getSize();i++)
        {
            neuron=this.getNeuralNetwork().getOutputLayer().getAt(i);
            errorDerivative=neuron.getTransferFunction().getDerivative(neuron.getNetInput());
            delta=outputErr[i]*errorDerivative;
            neuron.setDelta(roundThreeDecimals(delta));
            // now update the weights

            this.updateNeuronWeights(neuron);
        }

    }
   protected void updateHiddenLayerNeurons()
    {

        List<Layer> layers=this.network.getLayers();
        Layer currentLayer;
        double neuronErr;
        for ( int i=layers.size()-2;i>0;i--)
        {
            currentLayer= layers.get(i);

            for (int j=0;j<currentLayer.getSize();j++)
            {
                neuronErr=calculateHiddenLayerError(currentLayer.getAt(j));

                currentLayer.getAt(j).setDelta(neuronErr);
                this.updateNeuronWeights(currentLayer.getAt(j));
            }

        }
        //System.out.println("*****************************************");
    }
  protected double calculateHiddenLayerError(Neuron node)
    {
        List<Connection> outputCon= node.getOutputConnections();
        double errFactor=0;
        for (Connection outputCon1 : outputCon) {
            //System.out.println("output od dst: "+outputCon1.getDst().getOutput());
           // System.out.println("w dst: "+outputCon1.getWeight());
            //System.out.println("in CalcErr Factor err: "+outputCon.get(i).getDst().getError()+" w: "+outputCon.get(i).getWeight());
            errFactor += outputCon1.getDst().getDelta() * outputCon1.getWeight();
        }
        double derivative= node.getTransferFunction().getDerivative(node.getNetInput());

        return roundThreeDecimals(derivative*errFactor);
    }
     public void updateNeuronWeights(Neuron neuron)
{
    double weightChange;
    double input, error;
    for (Connection con: neuron.getInConnections())
    {   
        input=con.getInput();
       // System.out.println("input: "+input);
        error = neuron.getDelta();
        weightChange=this.learningRate*error*input;// error here is : output error * error derivative

        con.setWeight(roundThreeDecimals(con.getWeight()+weightChange));

    }
    // now update bias
    if(neuron.isBiasUsed())
    {
        //System.out.println("old bias: "+neuron.getBias());
        double biasChange=neuron.getBias()+neuron.getDelta()*this.learningRate;
        //System.out.println("new bias: "+biasChange);
       neuron.setBias(roundThreeDecimals(biasChange));
    }

}

我使用 [0.01,0.5] 范围内的学习率。谁能告诉我我的代码有什么问题吗?

TL;DR: 您应该使用与学习权重完全相同的方式通过反向传播来更新偏差。


可以肯定的是,与 OR 或 AND 相比,偏差在学习 XOR 中起着重要作用(参见 Why is a bias neuron necessary for a backpropagating neural network that recognizes the XOR operator? )。因此,偏见可能是罪魁祸首。

你说I'm using sigmoid as my activation function, and weighted sum as input你需要一个偏差,而不是用与学习权重完全相同的方式来学习。 注意:在应用激活函数之前,应在求和中添加偏差。