최초작성일:2016.6.20
이전의 글에 이어서 프로그래밍 연습을 해 보는 것이니, 이전글을 참고 하고 싶은 분은 아래의 링크를 따라가 주길 바란다.
(이전글의 링크: 최소 평균 제곱법 (Least Mean Squares Method, Widrow-Hoff Learning) [첫번째])
위와같이 A와 B의 집단을 가로지르는 직선 y에 대한 함수가 있다고 가정할때 그 값을 구하기 위한 Adaline의 적용례 이다.
위의 그래프를 기준으로, 두가지 입력 A,B에 따라서 출력값이 달라져야 한다.
따라서, 선분 y의 학습에 따른 그룹을 분류하기 위해, A: 1, B: -1로 하여 두 그룹을 분리한다.
먼저 학습을 위한 뉴런을 디자인 하자면 아래와 같이 나타 낼 수 있다.
위의 뉴런구조에 대한 출력값의 계산식은 아래와 같다.
여기서 b는 바이어스 값으로, 그래프 상으로 비유하자면 y절편에 해당되는 값이다.
이 바이어스를 넣지 않으면, 원점을 지나는 그래프의 수식에 대한 학습밖에 진행되지 않는다.
위의 수식에 대해 A, B 그룹으로 분류하기 위한 기준을 아래의 그림에서 나타낸다.
여기서 학습가중치에 대한 y값을 시그마를 이용하여 간략하게 나타 낼 수 있는데,
이때는 위와같이 로 두어서 로 두는 방법도있다.
각 그룹에 대한 입력값은 C언어를 이용하여 아래와 같이 나타 낼 수 있다.
1 2 3 4 5 6 7 8 9 10 11 | void NomalInput(int k){ if(k%2==0){ x[k][1] = 5.0 + normal_random_number() * 0.05; x[k][2] = 1.0 + normal_random_number() * 0.05; x[k][3] = 1.0; }else{ x[k][1] = 1.0 + normal_random_number() * 0.05; x[k][2] = 5.0 + normal_random_number() * 0.05; x[k][3] = -1.0; } } | cs |
2의 배수에 따라 (3,1)과 (1,3) 부근에 밀집하도록 점을 찍는다.
이 점들을 가로지르는 선분을 찾기 위해 뉴럴 네트워크의 학습을 이용한다.
가중치의 초기값을 0으로 초기화 하는 일이 없도록 해야 한다.
계산식이 곱셈으로 이루어 져 있기 때문에 0을 곱해버리면 학습이 진행되지 않는다.
따라서, 아래와 같이 가중치와 b값을 초기화 하였다.
1 2 3 4 5 6 | void WeightsInit(){ w[0][1] = normal_random_number() * 0.001; w[0][2] = normal_random_number() * 0.001; //바이어스 b b[0] = normal_random_number() * 0.001; } | cs |
여기서는 위와같이 적당한 난수값을 이용하여서 초기 가중치를 적용하였다.
지난번에 설명을 했던 가중치를 갱신하기 위한 수식을 가져온다.
이것을 C언어로 프로그래밍 하면 아래와 같이 만들수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | void Adaline(int k){ double mu=0.05; if(k%2==0){ w[0][1] += mu*(1-y[k])*x[k][1]; w[0][2] += mu*(1-y[k])*x[k][2]; b[0] += mu* (1-y[k]); }else{ w[0][1] += mu*(-1-y[k])*x[k][1]; w[0][2] += mu*(-1-y[k])*x[k][2]; b[0] += mu* (-1-y[k]); } } | cs |
따라서 if문을 이용하여서 y값 보다 클 경우에는 1을 반대의 경우는 -1을 적용해 준다.
여기서 값은 학습이 진동하거나, 너무 세밀하게 진행되지 않도록 적당히 적용 할 필요가 있다.
이와같은 학습규칙을 실행하는 메인문을 구현하면 아래와 같이 나태 날 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | int main(int argc, const char * argv[]) { int k; srand((unsigned int)time(NULL)); //입력부분 for(i=0;i<100;i++){ NomalInput(i); } WeightsInit(); for(i=0;i<5000;i++){ k=(int)(random_number()*100); y[k] = w[0][1]*x[k][1] + w[0][2]*x[k][2] + b[0]; Adaline(k); } //출력부분 printf("w[0][1]:%lf, \t w[0][2]:%lf, \t b[0]:%lf\n",w[0][1],w[0][2],b[0]); for (i=0;i<100;i++){ y[i] = w[0][1]*x[i][1] + w[0][2]*x[i][2] + b[0]; } printf("The group of +1\n"); for(i=0;i<100;i++){ if(y[i]>=0){ printf("y[%d]:%lf\t",i,y[i]); } } printf("\nThe group of -1\n"); for(i=0;i<100;i++){ if(y[i]<0){ printf("y[%d]:%lf\t",i,y[i]); } } printf("\n"); return 0; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | w[0][1]:0.247976, w[0][2]:-0.257816, b[0]:0.004910 The group of +1 y[0]:1.002532 y[2]:0.980550 y[4]:0.999439 y[6]:0.993767 y[8]:0.967772 y[10]:1.002970 y[12]:0.959107 y[14]:0.988246 y[16]:0.999693 y[18]:0.954653 y[20]:0.962063 y[22]:0.994093 y[24]:0.964085 y[26]:1.009830 y[28]:0.997437 y[30]:0.970826 y[32]:0.979284 y[34]:0.999618 y[36]:0.968749 y[38]:0.988110 y[40]:0.989170 y[42]:0.953714 y[44]:0.989208 y[46]:0.993478 y[48]:0.953484 y[50]:0.996792 y[52]:0.959610 y[54]:0.979793 y[56]:1.018864 y[58]:0.941375 y[60]:1.005707 y[62]:0.999593 y[64]:0.974662 y[66]:0.986495 y[68]:0.986200 y[70]:0.983751 y[72]:0.992835 y[74]:0.967915 y[76]:0.982125 y[78]:0.982757 y[80]:0.982970 y[82]:0.993718 y[84]:0.992167 y[86]:0.990641 y[88]:0.986043 y[90]:0.988128 y[92]:0.965995 y[94]:0.974769 y[96]:1.003075 y[98]:0.976202 The group of -1 y[1]:-1.018287 y[3]:-1.033705 y[5]:-1.048605 y[7]:-1.062589 y[9]:-1.026541 y[11]:-1.030194 y[13]:-1.062776 y[15]:-1.018513 y[17]:-1.030166 y[19]:-1.025713 y[21]:-1.006285 y[23]:-1.035965 y[25]:-1.048838 y[27]:-1.042318 y[29]:-1.038815 y[31]:-1.043376 y[33]:-1.057584 y[35]:-1.034113 y[37]:-1.013286 y[39]:-1.045135 y[41]:-1.042454 y[43]:-1.020391 y[45]:-1.053301 y[47]:-1.042524 y[49]:-1.052358 y[51]:-1.057190 y[53]:-1.026822 y[55]:-1.050978 y[57]:-1.028512 y[59]:-0.985872 y[61]:-1.044279 y[63]:-1.048507 y[65]:-1.036589 y[67]:-1.024148 y[69]:-1.024108 y[71]:-1.037620 y[73]:-1.053545 y[75]:-0.999278 y[77]:-1.025617 y[79]:-1.032241 y[81]:-1.031482 y[83]:-1.043788 y[85]:-1.030256 y[87]:-1.026200 y[89]:-1.049062 y[91]:-1.020469 y[93]:-1.073367 y[95]:-1.071565 y[97]:-1.025625 y[99]:-1.010947 Program ended with exit code: 0 | cs |
가중치 w를 학습 한 결과에 대한 값과, A, B에 대해 1, -1에 근접한 두 그룹으로 나뉘어진 것을 잘 알수있다.
여기에 작성하는 모든 포스팅 들은 스스로의 지식의 정리와, 지식의 공유 차원에서 정리한 것입니다.
학교의 레포트나 과제등은, 본인 스스로가 공부를 해서 직접 제출 하도록 합시다.