LoginSignup
0
0

More than 5 years have passed since last update.

cでxor その2

Posted at

概要

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

成果物

以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0