Simple Neural Network in C

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
A neural network is a structure of connections and nodes that takes input and generates an output. It can be "taught"(adjusting weights and biases of connections) from a teacher data set with acceptable outputs and inputs.
See https://en.wikipedia.org/wiki/Neural_network for more details.
nn.c:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define INPUT_COUNT 3
#define HIDDEN_COUNT 3
#define OUTPUT_COUNT 1
#define LEARNING_RATE 0.15
typedef struct
float in_Weights[INPUT_COUNT];
float inBias;
float value;
float out_Weights[OUTPUT_COUNT];
Neuron;
typedef struct
float value;
IO_Neuron;
typedef struct
int sucess;
IO_Neuron** training_in;
IO_Neuron** training_out;
int examples;
TData;
//loads training data from a file like format below
/*
#inputs,outputs,count
input1,input2,input3 output1,output2
*/
TData tData(const char* filename)
float genRandRange(float min,float max)
if (min == max)
return min;
float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
return min + scale * ( max - min ); /* [min, max] */
//activation function
float sigmoid(float x)
return 1 / (1 + exp(-x));
float sigmoid_derivative(float x)
return sigmoid(x) * (1 - sigmoid(x));
//computes weighted sum
float dot_summation(float* in,float* weights,int count)
int i;
float result = 0;
for (i =0;i < count;i++)
result += in[i]*weights[i];
return result;
//these functions extract data into an easier to handle format
float* ioValues(IO_Neuron* hidden_layer)
float* ret = malloc(sizeof(float)*INPUT_COUNT);
int i;
for (i =0; i < INPUT_COUNT;i++)
ret[i] = hidden_layer[i].value;
return ret;
float* values(Neuron* hidden_layer)
float* ret = malloc(sizeof(float)*HIDDEN_COUNT);
int i;
for (i =0; i < HIDDEN_COUNT;i++)
ret[i] = hidden_layer[i].value;
return ret;
float* outWeights(Neuron* hidden_layer,int index)
float* ret = malloc(sizeof(float)*HIDDEN_COUNT);
int i;
for (i =0; i < HIDDEN_COUNT;i++)
ret[i] = hidden_layer[i].out_Weights[index];
return ret;
//pass values through the neural network
void think(IO_Neuron* input_layer,Neuron* hidden_layer,IO_Neuron* output_layer)
int i;
float* io_values = ioValues(input_layer);
for (i =0; i < HIDDEN_COUNT;i++)
hidden_layer[i].value = sigmoid(dot_summation(io_values,hidden_layer[i].in_Weights,INPUT_COUNT) + hidden_layer[i].inBias);
free(io_values);
float* hidden_values = values(hidden_layer);
for (i =0; i < OUTPUT_COUNT;i++)
float* out_weights = outWeights(hidden_layer,i);
output_layer[i].value = sigmoid(dot_summation(hidden_values,out_weights,HIDDEN_COUNT));
free(out_weights);
free(hidden_values);
//adjust the neural network's connection weights and biases based upon training data
void train(IO_Neuron* input_layer,Neuron* hidden_layer,IO_Neuron* output_layer,IO_Neuron** input_training,IO_Neuron** output_training,int training_samples,int iterations)
int i,j,k,l;
IO_Neuron recorded_outputs[training_samples][OUTPUT_COUNT];
Neuron recorded_hidden[training_samples][HIDDEN_COUNT];
float error_output[training_samples][OUTPUT_COUNT];//contains output node's delta
float error_hidden[training_samples][HIDDEN_COUNT];
for (i =0; i < iterations;i++)
for (j =0; j < training_samples;j++)
think(input_training[j],hidden_layer,output_layer);
memcpy(recorded_outputs[j],output_layer,sizeof(IO_Neuron)*OUTPUT_COUNT);
memcpy(recorded_hidden[j],hidden_layer,sizeof(Neuron)*HIDDEN_COUNT);
for (j =0; j < training_samples;j++)
for (k =0; k < OUTPUT_COUNT;k++)
error_output[j][k] = recorded_outputs[j][k].value*(1 - recorded_outputs[j][k].value) * (output_training[j][k].value - recorded_outputs[j][k].value);
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
float errorFactor = 0;
for (l =0;l < OUTPUT_COUNT;l++)
errorFactor += (error_output[j][l]*hidden_layer[k].out_Weights[l]);
error_hidden[j][k] = recorded_hidden[j][k].value*(1 - recorded_hidden[j][k].value) * errorFactor;
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
//TODO update biases
hidden_layer[k].inBias = hidden_layer[k].inBias + LEARNING_RATE *error_hidden[j][k];
for (l = 0;l < INPUT_COUNT;l++)
hidden_layer[k].in_Weights[l] = hidden_layer[k].in_Weights[l] + (LEARNING_RATE*error_hidden[j][k]*input_training[j][l].value)/training_samples;
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
for (l = 0;l < OUTPUT_COUNT;l++)
hidden_layer[k].out_Weights[l] = hidden_layer[k].out_Weights[l] + (LEARNING_RATE*error_output[j][k]*recorded_hidden[j][k].value)/training_samples;
//assign random weights to the neural network's connections
void randweights(Neuron* neurons)
int i;
for (i =0;i< HIDDEN_COUNT;i++)
neurons[i].in_Weights[0] = 2*genRandRange(0,1) - 1;
neurons[i].in_Weights[1] = 2*genRandRange(0,1) - 1;
neurons[i].in_Weights[2] = 2*genRandRange(0,1) - 1;
neurons[i].out_Weights[2] = 2*genRandRange(0,1) - 1;
neurons[i].inBias = 2*genRandRange(0,1) - 1;
int main()
srand(1);
int i,j;
//aquire training data
TData t_data = tData("training.txt");
if (!t_data.sucess)
return 0;
IO_Neuron** training_in = t_data.training_in;
IO_Neuron** training_out = t_data.training_out;
//allocate neural network
IO_Neuron* input_layer = malloc(sizeof(IO_Neuron)*INPUT_COUNT);
Neuron* hidden_layer = malloc(sizeof(Neuron)*HIDDEN_COUNT);
IO_Neuron* output_layer = malloc(sizeof(IO_Neuron)*OUTPUT_COUNT);
randweights(hidden_layer);
//train with training data
train(input_layer,hidden_layer,output_layer,training_in,training_out,t_data.examples,10000);
//test out the learned pattern
input_layer[0].value = 0;
input_layer[1].value = 0;
input_layer[2].value = 0;
//generates the output
think(input_layer,hidden_layer,output_layer);
for (i =0; i < OUTPUT_COUNT;i++)
printf("%fn",output_layer[i].value );
return 0;
Here is a sample file of training data that can be read by the program.
training.txt:
#3,1,7
1,0,1 0
1,0,0 0
1,1,0 1
1,1,1 1
0,1,0 1
0,1,1 1
0,0,1 0
0,0,0 0
In case you have not noticed, the pattern present within the data is that it simply outputs the first number of the input.
The neural network has 3 inputs,3 hidden nodes, and 1 output, these can be changed easily by modifying training data and the constants at the beginning of the code.
I know pure C is not often used for neural networks due to its lack of true object orientation and strict typing but I prefer its simplicity and readability.
c machine-learning neural-network
add a comment |Â
up vote
1
down vote
favorite
A neural network is a structure of connections and nodes that takes input and generates an output. It can be "taught"(adjusting weights and biases of connections) from a teacher data set with acceptable outputs and inputs.
See https://en.wikipedia.org/wiki/Neural_network for more details.
nn.c:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define INPUT_COUNT 3
#define HIDDEN_COUNT 3
#define OUTPUT_COUNT 1
#define LEARNING_RATE 0.15
typedef struct
float in_Weights[INPUT_COUNT];
float inBias;
float value;
float out_Weights[OUTPUT_COUNT];
Neuron;
typedef struct
float value;
IO_Neuron;
typedef struct
int sucess;
IO_Neuron** training_in;
IO_Neuron** training_out;
int examples;
TData;
//loads training data from a file like format below
/*
#inputs,outputs,count
input1,input2,input3 output1,output2
*/
TData tData(const char* filename)
float genRandRange(float min,float max)
if (min == max)
return min;
float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
return min + scale * ( max - min ); /* [min, max] */
//activation function
float sigmoid(float x)
return 1 / (1 + exp(-x));
float sigmoid_derivative(float x)
return sigmoid(x) * (1 - sigmoid(x));
//computes weighted sum
float dot_summation(float* in,float* weights,int count)
int i;
float result = 0;
for (i =0;i < count;i++)
result += in[i]*weights[i];
return result;
//these functions extract data into an easier to handle format
float* ioValues(IO_Neuron* hidden_layer)
float* ret = malloc(sizeof(float)*INPUT_COUNT);
int i;
for (i =0; i < INPUT_COUNT;i++)
ret[i] = hidden_layer[i].value;
return ret;
float* values(Neuron* hidden_layer)
float* ret = malloc(sizeof(float)*HIDDEN_COUNT);
int i;
for (i =0; i < HIDDEN_COUNT;i++)
ret[i] = hidden_layer[i].value;
return ret;
float* outWeights(Neuron* hidden_layer,int index)
float* ret = malloc(sizeof(float)*HIDDEN_COUNT);
int i;
for (i =0; i < HIDDEN_COUNT;i++)
ret[i] = hidden_layer[i].out_Weights[index];
return ret;
//pass values through the neural network
void think(IO_Neuron* input_layer,Neuron* hidden_layer,IO_Neuron* output_layer)
int i;
float* io_values = ioValues(input_layer);
for (i =0; i < HIDDEN_COUNT;i++)
hidden_layer[i].value = sigmoid(dot_summation(io_values,hidden_layer[i].in_Weights,INPUT_COUNT) + hidden_layer[i].inBias);
free(io_values);
float* hidden_values = values(hidden_layer);
for (i =0; i < OUTPUT_COUNT;i++)
float* out_weights = outWeights(hidden_layer,i);
output_layer[i].value = sigmoid(dot_summation(hidden_values,out_weights,HIDDEN_COUNT));
free(out_weights);
free(hidden_values);
//adjust the neural network's connection weights and biases based upon training data
void train(IO_Neuron* input_layer,Neuron* hidden_layer,IO_Neuron* output_layer,IO_Neuron** input_training,IO_Neuron** output_training,int training_samples,int iterations)
int i,j,k,l;
IO_Neuron recorded_outputs[training_samples][OUTPUT_COUNT];
Neuron recorded_hidden[training_samples][HIDDEN_COUNT];
float error_output[training_samples][OUTPUT_COUNT];//contains output node's delta
float error_hidden[training_samples][HIDDEN_COUNT];
for (i =0; i < iterations;i++)
for (j =0; j < training_samples;j++)
think(input_training[j],hidden_layer,output_layer);
memcpy(recorded_outputs[j],output_layer,sizeof(IO_Neuron)*OUTPUT_COUNT);
memcpy(recorded_hidden[j],hidden_layer,sizeof(Neuron)*HIDDEN_COUNT);
for (j =0; j < training_samples;j++)
for (k =0; k < OUTPUT_COUNT;k++)
error_output[j][k] = recorded_outputs[j][k].value*(1 - recorded_outputs[j][k].value) * (output_training[j][k].value - recorded_outputs[j][k].value);
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
float errorFactor = 0;
for (l =0;l < OUTPUT_COUNT;l++)
errorFactor += (error_output[j][l]*hidden_layer[k].out_Weights[l]);
error_hidden[j][k] = recorded_hidden[j][k].value*(1 - recorded_hidden[j][k].value) * errorFactor;
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
//TODO update biases
hidden_layer[k].inBias = hidden_layer[k].inBias + LEARNING_RATE *error_hidden[j][k];
for (l = 0;l < INPUT_COUNT;l++)
hidden_layer[k].in_Weights[l] = hidden_layer[k].in_Weights[l] + (LEARNING_RATE*error_hidden[j][k]*input_training[j][l].value)/training_samples;
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
for (l = 0;l < OUTPUT_COUNT;l++)
hidden_layer[k].out_Weights[l] = hidden_layer[k].out_Weights[l] + (LEARNING_RATE*error_output[j][k]*recorded_hidden[j][k].value)/training_samples;
//assign random weights to the neural network's connections
void randweights(Neuron* neurons)
int i;
for (i =0;i< HIDDEN_COUNT;i++)
neurons[i].in_Weights[0] = 2*genRandRange(0,1) - 1;
neurons[i].in_Weights[1] = 2*genRandRange(0,1) - 1;
neurons[i].in_Weights[2] = 2*genRandRange(0,1) - 1;
neurons[i].out_Weights[2] = 2*genRandRange(0,1) - 1;
neurons[i].inBias = 2*genRandRange(0,1) - 1;
int main()
srand(1);
int i,j;
//aquire training data
TData t_data = tData("training.txt");
if (!t_data.sucess)
return 0;
IO_Neuron** training_in = t_data.training_in;
IO_Neuron** training_out = t_data.training_out;
//allocate neural network
IO_Neuron* input_layer = malloc(sizeof(IO_Neuron)*INPUT_COUNT);
Neuron* hidden_layer = malloc(sizeof(Neuron)*HIDDEN_COUNT);
IO_Neuron* output_layer = malloc(sizeof(IO_Neuron)*OUTPUT_COUNT);
randweights(hidden_layer);
//train with training data
train(input_layer,hidden_layer,output_layer,training_in,training_out,t_data.examples,10000);
//test out the learned pattern
input_layer[0].value = 0;
input_layer[1].value = 0;
input_layer[2].value = 0;
//generates the output
think(input_layer,hidden_layer,output_layer);
for (i =0; i < OUTPUT_COUNT;i++)
printf("%fn",output_layer[i].value );
return 0;
Here is a sample file of training data that can be read by the program.
training.txt:
#3,1,7
1,0,1 0
1,0,0 0
1,1,0 1
1,1,1 1
0,1,0 1
0,1,1 1
0,0,1 0
0,0,0 0
In case you have not noticed, the pattern present within the data is that it simply outputs the first number of the input.
The neural network has 3 inputs,3 hidden nodes, and 1 output, these can be changed easily by modifying training data and the constants at the beginning of the code.
I know pure C is not often used for neural networks due to its lack of true object orientation and strict typing but I prefer its simplicity and readability.
c machine-learning neural-network
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
A neural network is a structure of connections and nodes that takes input and generates an output. It can be "taught"(adjusting weights and biases of connections) from a teacher data set with acceptable outputs and inputs.
See https://en.wikipedia.org/wiki/Neural_network for more details.
nn.c:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define INPUT_COUNT 3
#define HIDDEN_COUNT 3
#define OUTPUT_COUNT 1
#define LEARNING_RATE 0.15
typedef struct
float in_Weights[INPUT_COUNT];
float inBias;
float value;
float out_Weights[OUTPUT_COUNT];
Neuron;
typedef struct
float value;
IO_Neuron;
typedef struct
int sucess;
IO_Neuron** training_in;
IO_Neuron** training_out;
int examples;
TData;
//loads training data from a file like format below
/*
#inputs,outputs,count
input1,input2,input3 output1,output2
*/
TData tData(const char* filename)
float genRandRange(float min,float max)
if (min == max)
return min;
float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
return min + scale * ( max - min ); /* [min, max] */
//activation function
float sigmoid(float x)
return 1 / (1 + exp(-x));
float sigmoid_derivative(float x)
return sigmoid(x) * (1 - sigmoid(x));
//computes weighted sum
float dot_summation(float* in,float* weights,int count)
int i;
float result = 0;
for (i =0;i < count;i++)
result += in[i]*weights[i];
return result;
//these functions extract data into an easier to handle format
float* ioValues(IO_Neuron* hidden_layer)
float* ret = malloc(sizeof(float)*INPUT_COUNT);
int i;
for (i =0; i < INPUT_COUNT;i++)
ret[i] = hidden_layer[i].value;
return ret;
float* values(Neuron* hidden_layer)
float* ret = malloc(sizeof(float)*HIDDEN_COUNT);
int i;
for (i =0; i < HIDDEN_COUNT;i++)
ret[i] = hidden_layer[i].value;
return ret;
float* outWeights(Neuron* hidden_layer,int index)
float* ret = malloc(sizeof(float)*HIDDEN_COUNT);
int i;
for (i =0; i < HIDDEN_COUNT;i++)
ret[i] = hidden_layer[i].out_Weights[index];
return ret;
//pass values through the neural network
void think(IO_Neuron* input_layer,Neuron* hidden_layer,IO_Neuron* output_layer)
int i;
float* io_values = ioValues(input_layer);
for (i =0; i < HIDDEN_COUNT;i++)
hidden_layer[i].value = sigmoid(dot_summation(io_values,hidden_layer[i].in_Weights,INPUT_COUNT) + hidden_layer[i].inBias);
free(io_values);
float* hidden_values = values(hidden_layer);
for (i =0; i < OUTPUT_COUNT;i++)
float* out_weights = outWeights(hidden_layer,i);
output_layer[i].value = sigmoid(dot_summation(hidden_values,out_weights,HIDDEN_COUNT));
free(out_weights);
free(hidden_values);
//adjust the neural network's connection weights and biases based upon training data
void train(IO_Neuron* input_layer,Neuron* hidden_layer,IO_Neuron* output_layer,IO_Neuron** input_training,IO_Neuron** output_training,int training_samples,int iterations)
int i,j,k,l;
IO_Neuron recorded_outputs[training_samples][OUTPUT_COUNT];
Neuron recorded_hidden[training_samples][HIDDEN_COUNT];
float error_output[training_samples][OUTPUT_COUNT];//contains output node's delta
float error_hidden[training_samples][HIDDEN_COUNT];
for (i =0; i < iterations;i++)
for (j =0; j < training_samples;j++)
think(input_training[j],hidden_layer,output_layer);
memcpy(recorded_outputs[j],output_layer,sizeof(IO_Neuron)*OUTPUT_COUNT);
memcpy(recorded_hidden[j],hidden_layer,sizeof(Neuron)*HIDDEN_COUNT);
for (j =0; j < training_samples;j++)
for (k =0; k < OUTPUT_COUNT;k++)
error_output[j][k] = recorded_outputs[j][k].value*(1 - recorded_outputs[j][k].value) * (output_training[j][k].value - recorded_outputs[j][k].value);
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
float errorFactor = 0;
for (l =0;l < OUTPUT_COUNT;l++)
errorFactor += (error_output[j][l]*hidden_layer[k].out_Weights[l]);
error_hidden[j][k] = recorded_hidden[j][k].value*(1 - recorded_hidden[j][k].value) * errorFactor;
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
//TODO update biases
hidden_layer[k].inBias = hidden_layer[k].inBias + LEARNING_RATE *error_hidden[j][k];
for (l = 0;l < INPUT_COUNT;l++)
hidden_layer[k].in_Weights[l] = hidden_layer[k].in_Weights[l] + (LEARNING_RATE*error_hidden[j][k]*input_training[j][l].value)/training_samples;
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
for (l = 0;l < OUTPUT_COUNT;l++)
hidden_layer[k].out_Weights[l] = hidden_layer[k].out_Weights[l] + (LEARNING_RATE*error_output[j][k]*recorded_hidden[j][k].value)/training_samples;
//assign random weights to the neural network's connections
void randweights(Neuron* neurons)
int i;
for (i =0;i< HIDDEN_COUNT;i++)
neurons[i].in_Weights[0] = 2*genRandRange(0,1) - 1;
neurons[i].in_Weights[1] = 2*genRandRange(0,1) - 1;
neurons[i].in_Weights[2] = 2*genRandRange(0,1) - 1;
neurons[i].out_Weights[2] = 2*genRandRange(0,1) - 1;
neurons[i].inBias = 2*genRandRange(0,1) - 1;
int main()
srand(1);
int i,j;
//aquire training data
TData t_data = tData("training.txt");
if (!t_data.sucess)
return 0;
IO_Neuron** training_in = t_data.training_in;
IO_Neuron** training_out = t_data.training_out;
//allocate neural network
IO_Neuron* input_layer = malloc(sizeof(IO_Neuron)*INPUT_COUNT);
Neuron* hidden_layer = malloc(sizeof(Neuron)*HIDDEN_COUNT);
IO_Neuron* output_layer = malloc(sizeof(IO_Neuron)*OUTPUT_COUNT);
randweights(hidden_layer);
//train with training data
train(input_layer,hidden_layer,output_layer,training_in,training_out,t_data.examples,10000);
//test out the learned pattern
input_layer[0].value = 0;
input_layer[1].value = 0;
input_layer[2].value = 0;
//generates the output
think(input_layer,hidden_layer,output_layer);
for (i =0; i < OUTPUT_COUNT;i++)
printf("%fn",output_layer[i].value );
return 0;
Here is a sample file of training data that can be read by the program.
training.txt:
#3,1,7
1,0,1 0
1,0,0 0
1,1,0 1
1,1,1 1
0,1,0 1
0,1,1 1
0,0,1 0
0,0,0 0
In case you have not noticed, the pattern present within the data is that it simply outputs the first number of the input.
The neural network has 3 inputs,3 hidden nodes, and 1 output, these can be changed easily by modifying training data and the constants at the beginning of the code.
I know pure C is not often used for neural networks due to its lack of true object orientation and strict typing but I prefer its simplicity and readability.
c machine-learning neural-network
A neural network is a structure of connections and nodes that takes input and generates an output. It can be "taught"(adjusting weights and biases of connections) from a teacher data set with acceptable outputs and inputs.
See https://en.wikipedia.org/wiki/Neural_network for more details.
nn.c:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define INPUT_COUNT 3
#define HIDDEN_COUNT 3
#define OUTPUT_COUNT 1
#define LEARNING_RATE 0.15
typedef struct
float in_Weights[INPUT_COUNT];
float inBias;
float value;
float out_Weights[OUTPUT_COUNT];
Neuron;
typedef struct
float value;
IO_Neuron;
typedef struct
int sucess;
IO_Neuron** training_in;
IO_Neuron** training_out;
int examples;
TData;
//loads training data from a file like format below
/*
#inputs,outputs,count
input1,input2,input3 output1,output2
*/
TData tData(const char* filename)
float genRandRange(float min,float max)
if (min == max)
return min;
float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
return min + scale * ( max - min ); /* [min, max] */
//activation function
float sigmoid(float x)
return 1 / (1 + exp(-x));
float sigmoid_derivative(float x)
return sigmoid(x) * (1 - sigmoid(x));
//computes weighted sum
float dot_summation(float* in,float* weights,int count)
int i;
float result = 0;
for (i =0;i < count;i++)
result += in[i]*weights[i];
return result;
//these functions extract data into an easier to handle format
float* ioValues(IO_Neuron* hidden_layer)
float* ret = malloc(sizeof(float)*INPUT_COUNT);
int i;
for (i =0; i < INPUT_COUNT;i++)
ret[i] = hidden_layer[i].value;
return ret;
float* values(Neuron* hidden_layer)
float* ret = malloc(sizeof(float)*HIDDEN_COUNT);
int i;
for (i =0; i < HIDDEN_COUNT;i++)
ret[i] = hidden_layer[i].value;
return ret;
float* outWeights(Neuron* hidden_layer,int index)
float* ret = malloc(sizeof(float)*HIDDEN_COUNT);
int i;
for (i =0; i < HIDDEN_COUNT;i++)
ret[i] = hidden_layer[i].out_Weights[index];
return ret;
//pass values through the neural network
void think(IO_Neuron* input_layer,Neuron* hidden_layer,IO_Neuron* output_layer)
int i;
float* io_values = ioValues(input_layer);
for (i =0; i < HIDDEN_COUNT;i++)
hidden_layer[i].value = sigmoid(dot_summation(io_values,hidden_layer[i].in_Weights,INPUT_COUNT) + hidden_layer[i].inBias);
free(io_values);
float* hidden_values = values(hidden_layer);
for (i =0; i < OUTPUT_COUNT;i++)
float* out_weights = outWeights(hidden_layer,i);
output_layer[i].value = sigmoid(dot_summation(hidden_values,out_weights,HIDDEN_COUNT));
free(out_weights);
free(hidden_values);
//adjust the neural network's connection weights and biases based upon training data
void train(IO_Neuron* input_layer,Neuron* hidden_layer,IO_Neuron* output_layer,IO_Neuron** input_training,IO_Neuron** output_training,int training_samples,int iterations)
int i,j,k,l;
IO_Neuron recorded_outputs[training_samples][OUTPUT_COUNT];
Neuron recorded_hidden[training_samples][HIDDEN_COUNT];
float error_output[training_samples][OUTPUT_COUNT];//contains output node's delta
float error_hidden[training_samples][HIDDEN_COUNT];
for (i =0; i < iterations;i++)
for (j =0; j < training_samples;j++)
think(input_training[j],hidden_layer,output_layer);
memcpy(recorded_outputs[j],output_layer,sizeof(IO_Neuron)*OUTPUT_COUNT);
memcpy(recorded_hidden[j],hidden_layer,sizeof(Neuron)*HIDDEN_COUNT);
for (j =0; j < training_samples;j++)
for (k =0; k < OUTPUT_COUNT;k++)
error_output[j][k] = recorded_outputs[j][k].value*(1 - recorded_outputs[j][k].value) * (output_training[j][k].value - recorded_outputs[j][k].value);
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
float errorFactor = 0;
for (l =0;l < OUTPUT_COUNT;l++)
errorFactor += (error_output[j][l]*hidden_layer[k].out_Weights[l]);
error_hidden[j][k] = recorded_hidden[j][k].value*(1 - recorded_hidden[j][k].value) * errorFactor;
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
//TODO update biases
hidden_layer[k].inBias = hidden_layer[k].inBias + LEARNING_RATE *error_hidden[j][k];
for (l = 0;l < INPUT_COUNT;l++)
hidden_layer[k].in_Weights[l] = hidden_layer[k].in_Weights[l] + (LEARNING_RATE*error_hidden[j][k]*input_training[j][l].value)/training_samples;
for (j =0; j < training_samples;j++)
for (k =0; k < HIDDEN_COUNT;k++)
for (l = 0;l < OUTPUT_COUNT;l++)
hidden_layer[k].out_Weights[l] = hidden_layer[k].out_Weights[l] + (LEARNING_RATE*error_output[j][k]*recorded_hidden[j][k].value)/training_samples;
//assign random weights to the neural network's connections
void randweights(Neuron* neurons)
int i;
for (i =0;i< HIDDEN_COUNT;i++)
neurons[i].in_Weights[0] = 2*genRandRange(0,1) - 1;
neurons[i].in_Weights[1] = 2*genRandRange(0,1) - 1;
neurons[i].in_Weights[2] = 2*genRandRange(0,1) - 1;
neurons[i].out_Weights[2] = 2*genRandRange(0,1) - 1;
neurons[i].inBias = 2*genRandRange(0,1) - 1;
int main()
srand(1);
int i,j;
//aquire training data
TData t_data = tData("training.txt");
if (!t_data.sucess)
return 0;
IO_Neuron** training_in = t_data.training_in;
IO_Neuron** training_out = t_data.training_out;
//allocate neural network
IO_Neuron* input_layer = malloc(sizeof(IO_Neuron)*INPUT_COUNT);
Neuron* hidden_layer = malloc(sizeof(Neuron)*HIDDEN_COUNT);
IO_Neuron* output_layer = malloc(sizeof(IO_Neuron)*OUTPUT_COUNT);
randweights(hidden_layer);
//train with training data
train(input_layer,hidden_layer,output_layer,training_in,training_out,t_data.examples,10000);
//test out the learned pattern
input_layer[0].value = 0;
input_layer[1].value = 0;
input_layer[2].value = 0;
//generates the output
think(input_layer,hidden_layer,output_layer);
for (i =0; i < OUTPUT_COUNT;i++)
printf("%fn",output_layer[i].value );
return 0;
Here is a sample file of training data that can be read by the program.
training.txt:
#3,1,7
1,0,1 0
1,0,0 0
1,1,0 1
1,1,1 1
0,1,0 1
0,1,1 1
0,0,1 0
0,0,0 0
In case you have not noticed, the pattern present within the data is that it simply outputs the first number of the input.
The neural network has 3 inputs,3 hidden nodes, and 1 output, these can be changed easily by modifying training data and the constants at the beginning of the code.
I know pure C is not often used for neural networks due to its lack of true object orientation and strict typing but I prefer its simplicity and readability.
c machine-learning neural-network
edited Apr 8 at 0:38
JDÃ Âugosz
5,047731
5,047731
asked Apr 7 at 22:29
J. H
574
574
add a comment |Â
add a comment |Â
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191498%2fsimple-neural-network-in-c%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password