2016-08-02 3 views
1

XOR 연산자처럼 작동해야하는 프로그램에서 작업 중입니다.인공 지능 (신경망) - 실제 출력이 올바른 출력에 도달하지 않음

가중치를 조정하기 위해 배경을 사용합니다.

나는 또한 깊은 학습 (거의 동일한 방식으로 잘 작동 함, 여기서는 같은 투쟁)을 포함 시켰지 만, 중요하지 않아야합니다. (

if(hiddenNeurons.size() > 1) 
{ 
..... 
} 

같은 경우-조항이있는 경우 여러 숨겨진 뉴런을 사용할 때 중요성에서 인 경우이 단지 코드가보다. (이 질문이 아닌 경우)에 어떤)

투쟁 : 결과는 입력이 무엇이든 관계없이 거의 항상 동일합니다 (약 0.5).

가중치와 바이어스가 조정됩니다. 여기

코드입니다 (더 많은 것이 있지만, 다른 코드는 중요한 것이 아닌) :

public void learnFromData(int iterations) //this method learns from the ArrayList 'inputs' and 'outputs' 
{ 
      if(inputs.size() == outputs.size()) 
      { 
       //Collections.shuffle(inputs); 
       for(int j = 0;j<iterations;j++) 
       { 
       for(int i = 0;i<inputs.size();i++) 
       { 

        double actualOutput = computeOutput(inputs.get(i))[0]; 
        double expectedOutput = outputs.get(i)[0]; 


        //System.out.println(String.format("Input: %.3f /\\ Ouput: %.4f Expected: %.4f",inputs.get(i)[0], actualOutput, expectedOutput)); 
        double error = 0; 
        if (actualOutput > expectedOutput) { 
         error = actualOutput - expectedOutput; 
        } else { 
         error = expectedOutput - actualOutput; 
        } 
        if(i == 0){ 
        System.out.println(String.format("Error: %.10f", error));} 
        learn(outputs.get(i)); 
       } 
      } 
     } 
     else{ 
      System.out.println("\nERROR: the number of inputs and outputs have to match!\n"); 
     } 
    } 
