1層のニューラルネットワーク
学習の勉強用に
基本的な1層の2入力のニューラルネットワーク
float z = nn(x1,x2,(x1&x2));
与える教師の(x1&x2)はANDで、
(x1|x2)にすればORを学習する
ただし1層の場合はXORは学習できない
1 | | +------1
というグラフで考えた場合、ANDとORはw1*x+w2*y+w3という直線で分離できるけど
XORはできないので(線形分離不能)
普通の将棋の評価関数は「駒割+位置評価+王脅威+大駒脅威」という足し算なので、
00→0
10→1
01→1
11→0
みたいに入力に相関がある出力は学習できないはず(11→1になる)
隠れ層がないのでバックプロパゲーションはない。
普通の2乗誤差の最小二乗法。
参考ソース
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> float w[3]; float sigmoid(float x) { return 1.0/(1.0+exp(-x)); } float dsigmoid(float x) { float z=sigmoid(x); return z*(1.0-z); } float nn(int x1,int x2,int teach) { if(x1==0) x1=-1; if(x2==0) x2=-1; float z0=(float)x1*w[0]+(float)x2*w[1] + w[2]; float z=sigmoid(z0); printf("input(%d,%d) z0=%5.3f z=%5.3f w1=%5.3f w2=%5.3f w3=%5.3f", x1,x2,z0,z, w[0],w[1],w[2] ); float err0 = (teach - z); float err = err0*err0; printf("err=%f \n",err); float derr_dw1 = err0 * dsigmoid(z0)*x1; float derr_dw2 = err0 * dsigmoid(z0)*x2; float derr_dw3 = err0 * dsigmoid(z0); const float alpha=0.003; w[0] += alpha * derr_dw1; w[1] += alpha * derr_dw2; w[2] += alpha * derr_dw3; return z; } void main() { srand((unsigned) time(NULL)); for(;;) { int x1=rand()%2; int x2=rand()%2; printf("(%d,%d)->%d \n",x1,x2,x1&x2); float z = nn(x1,x2,(x1&x2)); } }