wemos d1でxor その2


概要

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

写真

サンプルコード

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

以上。