public double[] computeOutput(double[] inputValues) 
    { 

    for(int i = 0;i<inputValues.length;i++) //giving the inputNeurons a value 
    { 
     inputNeurons[i] = inputValues[i]; 
    } 
    for(int i = 0;i<hiddenNeurons.get(0).length;i++) 
    { 
     hSums.get(0)[i] = 0.0; 
    } 
    for(int i = 0;i<aOutputNeurons.length;i++) 
    { 
     hoSums[i] = 0.0; 
    } 
    for(int i = 0;i<inputNeurons.length;i++) //calculating the sums of the hidden neurons (Input-function) 
    { 
     for(int b = 0;b<hiddenNeurons.get(0).length;b++) 
     { 
      hSums.get(0)[b] += inputNeurons[i] * ihWeights[i][b]; 
     } 
    } 
    for(int i = 0;i<hiddenNeurons.get(0).length;i++) //Each bias-value has to be added to its associated sum 
    { 
     hSums.get(0)[i] += hBiases.get(0)[i]; 
    } 


    for(int i = 0;i<hiddenNeurons.get(0).length;i++) 
    { 
     hiddenNeurons.get(0)[i] = Helper.sig(hSums.get(0)[i]); //output-function = sigmoid 
    } 

    //calculating the hSums 
    if(hiddenNeurons.size()>1) 
    { 
     for (int layer = 0;layer<hiddenNeurons.size()-1;layer++) 
     { 
      //calculating the sums of the layer 
      for(int neuron_nextLayer = 0; neuron_nextLayer < hiddenNeurons.get(layer+1).length;neuron_nextLayer++) 
      { 
       hSums.get(layer+1)[neuron_nextLayer] = 0; 
       for(int neuron_actualLayer = 0;neuron_actualLayer < hiddenNeurons.get(layer).length;neuron_actualLayer++) 
       { 
        hSums.get(layer+1)[neuron_nextLayer] += hiddenNeurons.get(layer)[neuron_actualLayer] * hhWeights.get(layer)[neuron_actualLayer][neuron_nextLayer]; 
       } 
      } 
     } 
    } 
    // calculating the sums of the output neurons (Input-function) 
    int lastHiddenLayer = hiddenNeurons.size()-1; 
    for(int i = 0;i<aOutputNeurons.length;i++) 
    { 
     hoSums[i] = 0; 
     for(int b = 0;b<hiddenNeurons.get(lastHiddenLayer).length;b++) 
     { 
      hoSums[i] += hiddenNeurons.get(lastHiddenLayer)[b] * hoWeights[b][i]; 
     } 
     hoSums[i] += hoBiases[i]; 
     aOutputNeurons[i] = Helper.sig(hoSums[i]); 
    } 
    //weightToString(); 
    return aOutputNeurons; 
    } 
    public void learn(double[] cValues) //correctValues 
    { 
    // calculating the output-gradients 
    for(int i = 0;i<aOutputNeurons.length;i++) 
    { 
     oGradients[i] = (cValues[i]-aOutputNeurons[i])*Helper.invSig(aOutputNeurons[i]); 
    } 

    //calculating the hidden-gradients 
    double sum; //sum of all multiplications between gradients of the output layer and the weights between the hidden neuron and each output neuron. 
    int lastHiddenLayer = hiddenNeurons.size()-1; 
    for(int i = 0;i<hiddenNeurons.get(lastHiddenLayer).length;i++) 
    { 
     sum = 0; 
     for(int b = 0;b<aOutputNeurons.length;b++) 
     { 
      sum += oGradients[b] * hoWeights[i][b]; 
     } 
     hGradients.get(lastHiddenLayer)[i] = Helper.invSig(hiddenNeurons.get(lastHiddenLayer)[i]) * sum; 
    } 

    if(hiddenNeurons.size() > 1) 
    { 
     for(int layer = lastHiddenLayer;layer > 0;layer--) 
     { 

      for(int neuron_actualHiddenLayer = 0; neuron_actualHiddenLayer < hiddenNeurons.get(layer-1).length;neuron_actualHiddenLayer++) // neuron_actualHiddenLayer is more in the direction of the input neurons and neuron_nextHiddenLayer more in the direction of the output neurons 
      { 
       sum = 0; 

       for(int neuron_nextHiddenLayer = 0;neuron_nextHiddenLayer < hiddenNeurons.get(layer).length;neuron_nextHiddenLayer++) 
       { 
        sum += hGradients.get(layer)[neuron_nextHiddenLayer] * hhWeights.get(layer-1)[neuron_actualHiddenLayer][neuron_nextHiddenLayer]; 
       } 
       hGradients.get(layer-1)[neuron_actualHiddenLayer] = Helper.invSig(hiddenNeurons.get(layer-1)[neuron_actualHiddenLayer]) * sum; 
      } 
     } 
    } 


    //calculating weight- and biasdeltas of input- to hidden neurons 
    for(int i = 0;i<inputNeurons.length;i++) 
    { 
     for(int b = 0;b<hiddenNeurons.get(0).length;b++) 
     { 
      ihPrevWeightsDeltas[i][b] = eta * hGradients.get(0)[b] * inputNeurons[i]; 
      ihWeights[i][b] += ihPrevWeightsDeltas[i][b]; 
     } 
    } 
    // calculating weight- and biasdeltas of hidden- to hidden neurons 
    if(hiddenNeurons.size() > 1) 
    { 
     for(int layer = 0;layer < hiddenNeurons.size()-1;layer++) 
     { 
      for(int neuron_actualHiddenLayer = 0; neuron_actualHiddenLayer < hiddenNeurons.get(layer).length;neuron_actualHiddenLayer++) // neuron_actualHiddenLayer is more in the direction of the input neurons and neuron_nextHiddenLayer more in the direction of the output neurons 
      { 
       for(int neuron_nextHiddenLayer = 0;neuron_nextHiddenLayer < hiddenNeurons.get(layer+1).length;neuron_nextHiddenLayer++) 
       { 
        hhPrevWeightDeltas.get(layer)[neuron_actualHiddenLayer][neuron_nextHiddenLayer] = eta * hGradients.get(layer+1)[neuron_nextHiddenLayer] * hiddenNeurons.get(layer)[neuron_actualHiddenLayer]; 
        hhWeights.get(layer)[neuron_actualHiddenLayer][neuron_nextHiddenLayer] += hhPrevWeightDeltas.get(layer)[neuron_actualHiddenLayer][neuron_nextHiddenLayer]; 
        hhPrevBiasDeltas.get(layer)[neuron_actualHiddenLayer] = eta*hGradients.get(layer)[neuron_actualHiddenLayer]; 
        hBiases.get(layer)[neuron_actualHiddenLayer] += hhPrevBiasDeltas.get(layer)[neuron_actualHiddenLayer]; 
       } 
      } 
     } 
    } 
    for(int i = 0;i<hiddenNeurons.get(0).length;i++) 
    { 
     ihPrevBiasDeltas[i] = eta*hGradients.get(0)[i]; 
     hBiases.get(0)[i] += ihPrevBiasDeltas[i]; 
    } 
    for(int i = 0;i<aOutputNeurons.length;i++) 
    { 
     hoPrevBiasDeltas[i] = eta*oGradients[i]; 
     hoBiases[i] += hoPrevBiasDeltas[i]; 
    } 
    for(int i = 0;i<hiddenNeurons.get(0).length;i++) 
    { 
     for(int b = 0;b<aOutputNeurons.length;b++) 
     { 
      hoPrevWeightsDeltas[i][b] = eta * oGradients[b] * hiddenNeurons.get(lastHiddenLayer)[i]; 
      hoWeights[i][b] += hoPrevWeightsDeltas[i][b]; 
     } 
    } 

} 
+0

