当前位置: 首页 > 知识库问答 >
问题:

神经网络的反向传播

益银龙
2023-03-14

我正在尝试实现一个简单的神经网络。我知道已经有很多可用的库,这不是重点。

我的网络只有3层:一个输入层一个隐藏层一个输出层

输出层有8个神经元,每个神经元代表不同的类。

我知道如何实现feedfoward算法,但我真的很难实现反向传播算法。

这是我到目前为止得出的结论:

private void backPropagation(List<List<Input>> trainingData)
{
    List<Input> trainingSet = new ArrayList<Input>();
    for (int row = 0; row < trainingData.size(); row++) {           
        trainingSet = trainingData.get(row);
        //we start by getting the output of the network
        List<Double> outputs = feedFoward(trainingSet); 

        //Im using the Iris dataset, so here the desiredOutput is
        //the species where 
        // 1 : setosa
        // 2 : versicolor
        // 3 : virginica
        double desiredOutput = getDesiredOutputFromTrainingSet(trainingSet);    
        //We are getting the output neuron that fired the highest result
        //like if we have
        //Ouput layer :
        //Neuron 1 --> 0.001221513
        //Neuron 2 --> 0.990516510
        //Neuron 3 --> 0.452221000
        //so the network predicted that the trainingData correspond to (2) versicolor
        double highestOutput = Collections.max(outputs);
        //What our neuron should aim for
        double target = 0;

        List<Double> deltaOutputLayer = new ArrayList<Double>();
        List<List<Double>> newWeightsOutputLayer = new ArrayList<List<Double>>();
        for (int j = 0; j < outputs.size(); j++) {  
            double out = outputs.get(j);
            //Important to do j + 1 because the species classes start at 1 (1 : setosa, 2: versicolor, 3:virginica)
            if(out == highestOutput && (j + 1) == desiredOutput)
                target = 0.99; //1
            else
                target = 0.01; //0

            //chain rule
            double delta = (out - target) * LogisticFonction.sigmoidPrime(out);
            deltaOutputLayer.add(delta);


            //get the new weigth value from delta and neta
            List<Double> newWeights = new ArrayList<Double>();
            for (int weightIndex = 0; weightIndex < _outputLayer.get(j).get_weigths().size(); weightIndex++) {
                double gradient = delta * _outputsAfterActivationHiddenLayer.get(weightIndex);
                double newWeight = _outputLayer.get(j).get_weigths().get(weightIndex) - (_learningRate * gradient);
                newWeights.add(newWeight);
            }
            newWeightsOutputLayer.add(newWeights);  
        }

        //hidden layer
        double totalError = 0;
        for (int i = 0; i < _neuronsHiddenLayer.size(); i++) {
            for (int j = 0; j < deltaOutputLayer.size(); j++) {
                double wi = _outputLayer.get(j).get_weigths().get(i);
                double delta = deltaOutputLayer.get(j);
                double partialError = wi * delta;
                totalError += partialError;
            }

            double z = _outputsAfterActivationHiddenLayer.get(i);
            double errorNeuron = LogisticFonction.sigmoidPrime(z);

            List<Double> newWeightsHiddenLayer = new ArrayList<Double>();

            for (int k = 0; k < _neuronsHiddenLayer.get(i).get_weigths().size(); k++) {
                double in = _neuronsHiddenLayer.get(i).get_inputs().get(k);
                double gradient =  totalError * errorNeuron * in;
                double oldWeigth = _neuronsHiddenLayer.get(i).get_weigths().get(k);
                double newWeigth = oldWeigth - (_learningRate * gradient);
                _neuronsHiddenLayer.get(i).get_weigths().set(k, newWeigth);
                newWeightsHiddenLayer.add(newWeigth);
            }
        }


        //then update the weigth of the output layer with the new values.
        for (int i = 0; i < newWeightsOutputLayer.size(); i++) {
            List<Double> newWeigths = newWeightsOutputLayer.get(i);
            _outputLayer.get(i).set_weigths(newWeigths);
        }
    }   
}

我尝试使用Iris数据集进行测试:https://en.wikipedia.org/wiki/Iris_flower_data_set

但我的结果非常不一致,这让我相信我的反向传播算法中有一个bug。

如果有人能看出一些重大缺陷,请告诉我!

非常感谢。

共有1个答案

牟星火
2023-03-14

在这部分代码中:

if(out == highestOutput && (j + 1) == desiredOutput)
     target = 0.99; //1
else
     target = 0.01; //0

当条件(out==high estOutput)时,神经元的目标输出为0.99

这部分代码的条件应该只为(j 1)=期望输出(desiredOutput)。删除out==高输出条件。对于期望输出的神经元,目标输出应为0.99,无论前馈是否产生该神经元。这是正确的代码:

if((j + 1) == desiredOutput)
     target = 0.99; //1
else
     target = 0.01; //0
 类似资料:
  • 我很难构建好的神经网络教学算法,因为有一些人工操作。第一件事:我的目标是教nn-xor函数,我使用sigmoid作为激活函数和简单的梯度下降。前馈很容易,但backprop在某种程度上令人困惑——大多数算法描述中常见的步骤有:1。计算输出层上的错误。2、将此错误传播到有关权重3的隐藏层。更新突触上的权重 所以我的问题:1。偏差也应该更新吗?如果是,如何更新?目前我随机选择偏差[0.5;1]?2.在

  • 我正在尝试用RELU实现神经网络。 输入层- 以上是我的神经网络结构。我对这个relu的反向传播感到困惑。对于RELU的导数,如果x 有人能解释一下我的神经网络架构的反向传播“一步一步”吗?

  • 考虑具有以下架构的卷积神经网络: Standford的深度学习教程使用以下等式来实现这一点: 然而,在使用这个等式时,我面临以下问题: 我做错了什么?有人能解释一下如何通过卷积层传播错误吗? 简单的MATLAB示例将受到高度赞赏。

  • 我们首先回顾DNN的反向传播算法。在DNN中,我们是首先计算出输出层的$$deltaL:deltaL = frac{partial J(W,b)}{partial zL} = frac{partial J(W,b)}{partial aL}odot sigma{'}(zL)$$ 利用数学归纳法,用$$delta{l+1}$$的值一步步的向前求出第l层的$$deltal$$,表达式为:$$delta

  • 我正在从头开始编写一个backprop神经网络迷你库,我需要一些帮助来编写有意义的自动测试。到目前为止,我已经进行了自动化测试,以验证backprop算法是否正确计算了权重和偏差梯度,但没有测试训练本身是否有效。 到目前为止,我使用的代码可以执行以下操作: 定义一个具有任意层数和每层神经元数的神经网络 鉴于所有这些,我可以编写什么样的自动化测试来确保训练算法被正确实施。我应该尝试近似什么函数(si

  • 这是本帖的后续问题。对于一个给定的神经元,我不清楚如何得到它的误差的偏导数和它的权重的偏导数。 通过这个网页,我们可以清楚地看到Propocation是如何工作的(尽管我处理的是弹性传播)。对于一个前馈神经网络,我们必须:1)在向前通过神经网络时,触发神经元;2)从输出层神经元,计算总误差;3)向后移动,以每个神经元的权值来计算该误差;4)再次向前移动,更新每个神经元的权值。 不过,这些都是我不明