Initial commit
This commit is contained in:
parent
eaaec5227c
commit
29cbc53cbc
1
.gitignore
vendored
1
.gitignore
vendored
@ -52,3 +52,4 @@ Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
csv/
|
||||
|
17
headers/file.h
Normal file
17
headers/file.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#ifndef _file_h_
|
||||
#define _file_h_
|
||||
|
||||
typedef struct {
|
||||
FILE *file;
|
||||
char *file_name;
|
||||
} File;
|
||||
|
||||
File *new_file(char *file_name);
|
||||
void free_file(File *f);
|
||||
double get_entry(File *f, int row, int col, char sep);
|
||||
int get_columns_num(File *f, int row, char sep);
|
||||
int get_rows_num(File *f);
|
||||
|
||||
#endif
|
17
headers/layer.h
Normal file
17
headers/layer.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#ifndef _layer_h_
|
||||
#define _layer_h_
|
||||
|
||||
#include "../headers/perceptron.h"
|
||||
|
||||
typedef struct {
|
||||
int p_num;
|
||||
Perceptron **p;
|
||||
} Layer;
|
||||
|
||||
Layer *new_layer(int p_num, int i_num);
|
||||
Layer *new_input_layer(int p_num);
|
||||
void free_layer(Layer *l);
|
||||
|
||||
#endif
|
16
headers/neural_net.h
Normal file
16
headers/neural_net.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#ifndef _neural_net_h_
|
||||
#define _neural_net_h_
|
||||
|
||||
#include "layer.h"
|
||||
|
||||
typedef struct {
|
||||
int l_num;
|
||||
Layer **l;
|
||||
} NeuralNet;
|
||||
|
||||
NeuralNet *new_neural_net(char *c_file_name, char *i_file_name);
|
||||
void free_neural_net(NeuralNet *n);
|
||||
|
||||
#endif
|
15
headers/perceptron.h
Normal file
15
headers/perceptron.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#ifndef _perceptron_h_
|
||||
#define _perceptron_h_
|
||||
|
||||
typedef struct {
|
||||
int i_num;
|
||||
double *weights;
|
||||
double output;
|
||||
} Perceptron;
|
||||
|
||||
Perceptron *new_perceptron(int i_num);
|
||||
void free_perceptron(Perceptron *p);
|
||||
|
||||
#endif
|
9
headers/training.h
Normal file
9
headers/training.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#ifndef _training_h_
|
||||
#define _training_h_
|
||||
|
||||
void train_by_backpropagation(NeuralNet *n, int runs, double t_factor,
|
||||
char *i_name, char *t_name);
|
||||
|
||||
#endif
|
99
src/file.c
Normal file
99
src/file.c
Normal file
@ -0,0 +1,99 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../headers/file.h"
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
|
||||
File
|
||||
*new_file(char *file_name)
|
||||
{
|
||||
File *f;
|
||||
|
||||
if ((f = malloc(sizeof(File))) == NULL) {
|
||||
fprintf(stderr, "memory for file was not allocated.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
f->file_name = file_name;
|
||||
//fprintf(stderr, "%s\n", f->file_name);
|
||||
|
||||
if ((f->file = fopen(f->file_name, "r")) == NULL) {
|
||||
fprintf(stderr, "file %s was not opened.\n",
|
||||
f->file_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
void
|
||||
free_file(File *f)
|
||||
{
|
||||
if (fclose(f->file) == EOF) {
|
||||
fprintf(stderr, "file %s was not closed.\n",
|
||||
f->file_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
free(f);
|
||||
}
|
||||
|
||||
double
|
||||
get_entry(File *f, int row, int col, char sep)
|
||||
{
|
||||
int i;
|
||||
char buf[BUF_SIZE];
|
||||
double x;
|
||||
|
||||
rewind(f->file);
|
||||
|
||||
for (i=0; i<row; i++)
|
||||
fgets(buf, BUF_SIZE, f->file);
|
||||
|
||||
for (i=0; i<col; i++) {
|
||||
while (fgetc(f->file) != sep)
|
||||
;
|
||||
}
|
||||
|
||||
fscanf(f->file, "%lf", &x);
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
get_columns_num(File *f, int row, char sep)
|
||||
{
|
||||
int i, count;
|
||||
char c, buf[BUF_SIZE];
|
||||
|
||||
c = '0';
|
||||
count = 1;
|
||||
rewind(f->file);
|
||||
|
||||
for (i=0; i<row; i++)
|
||||
fgets(buf, BUF_SIZE, f->file);
|
||||
|
||||
while (c != '\n') {
|
||||
c = fgetc(f->file);
|
||||
if (c == sep)
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
get_rows_num(File *f)
|
||||
{
|
||||
char buf[BUF_SIZE];
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
rewind(f->file);
|
||||
|
||||
while (fgets(buf, BUF_SIZE, f->file))
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
66
src/layer.c
Normal file
66
src/layer.c
Normal file
@ -0,0 +1,66 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../headers/layer.h"
|
||||
|
||||
Layer
|
||||
*new_layer(int p_num, int i_num)
|
||||
{
|
||||
int i;
|
||||
Layer *l;
|
||||
|
||||
l = malloc(sizeof(Layer));
|
||||
|
||||
l->p_num = p_num;
|
||||
|
||||
l->p = calloc(l->p_num, sizeof(Perceptron *));
|
||||
|
||||
for (i=0; i<l->p_num; i++) {
|
||||
l->p[i] = new_perceptron(i_num);
|
||||
}
|
||||
|
||||
if (l==NULL || l->p==NULL) {
|
||||
fprintf(stderr, "memory for layer was not allocated.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
Layer
|
||||
*new_input_layer(int p_num)
|
||||
{
|
||||
int i;
|
||||
Layer *l;
|
||||
|
||||
l = malloc(sizeof(Layer));
|
||||
|
||||
l->p_num = p_num;
|
||||
|
||||
l->p = calloc(l->p_num, sizeof(Perceptron *));
|
||||
|
||||
for (i=0; i<l->p_num; i++) {
|
||||
l->p[i] = new_perceptron(1);
|
||||
}
|
||||
|
||||
if (l==NULL || l->p==NULL) {
|
||||
fprintf(stderr, "memory for layer was not allocated.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
free_layer(Layer *l)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<l->p_num; i++) {
|
||||
free_perceptron(l->p[i]);
|
||||
}
|
||||
free(l->p);
|
||||
free(l);
|
||||
}
|
22
src/main.c
Normal file
22
src/main.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../headers/file.h"
|
||||
#include "../headers/neural_net.h"
|
||||
#include "../headers/training.h"
|
||||
|
||||
#define N 100000
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
NeuralNet *n = new_neural_net(argv[1], argv[2]);
|
||||
|
||||
train_by_backpropagation(n, N, 1, argv[2], argv[3]);
|
||||
|
||||
free_neural_net(n);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
59
src/neural_net.c
Normal file
59
src/neural_net.c
Normal file
@ -0,0 +1,59 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../headers/file.h"
|
||||
#include "../headers/neural_net.h"
|
||||
|
||||
NeuralNet
|
||||
*new_neural_net(char *c_file_name, char *i_file_name)
|
||||
{
|
||||
int i;
|
||||
NeuralNet *n;
|
||||
File *c_file = new_file(c_file_name);
|
||||
File *i_file = new_file(i_file_name);
|
||||
|
||||
n = malloc(sizeof(NeuralNet));
|
||||
n->l_num = get_columns_num(c_file, 0, ',');
|
||||
n->l = calloc(n->l_num, sizeof(Layer *));
|
||||
int p_num[n->l_num];
|
||||
int i_num[n->l_num];
|
||||
|
||||
for (i=0; i<n->l_num-1; i++) {
|
||||
p_num[i] = get_entry(c_file, 0, i, ',') + 1;
|
||||
}
|
||||
p_num[n->l_num-1] = get_entry(c_file, 0, n->l_num-1, ',');
|
||||
|
||||
i_num[0] = get_columns_num(i_file, 0, ',');
|
||||
for (i=1; i<n->l_num; i++) {
|
||||
i_num[i] = p_num[i-1];
|
||||
}
|
||||
|
||||
free_file(c_file);
|
||||
free_file(i_file);
|
||||
|
||||
n->l[0] = new_input_layer(p_num[0]);
|
||||
for (i=1; i<n->l_num; i++) {
|
||||
n->l[i] = new_layer(p_num[i], i_num[i]);
|
||||
}
|
||||
|
||||
if (n==NULL || n->l==NULL) {
|
||||
fprintf(stderr, "memory for neural net was not allocated.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
free_neural_net(NeuralNet *n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<n->l_num; i++) {
|
||||
free_layer(n->l[i]);
|
||||
}
|
||||
free(n->l);
|
||||
free(n);
|
||||
}
|
30
src/perceptron.c
Normal file
30
src/perceptron.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../headers/perceptron.h"
|
||||
|
||||
Perceptron
|
||||
*new_perceptron(int i_num)
|
||||
{
|
||||
Perceptron *p;
|
||||
|
||||
p = malloc(sizeof(Perceptron));
|
||||
p->i_num = i_num;
|
||||
p->weights = calloc(i_num, sizeof(double));
|
||||
|
||||
if (p==NULL || p->weights==NULL) {
|
||||
fprintf(stderr, "memory for perceptron was not allocated.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
free_perceptron(Perceptron *p)
|
||||
{
|
||||
free(p->weights);
|
||||
free(p);
|
||||
}
|
277
src/training.c
Normal file
277
src/training.c
Normal file
@ -0,0 +1,277 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../headers/file.h"
|
||||
#include "../headers/neural_net.h"
|
||||
|
||||
typedef struct {
|
||||
File *i_file;
|
||||
File *t_file;
|
||||
double t_factor;
|
||||
int rows_num;
|
||||
double *output_deltas;
|
||||
double **small_deltas;
|
||||
double ***weight_deltas;
|
||||
} TrainingInfo;
|
||||
|
||||
static TrainingInfo *new_training_info(NeuralNet *n, char *i_name,
|
||||
char *t_name, double t_factor);
|
||||
static void free_training_info(NeuralNet *n, TrainingInfo *t);
|
||||
static void init_inputs(NeuralNet *n);
|
||||
static void init_weights(NeuralNet *n);
|
||||
static void set_input_layer(NeuralNet *n, TrainingInfo *t, int i_file_row);
|
||||
static void calculate_outputs(NeuralNet *n);
|
||||
static void calculate_output_deltas(NeuralNet *n, TrainingInfo *t, int row);
|
||||
static void calculate_small_deltas(NeuralNet *n, TrainingInfo *t);
|
||||
static void calculate_weight_deltas(NeuralNet *n, TrainingInfo *t);
|
||||
static void calculate_weights(NeuralNet *n, TrainingInfo *t);
|
||||
static void print_weights(NeuralNet *n);
|
||||
|
||||
void
|
||||
train_by_backpropagation(NeuralNet *n, int runs, double t_factor, char *i_name,
|
||||
char *t_name)
|
||||
{
|
||||
int i, j;
|
||||
TrainingInfo *t;
|
||||
|
||||
t = new_training_info(n, i_name, t_name, t_factor);
|
||||
init_inputs(n);
|
||||
init_weights(n);
|
||||
|
||||
for (i=0; i<runs; i++) {
|
||||
for (j=0; j<t->rows_num; j++) {
|
||||
set_input_layer(n, t, j);
|
||||
calculate_outputs(n);
|
||||
calculate_output_deltas(n, t, j);
|
||||
calculate_small_deltas(n, t);
|
||||
calculate_weight_deltas(n, t);
|
||||
calculate_weights(n, t);
|
||||
}
|
||||
}
|
||||
print_weights(n);
|
||||
|
||||
free_training_info(n, t);
|
||||
}
|
||||
|
||||
static TrainingInfo
|
||||
*new_training_info(NeuralNet *n, char *i_name, char *t_name, double t_factor)
|
||||
{
|
||||
int i, j;
|
||||
TrainingInfo *t;
|
||||
|
||||
t = malloc(sizeof(TrainingInfo));
|
||||
t->i_file = new_file(i_name);
|
||||
t->t_file = new_file(t_name);
|
||||
t->t_factor = t_factor;
|
||||
t->rows_num = get_rows_num(t->i_file);
|
||||
t->output_deltas = calloc(n->l[n->l_num-1]->p_num, sizeof(double));
|
||||
t->small_deltas = calloc(n->l_num-1, sizeof(double *));
|
||||
for (i=0; i<n->l_num; i++) {
|
||||
t->small_deltas[i] = calloc(n->l[i]->p_num, sizeof(double));
|
||||
}
|
||||
t->weight_deltas = calloc(n->l_num-1, sizeof(double **));
|
||||
for (i=1; i<n->l_num; i++) {
|
||||
t->weight_deltas[i] = calloc(n->l[i]->p_num, sizeof(double *));
|
||||
for (j=0; j<n->l[i]->p_num; j++) {
|
||||
t->weight_deltas[i][j] = calloc(n->l[i-1]->p_num,
|
||||
sizeof(double));
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void
|
||||
free_training_info(NeuralNet *n, TrainingInfo *t)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
free_file(t->i_file);
|
||||
free_file(t->t_file);
|
||||
|
||||
free(t->output_deltas);
|
||||
for (i=1; i<n->l_num; i++) {
|
||||
free(t->small_deltas[i]);
|
||||
}
|
||||
free(t->small_deltas);
|
||||
for (i=1; i<n->l_num; i++) {
|
||||
for (j=0; j<n->l[i]->p_num; j++) {
|
||||
free(t->weight_deltas[i][j]);
|
||||
}
|
||||
free(t->weight_deltas[i]);
|
||||
}
|
||||
free(t->weight_deltas);
|
||||
free(t);
|
||||
}
|
||||
|
||||
static void
|
||||
init_inputs(NeuralNet *n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<n->l_num-1; i++) {
|
||||
n->l[i]->p[0]->output = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_weights(NeuralNet *n)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
srand(time(NULL));
|
||||
for (i=1; i<n->l_num; i++) {
|
||||
for (j=1; j<n->l[i]->p_num; j++) {
|
||||
for (k=0; k<n->l[i]->p[j]->i_num; k++) {
|
||||
n->l[i]->p[j]->weights[k] = (double) rand()
|
||||
/ RAND_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_input_layer(NeuralNet *n, TrainingInfo *t, int i_file_row)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1; i<n->l[0]->p_num-1; i++) {
|
||||
n->l[0]->p[i]->output =
|
||||
get_entry(t->i_file, i_file_row, i, ',');
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_outputs(NeuralNet *n)
|
||||
{
|
||||
int i, j, k;
|
||||
int x;
|
||||
|
||||
for (i=1; i<n->l_num; i++) {
|
||||
for (j=1; j<n->l[i]->p_num; j++) {
|
||||
x = 0;
|
||||
for (k=0; k<n->l[i]->p[j]->i_num; k++) {
|
||||
x -= n->l[i]->p[j]->weights[k] *
|
||||
n->l[i-1]->p[k]->output;
|
||||
}
|
||||
n->l[i]->p[j]->output = 1 / (1 + exp(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_output_deltas(NeuralNet *n, TrainingInfo *t, int row)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<n->l[n->l_num-1]->p_num; i++) {
|
||||
t->output_deltas[i] = get_entry(t->t_file, row, i, ',')
|
||||
- n->l[n->l_num-1]->p[i]->output;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_small_deltas(NeuralNet *n, TrainingInfo *t)
|
||||
{
|
||||
int i, j, k;
|
||||
double sum;
|
||||
|
||||
for (i=0; i<n->l[n->l_num-1]->p_num; i++) {
|
||||
t->small_deltas[n->l_num-1][i] = t->output_deltas[i]
|
||||
* (1 - n->l[n->l_num-1]->p[i]->output)
|
||||
* n->l[n->l_num-1]->p[i]->output;
|
||||
}
|
||||
|
||||
sum = 0;
|
||||
for (i=0; i<n->l[n->l_num-2]->p_num; i++) {
|
||||
sum += t->small_deltas[n->l_num-1][i];
|
||||
}
|
||||
for (i=1; i<n->l[n->l_num-2]->p_num; i++) {
|
||||
for (j=0; j<n->l[n->l_num-1]->p_num; j++) {
|
||||
t->small_deltas[n->l_num-2][i-1]
|
||||
= (1 - n->l[n->l_num-2]->p[j]->output)
|
||||
* n->l[n->l_num-2]->p[j]->output
|
||||
* sum
|
||||
* n->l[n->l_num-1]->p[j]->weights[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i=n->l_num-3; i>0; i--) {
|
||||
sum = 0;
|
||||
for (j=1; j<n->l[i+1]->p_num; j++) {
|
||||
sum += t->small_deltas[i+1][j-1];
|
||||
}
|
||||
for (j=0; j<n->l[i]->p_num; j++) {
|
||||
for (k=1; k<n->l[i+1]->p_num; k++) {
|
||||
t->small_deltas[i][j]
|
||||
= (1 - n->l[i]->p[k]->output)
|
||||
* n->l[i]->p[k]->output
|
||||
* sum
|
||||
* n->l[i+1]->p[k]->weights[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_weight_deltas(NeuralNet *n, TrainingInfo *t)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
for (i=n->l_num-1; i>0; i--) {
|
||||
for (j=0; j<n->l[i]->p_num; j++) {
|
||||
for (k=0; k<n->l[i-1]->p_num; k++) {
|
||||
t->weight_deltas[i][j][k] = t->t_factor
|
||||
* t->small_deltas[i][j]
|
||||
* n->l[i-1]->p[k]->output;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_weights(NeuralNet *n, TrainingInfo *t)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
for (i=n->l_num-1; i>0; i--) {
|
||||
for (j=0; j<n->l[i]->p_num; j++) {
|
||||
for (k=0; k<n->l[i-1]->p_num; k++) {
|
||||
n->l[i]->p[j]->weights[k]
|
||||
= n->l[i]->p[j]->weights[k]
|
||||
- t->weight_deltas[i][j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_weights(NeuralNet *n)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
for (i=1; i<n->l_num-1; i++) {
|
||||
fprintf(stderr, "L %d", i);
|
||||
for (j=1; j<n->l[i]->p_num; j++) {
|
||||
fprintf(stderr, "\tP %d\n", j);
|
||||
for (k=0; k<n->l[i-1]->p_num; k++) {
|
||||
printf("%lf,", n->l[i]->p[j]->weights[k]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
fprintf(stderr, "L %d", i);
|
||||
for (i=0; i<n->l[n->l_num-1]->p_num; i++) {
|
||||
fprintf(stderr, "\tP %d\n", i);
|
||||
for (j=0; j<n->l[n->l_num-2]->p_num; j++) {
|
||||
printf("%lf,", n->l[n->l_num-1]->p[i]->weights[j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user