이번에도 XOR로 예제를 할껀데요, Multi-layer이므로 hidden을 2개 2개 연결하는 전체 layer를 4개가 되도록 만들겠습니다.
이미 다른 툴에서도 같은 방식으로 테스트 하였습니다.
빨간색으로 표시된 부분에 node형태를 기록합니다. 2-2-2-1 을 적어주면 자동으로 아래와 같은 신경망이 생기게 됩니다.
학습 데이터는 CSV 파일로 입력하면 되는데 ","로 구별되게 만들면 됩니다. excel 로 만들거나 open office 또는 직접만들면 됩니다.
x1,x2,y
0,0,0
1,0,1
0,1,1
1,1,0
train data를 선택하고 가중치 값을 randomize 설정합니다. 일반적으로 -0.5~0.5 구간으로 설정하고 train 버튼을 누릅니다.
해당 결과를 C언어로 생성하면 다음과 같다
/** Generated by Multiple Back-Propagation Version 2.2.4 Multiple Back-Propagation can be freely obtained at http://dit.ipg.pt/MBP */ #include <math.h> /** inputs - should be an array of 2 element(s), containing the network input(s). outputs - should be an array of 1 element(s), that will contain the network output(s). Note : The array inputs will also be changed.Its values will be rescaled between -1 and 1. */ void test1(double * inputs, double * outputs) { double mainWeights[] = {-3.432557344436646, 3.249020814895630, 3.257052659988403, 2.534264326095581, 2.839271068572998, 2.841655492782593, -2.028863191604614, -5.165799140930176, 4.703624248504639, 0.984100341796875, 1.948586821556091, -2.196990251541138, -2.397869348526001, 8.108511924743652, -3.533092021942139}; double * mw = mainWeights; double hiddenLayer1outputs[2]; double hiddenLayer2outputs[2]; int c; inputs[0] = -1.0 + (inputs[0] - 0.000000000000000) / 0.500000000000000; inputs[1] = -1.0 + (inputs[1] - 0.000000000000000) / 0.500000000000000; hiddenLayer1outputs[0] = *mw++; for(c = 0; c < 2; c++) hiddenLayer1outputs[0] += *mw++ * inputs[c]; hiddenLayer1outputs[0] = 1.0 / (1.0 + exp(-hiddenLayer1outputs[0])); hiddenLayer1outputs[1] = *mw++; for(c = 0; c < 2; c++) hiddenLayer1outputs[1] += *mw++ * inputs[c]; hiddenLayer1outputs[1] = 1.0 / (1.0 + exp(-hiddenLayer1outputs[1])); hiddenLayer2outputs[0] = *mw++; for(c = 0; c < 2; c++) hiddenLayer2outputs[0] += *mw++ * hiddenLayer1outputs[c]; hiddenLayer2outputs[0] = 1.0 / (1.0 + exp(-hiddenLayer2outputs[0])); hiddenLayer2outputs[1] = *mw++; for(c = 0; c < 2; c++) hiddenLayer2outputs[1] += *mw++ * hiddenLayer1outputs[c]; hiddenLayer2outputs[1] = 1.0 / (1.0 + exp(-hiddenLayer2outputs[1])); outputs[0] = *mw++; for(c = 0; c < 2; c++) outputs[0] += *mw++ * hiddenLayer2outputs[c]; outputs[0] = 1.0 / (1.0 + exp(-outputs[0])); outputs[0] = 0.000000000000000 + (outputs[0] - 0.000000) * 1.000000000000000; }
위 소스를 java로 변경하여 테스트 해보았습니다.
public class MBPtest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub double []inputs = new double [2]; double []outputs = new double [1]; inputs[0]=0d; inputs[1]=0d; test1(inputs,outputs); System.out.println("test1 : 0 0 "+outputs[0]); inputs[0]=0d; inputs[1]=1d; test1(inputs,outputs); System.out.println("test1 : 0 1 "+outputs[0]); inputs[0]=1d; inputs[1]=0d; test1(inputs,outputs); System.out.println("test1 : 1 0 "+outputs[0]); inputs[0]=1d; inputs[1]=1d; test1(inputs,outputs); System.out.println("test1 : 1 1 "+outputs[0]); } public static void test1(double []inputs, double []outputs) { double mainWeights[] = {-3.432557344436646, 3.249020814895630, 3.257052659988403, 2.534264326095581, 2.839271068572998, 2.841655492782593, -2.028863191604614, -5.165799140930176, 4.703624248504639, 0.984100341796875, 1.948586821556091, -2.196990251541138, -2.397869348526001, 8.108511924743652, -3.533092021942139}; double [] mw = mainWeights; int mwindex = 0; double []hiddenLayer1outputs = new double[2]; double []hiddenLayer2outputs = new double[2]; int c; inputs[0] = -1.0 + (inputs[0] - 0.000000000000000) / 0.500000000000000; inputs[1] = -1.0 + (inputs[1] - 0.000000000000000) / 0.500000000000000; hiddenLayer1outputs[0] = mw[mwindex++]; for(c = 0; c < 2; c++) hiddenLayer1outputs[0] += mw[mwindex++] * inputs[c]; hiddenLayer1outputs[0] = 1.0 / (1.0 + Math.exp(-hiddenLayer1outputs[0])); hiddenLayer1outputs[1] = mw[mwindex++]; for(c = 0; c < 2; c++) hiddenLayer1outputs[1] += mw[mwindex++] * inputs[c]; hiddenLayer1outputs[1] = 1.0 / (1.0 + Math.exp(-hiddenLayer1outputs[1])); hiddenLayer2outputs[0] = mw[mwindex++]; for(c = 0; c < 2; c++) hiddenLayer2outputs[0] += mw[mwindex++] * hiddenLayer1outputs[c]; hiddenLayer2outputs[0] = 1.0 / (1.0 + Math.exp(-hiddenLayer2outputs[0])); hiddenLayer2outputs[1] = mw[mwindex++]; for(c = 0; c < 2; c++) hiddenLayer2outputs[1] += mw[mwindex++] * hiddenLayer1outputs[c]; hiddenLayer2outputs[1] = 1.0 / (1.0 + Math.exp(-hiddenLayer2outputs[1])); outputs[0] = mw[mwindex++]; for(c = 0; c < 2; c++) outputs[0] += mw[mwindex++] * hiddenLayer2outputs[c]; outputs[0] = 1.0 / (1.0 + Math.exp(-outputs[0])); outputs[0] = 0.000000000000000 + (outputs[0] - 0.000000) * 1.000000000000000; } }
결과는 아래와 같이 나왔습니다.
test1 : 0 0 0.022113442375209617굉장히 편한 도구입니다. 대부분의 학습은 속도가 느리기 때문에 해당 툴을 CUDA를 이용해서 학습 후 결과만 받아서, 사용하는 곳에서는 그 결과를 이용해서 구현하면 되기 때문에 모바일 환경에서도 쉽게 구현할 수 있을것 같습니다.
test1 : 0 1 0.9805543032118464
test1 : 1 0 0.980571510242402
test1 : 1 1 0.018783890881570123
댓글 없음:
댓글 쓰기