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));
	}
}