简体   繁体   中英

Backpropagation for neural network

I'm trying to implement a simple neural network. I know there is a lot of library already available out there, that is not the point.

My network has only 3 layers: one input layer one hidden layer one output layer

The output layer has 8 neuron representing each a different class.

I've understand how to implement the feedfoward algorythm but i'm really struggling for the backpropagation one.

here is what i've come up with so far :

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

I've try testing with the Iris dataset : https://en.wikipedia.org/wiki/Iris_flower_data_set

but my result are very inconsistant leading me to belive there is a bug in my backpropagation algorythm.

If anyone can see some major flaw tell me please!

thanks a lot.

In this part of the code:

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

The target output of the neuron is 0.99 when the condition (out == highestOutput && (j + 1) == desiredOutput) . It means that you would only expect the output of the neuron to be 0.99 when the feedforward outputs the same neuron as the training example. This is incorrect.

The condition on that part of the code should've been only (j + 1) == desiredOutput . Remove out == highestOutput condition. The target output should be 0.99 for the desiredOutput neuron no matter whether the feedforward results in that neuron or not. So this is the corrected code:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM