mirror of
https://github.com/glouw/tinn
synced 2024-11-25 07:49:35 +03:00
making some good progress
This commit is contained in:
parent
758a0bcbbd
commit
756e383bb5
131
test.c
131
test.c
@ -2,72 +2,93 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
// [i1] [h1] [o1]
|
||||
//
|
||||
// [i2] [h2] [o2]
|
||||
//
|
||||
// [b1] [b2]
|
||||
|
||||
static double act(const double in)
|
||||
{
|
||||
return 1.0 / (1.0 + exp(-in));
|
||||
}
|
||||
|
||||
static double shid(const double W[], const double I[], const int neuron, const int inputs)
|
||||
{
|
||||
double sum = 0.0;
|
||||
int i;
|
||||
for(i = 0; i < inputs; i++)
|
||||
sum += I[i] * W[i + neuron * inputs];
|
||||
return sum;
|
||||
}
|
||||
|
||||
static double sout(const double W[], const double I[], const int neuron, const int inputs, const int hidden)
|
||||
{
|
||||
double sum = 0.0;
|
||||
int i;
|
||||
for(i = 0; i < inputs; i++)
|
||||
sum += I[i] * W[i + hidden * (neuron + inputs)];
|
||||
return sum;
|
||||
}
|
||||
|
||||
static double cerr(const double T[], const double O[], const int count)
|
||||
{
|
||||
double ssqr = 0.0;
|
||||
int i;
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
const double sub = T[i] - O[i];
|
||||
ssqr += sub * sub;
|
||||
}
|
||||
return 0.5 * ssqr;
|
||||
}
|
||||
|
||||
static void bprop(double W[], const double I[], const double H[], const double O[], const double T[], const double rate)
|
||||
{
|
||||
const double a = -(T[0] - O[0]) * O[0] * (1.0 - O[0]);
|
||||
const double b = -(T[1] - O[1]) * O[1] * (1.0 - O[1]);
|
||||
const double c = (W[4] * a + W[6] * b) * (1.0 - H[0]);
|
||||
const double d = (W[5] * a + W[7] * b) * (1.0 - H[1]);
|
||||
/* Hidden layer */
|
||||
W[0] -= rate * H[0] * c * I[0];
|
||||
W[1] -= rate * H[0] * c * I[1];
|
||||
W[2] -= rate * H[1] * d * I[0];
|
||||
W[3] -= rate * H[1] * d * I[1];
|
||||
/* Output layer */
|
||||
W[4] -= rate * H[0] * a;
|
||||
W[5] -= rate * H[1] * a;
|
||||
W[6] -= rate * H[0] * b;
|
||||
W[7] -= rate * H[1] * b;
|
||||
}
|
||||
|
||||
/* Single layer feed forward neural network with back propogation error correction */
|
||||
static double train(const double I[], const double T[], const int nips, const int nops, const double rate, const int iters)
|
||||
{
|
||||
const double B[] = { 0.35, 0.60 };
|
||||
const int nhid = sizeof(B) / sizeof(*B);
|
||||
double W[] = { 0.15, 0.20, 0.25, 0.30, 0.40, 0.45, 0.50, 0.55 };
|
||||
double* H = (double*) malloc(sizeof(*H) * nhid);
|
||||
double* O = (double*) malloc(sizeof(*O) * nops);
|
||||
double error;
|
||||
int iter;
|
||||
for(iter = 0; iter < iters; iter++)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < nhid; i++) H[i] = act(B[0] + shid(W, I, i, nips));
|
||||
for(i = 0; i < nops; i++) O[i] = act(B[1] + sout(W, H, i, nips, nhid));
|
||||
bprop(W, I, H, O, T, rate);
|
||||
}
|
||||
error = cerr(T, O, nops);
|
||||
free(H);
|
||||
free(O);
|
||||
return error;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const double rate = 0.5;
|
||||
// Input.
|
||||
const double i1 = 0.05;
|
||||
const double i2 = 0.10;
|
||||
// Output.
|
||||
const double t1 = 0.01;
|
||||
const double t2 = 0.99;
|
||||
// Weights and biases.
|
||||
double w[] = { 0.15, 0.20, 0.25, 0.30, 0.40, 0.45, 0.50, 0.55 };
|
||||
double b[] = { 0.35, 0.60 };
|
||||
|
||||
double et = 0;
|
||||
const double I[] = { 0.05, 0.10 };
|
||||
|
||||
for(int i = 0; i < 10000; i++)
|
||||
{
|
||||
// Compute.
|
||||
const double h1 = act(w[0] * i1 + w[1] * i2 + b[0]);
|
||||
const double h2 = act(w[2] * i1 + w[3] * i2 + b[0]);
|
||||
const double o1 = act(w[4] * h1 + w[5] * h2 + b[1]);
|
||||
const double o2 = act(w[6] * h1 + w[7] * h2 + b[1]);
|
||||
const double T[] = { 0.01, 0.99 };
|
||||
|
||||
// Error calculation.
|
||||
const double to1 = t1 - o1;
|
||||
const double to2 = t2 - o2;
|
||||
const double e1 = 0.5 * to1 * to1;
|
||||
const double e2 = 0.5 * to2 * to2;
|
||||
et = e1 + e2;
|
||||
const double error = train(I, T, sizeof(I) / sizeof(*I), sizeof(T) / sizeof(*T), rate, 10000);
|
||||
|
||||
const double a = -to1 * o1 * (1.0 - o1);
|
||||
const double b = -to2 * o2 * (1.0 - o2);
|
||||
const double c = (w[4] * a + w[6] * b) * (1.0 - h1);
|
||||
const double d = (w[5] * a + w[7] * b) * (1.0 - h2);
|
||||
printf("%f\n", error);
|
||||
|
||||
// Back Propogation.
|
||||
w[0] -= rate * h1 * c * i1;
|
||||
w[1] -= rate * h1 * c * i2;
|
||||
w[2] -= rate * h2 * d * i1;
|
||||
w[3] -= rate * h2 * d * i2;
|
||||
w[4] -= rate * h1 * a;
|
||||
w[5] -= rate * h2 * a;
|
||||
w[6] -= rate * h1 * b;
|
||||
w[7] -= rate * h2 * b;
|
||||
|
||||
#if 0
|
||||
printf("w1 %.9f\n", w[0]);
|
||||
printf("w2 %.9f\n", w[1]);
|
||||
printf("w3 %.9f\n", w[2]);
|
||||
printf("w4 %.9f\n", w[3]);
|
||||
printf("w5 %.9f\n", w[4]);
|
||||
printf("w6 %.9f\n", w[5]);
|
||||
printf("w7 %.9f\n", w[6]);
|
||||
printf("w8 %.9f\n", w[7]);
|
||||
#endif
|
||||
}
|
||||
printf("%0.12f\n", et);
|
||||
return 0;
|
||||
}
|
||||
|
112
test2.c
Normal file
112
test2.c
Normal file
@ -0,0 +1,112 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
static double act(double net)
|
||||
{
|
||||
return 1.0 / (1.0 + exp(-net));
|
||||
}
|
||||
|
||||
static void forepass(double* I, double* O, double* H, double* W, double* B, const int inputs, const int output, const int hidden)
|
||||
{
|
||||
double* X = W + hidden * inputs;
|
||||
for(int i = 0; i < hidden; i++) { for(int j = 0; j < inputs; j++) H[i] += I[j] * W[i * inputs + j]; H[i] = act(H[i] + B[0]); }
|
||||
for(int i = 0; i < output; i++) { for(int j = 0; j < hidden; j++) O[i] += H[j] * X[i * hidden + j]; O[i] = act(O[i] + B[1]); }
|
||||
}
|
||||
|
||||
static void backpass(double* I, double* O, double* H, double* W, double* T, const int inputs, const int output, const int hidden, const double rate)
|
||||
{
|
||||
double* X = W + hidden * inputs;
|
||||
for(int i = 0; i < output; i++)
|
||||
for(int j = 0; j < hidden; j++)
|
||||
X[2 * i + j] -= rate * ((O[i] - T[i]) * (O[i] * (1 - O[i])) * H[j]);
|
||||
|
||||
//W[4] -= rate * ((T[0] - O[0]) * (T[0] * (1 - T[0])) * H[0]);
|
||||
//W[5] -= rate * ((T[0] - O[0]) * (T[0] * (1 - T[0])) * H[1]);
|
||||
//W[6] -= rate * ((T[1] - O[1]) * (T[1] * (1 - T[1])) * H[0]);
|
||||
//W[7] -= rate * ((T[1] - O[1]) * (T[1] * (1 - T[1])) * H[1]);
|
||||
}
|
||||
|
||||
static double cerror(double *O, double* T, const int output)
|
||||
{
|
||||
double error = 0.0;
|
||||
for(int i = 0; i < output; i++)
|
||||
error += 0.5 * pow(T[i] - O[i], 2.0);
|
||||
return error;
|
||||
}
|
||||
|
||||
static double* train(double* I, double* T, const int inputs, const int output, const int hidden)
|
||||
{
|
||||
// Weights.
|
||||
double* W = (double*) calloc(hidden * (inputs + output), sizeof(*W));
|
||||
W[0] = 0.15;
|
||||
W[1] = 0.20;
|
||||
W[2] = 0.25;
|
||||
W[3] = 0.30;
|
||||
W[4] = 0.40;
|
||||
W[5] = 0.45;
|
||||
W[6] = 0.50;
|
||||
W[7] = 0.55;
|
||||
|
||||
// Fixed at single hidden layer - only two biases are needed.
|
||||
double B[] = { 0.35, 0.60 };
|
||||
|
||||
// Hidden layer.
|
||||
double* H = (double*) calloc(hidden, sizeof(*H));
|
||||
|
||||
// Output layer. Will eventually converge to output with enough iterations.
|
||||
double* O = (double*) calloc(output, sizeof(*O));
|
||||
|
||||
// Computes hidden and target nodes.
|
||||
forepass(I, O, H, W, B, inputs, output, hidden);
|
||||
|
||||
// Computes output to target error.
|
||||
double err = cerror(O, O, output);
|
||||
|
||||
printf("error: %f\n", err);
|
||||
|
||||
// Updates weights based on target error.
|
||||
backpass(I, O, H, W, T, inputs, output, hidden, 0.5);
|
||||
|
||||
printf("W5: %f\n", W[4]);
|
||||
printf("W6: %f\n", W[5]);
|
||||
printf("W7: %f\n", W[6]);
|
||||
printf("W8: %f\n", W[7]);
|
||||
|
||||
printf("%f\n", H[0]);
|
||||
printf("%f\n", H[1]);
|
||||
printf("%f\n", O[0]);
|
||||
printf("%f\n", O[1]);
|
||||
|
||||
free(H);
|
||||
|
||||
return W;
|
||||
}
|
||||
|
||||
double* predict(double* I, double* W, const int inputs, const int output)
|
||||
{
|
||||
double* O = NULL;
|
||||
|
||||
// ...
|
||||
|
||||
return O;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const int inputs = 2, output = 2, hidden = 2;
|
||||
|
||||
// Input.
|
||||
double* I = (double*) calloc(inputs, sizeof(*I));
|
||||
I[0] = 0.05;
|
||||
I[1] = 0.10;
|
||||
|
||||
// Target.
|
||||
double* T = (double*) calloc(output, sizeof(*I));
|
||||
T[0] = 0.01;
|
||||
T[1] = 0.99;
|
||||
|
||||
train(I, T, inputs, output, hidden);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user