0

간단한 신경망을 구현하려고합니다. 이미 많은 라이브러리가 이미 있음을 알고 있습니다. 그 점은 중요하지 않습니다. 한 입력 층 하나 은닉층 하나 출력층신경망에 대한 Backpropagation

출력층 각각 다른 클래스를 나타내는 8 뉴런을 가지고

내 네트워크는 단지 3 개의 층을 갖는다.

나는 feedfoward algorythm을 구현하는 방법을 알고 있지만 정말 backpropagation을 위해 고심하고있다. 여기

내가 지금까지 가지고 올 한 것입니다 : https://en.wikipedia.org/wiki/Iris_flower_data_set

하지만 내 결과가 나이 보라로 이어지는 매우 일관성이 있습니다

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

나는 아이리스 데이터 세트와 시도 테스트를했습니다 내 backpropagation algorythm의 버그.

누군가가 어떤 중요한 결함을 볼 수 있다면 제발 말해주세요!

감사합니다. 코드의 이러한 부분에서

답변

0

:

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

뉴런의 목표 출력은 0.99 때 조건 (out == highestOutput && (j + 1) == desiredOutput). 즉, 피드 포워드가 학습 예제와 동일한 뉴런을 출력 할 때 뉴런의 출력이 0.99 일 때만 기대할 수 있습니다. 이것은 잘못되었습니다.

코드 부분의 조건은 (j + 1) == desiredOutput이어야합니다. out == highestOutput 상태를 제거하십시오. 피드 포워드가 그 뉴런을 초래하는지 여부에 관계없이 목표 출력은 desiredOutput 뉴런에 대해 0.99이어야합니다. 수정 된 코드입니다.

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