#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#define PN 4
#define INPUT 2
#define HIDDEN 2
#define TARGET 1
#define OUTPUT 1
struct NN
{
int ni;
int nh;
int no;
double * ai;
double * ah;
double * ao;
double * wi;
double * wo;
double * ci;
double * co;
};
double rand(double a, double b)
{
return (b - a) * rand() / (double)(RAND_MAX) + a;
}
double * makeMatrix(int i, int j, double fill)
{
double * matrix = (double *) malloc (i * j * sizeof(double));
int m, n;
for (m = 0;m < i;++ m) {
for (n = 0;n < j;++ n) {
*(matrix + m * j + n) = fill;
}
}
return matrix;
}
double sigmoid(double x)
{
return (exp(x) - exp(-x)) / (exp(x) + exp(-x));
}
double dsigmoid(double x)
{
return 1.0 - x * x;
}
void init(NN * self, int ni, int nh, int no)
{
srand(time(NULL));
int i, j;
self->ni = ni + 1;
self->nh = nh;
self->no = no;
self->ai = (double *) malloc (sizeof(double) * self->ni);
self->ah = (double *) malloc (sizeof(double) * self->nh);
self->ao = (double *) malloc (sizeof(double) * self->no);
for (i = 0;i < self->ni;++ i) {
self->ai[i] = 1.0;
}
for (i = 0;i < self->nh;++ i) {
self->ah[i] = 1.0;
}
for (i = 0;i < self->no;++ i) {
self->ao[i] = 1.0;
}
self->wi = makeMatrix(self->ni, self->nh, 0);
self->wo = makeMatrix(self->nh, self->no, 0);
for (i = 0;i < self->ni;++ i) {
for (j = 0;j < self->nh;++ j) {
self->wi[i * self->nh + j] = rand(-0.2, 0.2);
}
}
for (i = 0;i < self->nh;++ i) {
for (j = 0;j < self->no;++ j) {
self->wo[i * self->no + j] = rand(-2.0, 2.0);
}
}
self->ci = makeMatrix(self->ni, self->nh, 0);
self->co = makeMatrix(self->nh, self->no, 0);
}
double * update(NN * self, double *inputs)
{
if (INPUT != self->ni - 1) {
printf("wrong number of inputs\n");
}
int i, j, k;
for (i = 0;i < self->ni - 1;++ i) {
self->ai[i] = inputs[i];
}
for (j = 0;j < self->nh;++ j) {
double sum = 0;
for (i = 0;i < self->ni;++ i) {
sum += self->ai[i] * self->wi[i * self->nh + j];
}
self->ah[j] = sigmoid(sum);
}
for (k = 0;k < self->no;++ k) {
double sum = 0;
for (j = 0;j < self->nh;++ j) {
sum += self->ah[j] * self->wo[j * self->no + k];
}
self->ao[k] = sigmoid(sum);
}
double *output = (double *) malloc (sizeof(double) * self->no);
for (i = 0;i < self->no;++ i) {
*(output + i) = self->ao[i];
}
return output;
}
double backprobagation(NN * self, double *targets, double N, double M)
{
if (TARGET != self->no) {
printf("wrong number of target values\n");
}
int i, j, k;
double *output_deltas = (double *) calloc (self->no, sizeof(double));
for (k = 0;k < self->no;++ k) {
double error = targets[k] - self->ao[k];
output_deltas[k] = dsigmoid(self->ao[k]) * error;
}
double *hidden_deltas = (double *) calloc (self->nh, sizeof(double));
for (j = 0;j < self->nh;++ j) {
double error = 0;
for (k = 0;k < self->no;++ k) {
error += output_deltas[k] * self->wo[j * self->no + k];
}
hidden_deltas[j] = dsigmoid(self->ah[j]) * error;
}
for (j = 0;j < self->nh;++ j) {
for (k = 0;k < self->no;++ k) {
double change = output_deltas[k] * self->ah[j];
self->wo[j * self->no + k] += (N * change + M * self->co[j * self->no + k]);
self->co[j * self->no + k] = change;
}
}
for (i = 0;i < self->ni;++ i) {
for (j = 0;j < self->nh;++ j) {
double change = hidden_deltas[j] * self->ai[i];
self->wi[i * self->nh + j] += (N * change + M * self->ci[i * self->nh + j]);
self->ci[i * self->nh + j] = change;
}
}
double error = 0;
for (k = 0;k < TARGET;++ k) {
error += 0.5 * (targets[k] - self->ao[k]) * (targets[k] - self->ao[k]);
}
return error;
}
void test(NN * self, double *inputs, double *targets)
{
int i, j, k;
for (i = 0;i < PN;++ i) {
double * input = (double *) malloc (sizeof(double) * INPUT);
for (j = 0;j < INPUT;++ j) {
input[j] = inputs[i * INPUT + j];
printf("%lf ", input[j]);
}
update(self, input);
for (k = 0;k < self->no;++ k) {
printf("%lf ", self->ao[k]);
}
printf("\n");
}
}
void train(NN * self, double *inputs, double *targets, int iteration, double N, double M)
{
int i, j, k, p;
for (i = 0;i < iteration;++ i) {
double error = 0;
for (p = 0;p < PN;++ p) {
double *input = (double *) malloc (sizeof(double) * INPUT);
double *target = (double *) malloc (sizeof(double) * TARGET);
for (j = 0;j < INPUT;++ j) {
*(input + j) = inputs[p * INPUT + j];
}
for (k = 0;k < TARGET;++ k) {
*(target + k) = targets[p * TARGET + k];
}
update(self, input);
error += backprobagation(self, target, N, M);
}
if (i % 100 == 0) {
printf("error %-.5lf\n", error);
}
}
}
int main()
{
double inputs[PN * INPUT] = {0, 0, 0, 1, 1, 0, 1, 1};
double targets[PN * TARGET] = {0, 1, 1, 0};
NN * self = (NN *) calloc (1, sizeof(NN));
init(self, 2, 2, 1);
train(self, inputs, targets, 5000, 0.5, 0.1);
test(self, inputs, targets);
return 0;
}
#include <math.h>
#include <time.h>
#include <stdlib.h>
#define PN 4
#define INPUT 2
#define HIDDEN 2
#define TARGET 1
#define OUTPUT 1
struct NN
{
int ni;
int nh;
int no;
double * ai;
double * ah;
double * ao;
double * wi;
double * wo;
double * ci;
double * co;
};
double rand(double a, double b)
{
return (b - a) * rand() / (double)(RAND_MAX) + a;
}
double * makeMatrix(int i, int j, double fill)
{
double * matrix = (double *) malloc (i * j * sizeof(double));
int m, n;
for (m = 0;m < i;++ m) {
for (n = 0;n < j;++ n) {
*(matrix + m * j + n) = fill;
}
}
return matrix;
}
double sigmoid(double x)
{
return (exp(x) - exp(-x)) / (exp(x) + exp(-x));
}
double dsigmoid(double x)
{
return 1.0 - x * x;
}
void init(NN * self, int ni, int nh, int no)
{
srand(time(NULL));
int i, j;
self->ni = ni + 1;
self->nh = nh;
self->no = no;
self->ai = (double *) malloc (sizeof(double) * self->ni);
self->ah = (double *) malloc (sizeof(double) * self->nh);
self->ao = (double *) malloc (sizeof(double) * self->no);
for (i = 0;i < self->ni;++ i) {
self->ai[i] = 1.0;
}
for (i = 0;i < self->nh;++ i) {
self->ah[i] = 1.0;
}
for (i = 0;i < self->no;++ i) {
self->ao[i] = 1.0;
}
self->wi = makeMatrix(self->ni, self->nh, 0);
self->wo = makeMatrix(self->nh, self->no, 0);
for (i = 0;i < self->ni;++ i) {
for (j = 0;j < self->nh;++ j) {
self->wi[i * self->nh + j] = rand(-0.2, 0.2);
}
}
for (i = 0;i < self->nh;++ i) {
for (j = 0;j < self->no;++ j) {
self->wo[i * self->no + j] = rand(-2.0, 2.0);
}
}
self->ci = makeMatrix(self->ni, self->nh, 0);
self->co = makeMatrix(self->nh, self->no, 0);
}
double * update(NN * self, double *inputs)
{
if (INPUT != self->ni - 1) {
printf("wrong number of inputs\n");
}
int i, j, k;
for (i = 0;i < self->ni - 1;++ i) {
self->ai[i] = inputs[i];
}
for (j = 0;j < self->nh;++ j) {
double sum = 0;
for (i = 0;i < self->ni;++ i) {
sum += self->ai[i] * self->wi[i * self->nh + j];
}
self->ah[j] = sigmoid(sum);
}
for (k = 0;k < self->no;++ k) {
double sum = 0;
for (j = 0;j < self->nh;++ j) {
sum += self->ah[j] * self->wo[j * self->no + k];
}
self->ao[k] = sigmoid(sum);
}
double *output = (double *) malloc (sizeof(double) * self->no);
for (i = 0;i < self->no;++ i) {
*(output + i) = self->ao[i];
}
return output;
}
double backprobagation(NN * self, double *targets, double N, double M)
{
if (TARGET != self->no) {
printf("wrong number of target values\n");
}
int i, j, k;
double *output_deltas = (double *) calloc (self->no, sizeof(double));
for (k = 0;k < self->no;++ k) {
double error = targets[k] - self->ao[k];
output_deltas[k] = dsigmoid(self->ao[k]) * error;
}
double *hidden_deltas = (double *) calloc (self->nh, sizeof(double));
for (j = 0;j < self->nh;++ j) {
double error = 0;
for (k = 0;k < self->no;++ k) {
error += output_deltas[k] * self->wo[j * self->no + k];
}
hidden_deltas[j] = dsigmoid(self->ah[j]) * error;
}
for (j = 0;j < self->nh;++ j) {
for (k = 0;k < self->no;++ k) {
double change = output_deltas[k] * self->ah[j];
self->wo[j * self->no + k] += (N * change + M * self->co[j * self->no + k]);
self->co[j * self->no + k] = change;
}
}
for (i = 0;i < self->ni;++ i) {
for (j = 0;j < self->nh;++ j) {
double change = hidden_deltas[j] * self->ai[i];
self->wi[i * self->nh + j] += (N * change + M * self->ci[i * self->nh + j]);
self->ci[i * self->nh + j] = change;
}
}
double error = 0;
for (k = 0;k < TARGET;++ k) {
error += 0.5 * (targets[k] - self->ao[k]) * (targets[k] - self->ao[k]);
}
return error;
}
void test(NN * self, double *inputs, double *targets)
{
int i, j, k;
for (i = 0;i < PN;++ i) {
double * input = (double *) malloc (sizeof(double) * INPUT);
for (j = 0;j < INPUT;++ j) {
input[j] = inputs[i * INPUT + j];
printf("%lf ", input[j]);
}
update(self, input);
for (k = 0;k < self->no;++ k) {
printf("%lf ", self->ao[k]);
}
printf("\n");
}
}
void train(NN * self, double *inputs, double *targets, int iteration, double N, double M)
{
int i, j, k, p;
for (i = 0;i < iteration;++ i) {
double error = 0;
for (p = 0;p < PN;++ p) {
double *input = (double *) malloc (sizeof(double) * INPUT);
double *target = (double *) malloc (sizeof(double) * TARGET);
for (j = 0;j < INPUT;++ j) {
*(input + j) = inputs[p * INPUT + j];
}
for (k = 0;k < TARGET;++ k) {
*(target + k) = targets[p * TARGET + k];
}
update(self, input);
error += backprobagation(self, target, N, M);
}
if (i % 100 == 0) {
printf("error %-.5lf\n", error);
}
}
}
int main()
{
double inputs[PN * INPUT] = {0, 0, 0, 1, 1, 0, 1, 1};
double targets[PN * TARGET] = {0, 1, 1, 0};
NN * self = (NN *) calloc (1, sizeof(NN));
init(self, 2, 2, 1);
train(self, inputs, targets, 5000, 0.5, 0.1);
test(self, inputs, targets);
return 0;
}