ｃでxor その2

#概要
cでxorやってみた。


#サンプルコード

```
#include <stdio.h>
#include <math.h>

#define NPATTERNS               4
#define NHIDDEN                 8
#define randomdef				((float) random() / (float) ((1 << 31) - 1))
double forward(double state[]);
void backprop(double push, double target);
void WeightChangesHO(double error);
void WeightChangesIH(double error);
void initWeights();
void initData();
double sigmoid(double x);
double tanh(double x);
void testAll();
void calcOverallError();
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 backprop(double push, double target) 
{
	error = push - target;
	WeightChangesHO(error);
	WeightChangesIH(error);
}
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;
		}
	}
}
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 printWeights() 
{
	int i, 
	    j;
	for (i = 0; i < 2; i ++) 
	{
		for (j = 0; j < 4; j ++) 
		{
		    printf("%.4f ", wih[i][j]);
		}
		printf(" ok\n");
	}
	for (i = 0; i < 4; i ++) 
	{
	    printf("%.4f ", who[i]);
	}
	printf ("\n");
}
void testAll()
{
	int i;
	double push;
	for (i = 0; i < numPatterns; i++)
	{
		push = test(i);
		printf ("pat%d expected = %.1f neural model = %.2f\n", patNum + 1, trainOutputs[patNum], 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) 
		{
			printf ("epoch = %d loss = %.4f\n", j, RMSerror);
			testAll();
		}
	}
}
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 init() 
{
	initWeights();
}
int main()
{
	init();
	train();
	return 0;
}

```

#成果物

https://paiza.io/projects/Zd4U3sdVNDYrPV7iKRRzKA

以上。