이걸 [MCVE] (http://stackoverflow.com/help/mcve)로 바꾸어서 더 읽기 쉽게 만들 수 있습니까? 같은 코드와 관련이없는 코드가 있기 때문에 특히 많은 코드입니다. –

+0

그래, 나는 누군가가 그렇게 말할 것이라고 생각했다. 하지만 어떻게하면 코드를 더 읽기 좋게 만들 수 있습니까? 당신은 더 나은 개요 (이 경우에는 불가능합니다)가 적은 코드를 의미합니까, 아니면 "문제를 재현하는 데 필요한 모든 부품을 제공"하기 위해 가지고있는 전체 코드를 넣어야합니까 (어느 것이 많습니까?)? – asparagus

+0

'어떻게하면 코드를 좀 더 읽기 좋게 만들 수 있을까요? '그건 당신의 문제입니다. 우리는 이미 질문을 이해하고 대답하고 있습니다. :) 그러나, 당신은 비트가 관련성이 없다고 말하면서, 서식을 개선하고 관대하게 느껴지더라도 질문을 편집 한 다음 결과를 실제 실행에 필요한 추가 상용구 코드 (예 : Github)와 함께 업로드하십시오. MCVE [here] (http://stackoverflow.com/help/mcve)의 정의를 읽으십시오. –

답변

1

가 자신의 코드이기 때문에, 같은 일부 성숙 프로젝트를 사용하여 동일한 네트워크를 할보십시오 Neuroph 라이브러리 및 결과를 비교, 그것은 당신이 문제를 좁히는 데 도움이됩니다.

또한 XOR 함수는 비선형 분류 문제이므로 비선형 활성화 함수로 최소 2 개의 레이어 (입력 1 개, 숨김 1 개)가 필요하다는 것을 기억하십시오. 그것은 선형 분류기가 비선형 분류를 수행 할 수 없기 때문에 비선형 분류기가 필요합니다.

+0

내 네트워크가 1 개의 레이어로만 구성된다는 것을 어떻게 알았습니까? (어쩌면 나는 그 질문에 잘못된 것을 공식화했다). 사실 1 개의 입력 -, 1 개의 숨겨진 - 및 1 개의 출력 레이어가 있기 때문입니다. – asparagus

+1

코드가 맞습니까? Neuroph 라이브러리를 사용해보십시오. 같은 것을 시도하십시오. 성숙한 프로젝트이며, 코드가 옳은지 테스트 할 수 없기 때문에 그러한 테스트는 코드가 정상인지 여부를 알려줍니다. –

+0

나는 분이 있다고 확신한다. 3 레이어. 나는 다른 레이어 사이의 모든 무게와 바이어스를 저장하는 .csv 파일을 가지고 있습니다. 모두가 실제로 3 개의 레이어가 있음을 볼 수있는 생성자를 넣는 것이 좋습니다. – asparagus