2014-11-16 5 views
1

Java에서 back-propagation ANN의 간단한 구현을 작성하려고하는데 아주 이상한 출력을 얻고 있습니다. ANN은 두 개의 노드 (입력 벡터의 각 값에 하나씩), 네 개의 노드가있는 단일 숨겨진 레이어 (더 이상 사용하지 않으려 고 실험했습니다) 및 3 개의 노드가있는 출력 레이어가있는 입력 레이어가 있습니다. 3 개의 출력 노드는 "one-hot"인코딩을 사용하여 데이터의 세 가지 가능한 분류를 나타냅니다. 2 입력으로하여 2 진수로Java Back-propagation ANN 출력 값

0.020055 0.40759 2 
0.020117 0.14934 3 
0.020117 0.25128 3 
0.020262 1.6068 1 

및 정수 원하는 분류 (1-3) 인 :

ANN에 어떤 입력은 다음과 같이 포맷된다.

목록에서 가능한 모든 데이터 조합으로 ANN 훈련 후

, 나는 세 개의 출력 노드

0.11237534579646044 0.15172262242962917 0.7906017313009316 2 
0.13686775670201043 0.1774606939461421 0.7656339988150088 3 
0.13554918638846133 0.1761024282314506 0.766924262279491 3 
0.06185317503169881 0.09410559150503017 0.8516964148498476 1 

의 출력으로 소수로, 다음과 같이 내가 가진 방법을 볼 수 출력의 모든 각 라인은 "높은"값 (S 자형 함수로 인해 0.95에 가깝다)을 나타내야하고 나머지는 "낮음"(0.05에 가깝다)이어야한다. 다음은

내가 최종 출력 값을 계산하기 위해 쓴 방법 :

public static double [] testANN(double [] input, List<BPNode> hiddenLayer, List <BPNode> outputLayer){ 
    double [] outInputs = new double[hiddenLayer.size()]; 
    double [] results = new double[outputLayer.size()]; 
    for(int i = 0; i<hiddenLayer.size(); i++){ 
     BPNode node = hiddenLayer.get(i); 
     node.inputs = input.clone(); 
     outInputs[i] = node.getOutput(); 
    } 
    for(int i = 0; i<outputLayer.size(); i++){ 
     BPNode node = outputLayer.get(i); 
     node.inputs = outInputs.clone(); 
     results[i] = node.getOutput(); 
    } 

    return results; 
} 

을 그리고 여기에 역 전파 알고리즘과 인공 신경망을 훈련하는 방법이다 :

public static void trainANN(double [] input, int desired, List<BPNode> hiddenLayer, List <BPNode> outputLayer){ 
    double [] d = new double[outputLayer.size()]; 
    d[0] = desired==1 ? 0.95 :0.05; 
    d[1] = desired==2 ? 0.95 :0.05; 
    d[2] = desired==3 ? 0.95 :0.05; 
    double [] [] weights = new double[outputLayer.size()][hiddenLayer.size()]; 
    double [] output = testANN(input,hiddenLayer,outputLayer); 
    double [] del = new double[outputLayer.size()]; 
    for(int i = 0; i<outputLayer.size(); i++){ 
     del[i] = (d[i]-output[i])*output[i]*(1-output[i]); 
     for (int j = 0; j<outputLayer.get(i).weights.length; j++){ 
      weights[i][j] = outputLayer.get(i).weights[j]; 
      outputLayer.get(i).weights[j]+=0.2*del[i]*outputLayer.get(i).inputs[j]; 
     } 
    } 
    for(int i = 0; i<hiddenLayer.size(); i++){ 
     double hiddenDel = 0.0; 
     for(int j = 0; j<outputLayer.size(); j++){ 
      hiddenDel+=(del[j]*weights[j][i]*hiddenLayer.get(i).getOutput()*(1-hiddenLayer.get(i).getOutput())); 
     } 
     for(int j = 0; j<hiddenLayer.get(i).weights.length; j++){ 
      hiddenLayer.get(i).weights[j]+=0.2*hiddenDel*input[j]; 
     } 
    } 

}

마지막으로 ANN을 구현하는 데 사용한 Node 클래스는 다음과 같습니다.

public class BPNode { 

public double [] inputs = new double[10]; 
public double [] weights = new double[10]; 

public BPNode(double [] w){ 
    weights = w; 
} 

public double getOutput() { 
    double a = 0; 
    for(int j = 0; j<inputs.length; j++){ 
     a += (inputs[j] * weights[j]); 
    } 
    return sigmoid(a,10.0); 
} 

private static double sigmoid(double x, double m) 
{ 
    return 1/(1 + Math.exp(-x*m)); 
} 

} 

모든 가중치가 0.1로 초기화되고 노드가 배열 목록에 배치되었습니다. 도와 주셔서 정말 감사합니다.

답변

1

이 문제를 해결하는 방법에 대해 궁금한 분은 0에서 1 사이의 가중치를 임의로 변경해 보았습니다.이 방법은 약간 좋았지 만 1에서 -1로 가중치를 변경하면 ANN이 데이터를 올바르게.