wemos d1でxor その2

#概要
wemos d1でxor問題やってみた。NeuralNetworkで。


#写真

![xor0.JPG](https://qiita-image-store.s3.amazonaws.com/0/18104/b8322aca-8436-3933-381c-2a2f3822a750.jpeg)


#サンプルコード


```
#include <math.h>

#define NPATTERNS			4
#define NHIDDEN				8
#define randomdef			(double) ((rand() % 2000) - 1000) / 1000
double trainInputs[4][2] = {
	{0, 0},
	{1, 0},
	{0, 1},
	{1, 1}
};
static double trainOutputs[] = {
	0,
	1,
	1,
	0
};
static int numEpochs = 200;
static int numInputs = 2;
static int numPatterns = NPATTERNS;
static double LR_IH = 0.7;
static double LR_HO = 0.07;
static double h[NHIDDEN];
static double wih[4][NHIDDEN];
static double who[NHIDDEN];
static int patNum;
static double error;
static double outPred;
static double RMSerror;

double forward(double state[])
{
	int i,
		j;
	for (i = 0; i < NHIDDEN; i++)
	{
		h[i] = 0.0;
		for (j = 0; j < numInputs; j++)
		{
			h[i] = h[i] + (state[j] * wih[j][i]);
		}
		h[i] = tanh(h[i]);
	}
	double push = 0.0,
		sum = 0.0;
	for (i = 0; i < NHIDDEN; i++)
	{
		sum += h[i] * who[i];
	}
	push = sum;
	return push;
}
void WeightChangesHO(double error)
{
	int k;
	for (k = 0; k < NHIDDEN; k++)
	{
		double weightChange = LR_HO * error * h[k];
		who[k] = who[k] - weightChange;
		if (who[k] < -5) who[k] = -5;
		else if (who[k] > 5) who[k] = 5;
	}
}
void WeightChangesIH(double error)
{
	int i,
		k;
	for (i = 0; i < NHIDDEN; i++)
	{
		double gradient = (1 - (h[i]) * h[i]) * who[i] * error * LR_IH;
		for (k = 0; k < numInputs; k++)
		{
			double weightChange = gradient * trainInputs[patNum][k];
			wih[k][i] = wih[k][i] - weightChange;
		}
	}
}
void backprop(double push, double target)
{
	error = push - target;
	WeightChangesHO(error);
	WeightChangesIH(error);
}
double tanh(double x)
{
	if (x > 20) return 1;
	else if (x < -20) return -1;
	else
	{
		double a = exp(x);
		double b = exp(-x);
		return (a - b) / (a + b);
	}
}
double test(int patternNumber)
{
	patNum = patternNumber;
	return forward(trainInputs[patNum]);
}
void calcOverallError()
{
	int i;
	RMSerror = 0.0;
	for (i = 0; i < numPatterns; i++)
	{
		patNum = i;
		forward(trainInputs[patNum]);
		RMSerror = RMSerror + (error * error);
	}
	RMSerror = RMSerror / numPatterns;
	RMSerror = sqrt(RMSerror);
}
void testAll()
{
	int i;
	double push;
	for (i = 0; i < numPatterns; i++)
	{
		push = test(i);
		Serial.print(patNum);
		Serial.print("  ");
		Serial.print(trainOutputs[patNum]);
		Serial.print("  ");
		Serial.println(push);
	}
}
static void train()
{
	int i,
		j;
	double push;
	for (j = 0; j <= numEpochs; j++)
	{
		for (i = 0; i < numPatterns; i++)
		{
			patNum = (int) ((randomdef * numPatterns) - 0.001);
			push = forward(trainInputs[patNum]);
			backprop(push, trainOutputs[patNum]);
		}
		calcOverallError();
		if (j % 100 == 0)
		{
			Serial.print(j);
			Serial.print("  ");
			Serial.println(RMSerror);
			testAll();
		}
		delay(1);
	}
}
void initWeights()
{
	int i,
		j;
	for (j = 0; j < NHIDDEN; j++)
	{
		who[j] = (randomdef - 0.5) / 2;
		for (i = 0; i < numInputs; i++)
		{
			wih[i][j] = (randomdef - 0.5) / 5;
		}
	}
}
void setup()
{
	Serial.begin(115200);
	while (!Serial) delay(250);
	Serial.print("ok");
	Serial.println(randomdef);
	Serial.println(randomdef);
	Serial.println(randomdef);
	Serial.println(randomdef);
	initWeights();
	train();
}
void loop()
{
	delay(5000);
}

```

以上。