From c5aa7ab9060263d0e626b241a7269649a0403a63 Mon Sep 17 00:00:00 2001 From: Soikk <76824648+Soikk@users.noreply.github.com> Date: Tue, 23 Aug 2022 13:37:28 +0200 Subject: [PATCH] Reorganized nnet --- main.c | 24 ++++++++ nnet.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ nnet.h | 69 +++++++++++++++++++++++ 3 files changed, 267 insertions(+) create mode 100644 main.c create mode 100644 nnet.c create mode 100644 nnet.h diff --git a/main.c b/main.c new file mode 100644 index 0000000..4316424 --- /dev/null +++ b/main.c @@ -0,0 +1,24 @@ +#include +#include +#include "../libs/nnet.h" + + +int main(){ + + neuron *n1 = createNeuron(0.25, SIGMOID, 2, 0.5, -0.5); + neuron *n2 = createNeuron(-0.25, SIGMOID, 2, -0.5, 0.2); + neuron *n3 = createNeuron(1, SIGMOID, 2, 1.0, -1); + neuron *n4 = createNeuron(1, SIGMOID, 3, 0.35, -0.3, 0.75); + neuron *n5 = createNeuron(-1, SIGMOID, 3, 0.25, -0.4, 0.75); + neuron *n6 = createNeuron(0.8, SIGMOID, 2, -0.9, 0.9); + + layer l1 = createLayer(3, n1, n2, n4); + layer l2 = createLayer(2, n4, n5); + layer l3 = createLayer(1, n6); + net nt = createNet(3, l1, l2, l3); + + double *end = propagate(&nt, 1.0, 1.0); + printf("%lf\n", end[0]); + + return 0; +} diff --git a/nnet.c b/nnet.c new file mode 100644 index 0000000..3bfdb71 --- /dev/null +++ b/nnet.c @@ -0,0 +1,174 @@ +#include "nnet.h" + + + +static branch emptyBranch = {.data = 0.0, .weight = 0.0}; + +static neuron emptyNeuron = {.function = LINEAR, .size = 0, .branches = &emptyBranch, .bias = 0.0, .out = 0.0}; + + +double drand(double high, double low){ + srand(time(NULL)); + return ((double)rand()*(high-low))/(double)RAND_MAX + low; +} + +branch createBranch(double weight, double data){ + branch b = {.weight = weight, .data = data}; + return b; +} + +neuron *createNeuron(double bias, functions function, int size, ...){ + neuron *n = malloc(sizeof(neuron)); + n->bias = bias; + n->function = function; + n->size = size; + n->branches = malloc(size*sizeof(branch)); + va_list wargs; + va_start(wargs, size); + for(int i = 0; i < size; ++i) + n->branches[i] = createBranch(va_arg(wargs, double), 0.0); + n->out = 0; + va_end(wargs); + return n; +} + +void addBranch(neuron *n, double weight){ + branch *tmp = malloc((n->size+1)*sizeof(branch)); + memmove(tmp, n->branches, n->size*sizeof(branch)); + tmp[n->size] = createBranch(weight, 0.0); + n->branches = tmp; + n->size++; +} + +void addBranches(neuron *n, int size, double *data){ + for(int i = 0; i < size; ++i) + addBranch(n, data[i]); +} + +void changeFunction(neuron *n, functions function){ + n->function = function; +} + +int changeWeight(neuron *n, int pos, double weight){ + if(pos >= 0 && pos < n->size){ + n->branches[pos].weight = weight; + return 0; + } + return -1; +} + +int inputNeuron(neuron *n, int pos, double data){ + if(pos >= 0 && pos < n->size){ + n->branches[pos].data = data; + return 0; + } + return -1; +} + +double rawValue(neuron *n){ + double v = n->bias; + printf("0 "); + for(int i = 0; i < n->size; ++i){ + printf("+ %.5lf + %.5lf*%.5lf ", n->bias, n->branches[i].data, n->branches[i].weight); + v += n->branches[i].data*n->branches[i].weight; + } + printf("= %.5lf\n", v); + return v; +} + +double outputNeuron(neuron *n){ + double x = rawValue(n); + switch(n->function){ + case LINEAR: + n->out = x; + break; + case SIGMOID: + n->out = (double)(1.0/(1.0+exp(-x))); + } + return n->out; +} + +layer createLayer(int size, ...){ + layer l; + l.size = size; + l.neurons = malloc(size*sizeof(neuron*)); + for(int i = 0; i < size; ++i) + l.neurons[i] = malloc(sizeof(neuron)); + va_list nargs; + va_start(nargs, size); + int done = 0; + for(int i = 0; i < size; ++i){ + neuron *a = va_arg(nargs, neuron*); + if(a == NULL) + done = 1; + if(done) + l.neurons[i] = &emptyNeuron; + else + l.neurons[i] = a; + } + va_end(nargs); + return l; +} + +net createNet(int layers, ...){ + net nt; + nt.layers = layers; + nt.head = NULL; + va_list largs; + va_start(largs, layers); + for(int i = 0; i < layers; ++i){ + lnode *tmp = malloc(sizeof(lnode)); + tmp->layer = va_arg(largs, layer); + tmp->next = NULL; + if(nt.head != NULL){ + lnode *act = nt.head; + while(act->next != NULL) + act = act->next; + act->next = tmp; + }else{ + nt.head = tmp; + } + } + va_end(largs); + return nt; +} + +double *propagateLayer(layer *l, int size, double *data){ + double *result = malloc(l->size*sizeof(double)); + for(int i = 0; i < l->size; ++i){ + if(l->neurons[i]->size < size){ + int diff = size - l->neurons[i]->size; + printf("Creando %d mas\n", diff); + double *weights = malloc(diff*sizeof(double)); + for(int j = 0; j < diff; ++j) + weights[j] = drand(2, -2); + addBranches(l->neurons[i], diff, weights); + } + for(int j = 0; j < size; ++j) + inputNeuron(l->neurons[i], j, data[j]); + result[i] = outputNeuron(l->neurons[i]); + } + return result; +} + +double *propagate(net *nt, ...){ + if(nt->head != NULL){ + va_list ntargs; + va_start(ntargs, nt); + lnode *tmp = nt->head; + for(int i = 0; i < tmp->layer.size; ++i) + inputNeuron(tmp->layer.neurons[i], 0, va_arg(ntargs, double)); + double *data = malloc(tmp->layer.size*sizeof(double)); + for(int i = 0; i < tmp->layer.size; ++i) + data[i] = outputNeuron(tmp->layer.neurons[i]); + int size; + while(tmp->next != NULL){ + size = tmp->layer.size; + double *tmpdata = propagateLayer(&tmp->next->layer, size, data); + data = tmpdata; + tmp = tmp->next; + } + return data; + } + return NULL; +} diff --git a/nnet.h b/nnet.h new file mode 100644 index 0000000..81f7574 --- /dev/null +++ b/nnet.h @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include + + +typedef enum{ + LINEAR, + SIGMOID, +} functions; + +typedef struct{ + double weight; + double data; +} branch; + +typedef struct{ + functions function; + int size; + branch *branches; + double bias; + double out; +} neuron; + +typedef struct{ + int size; + neuron **neurons; +} layer; + +typedef struct lnode{ + layer layer; + struct lnode *next; +} lnode; + +typedef struct{ + int layers; + lnode *head; +} net; + + +double drand(double high, double low); + +branch createBranch(double weight, double data); + +neuron *createNeuron(double bias, functions function, int size, ...); + +void addBranch(neuron *n, double weight); + +void addBranches(neuron *n, int size, double *data); + +void changeFunction(neuron *n, functions function); + +int changeWeight(neuron *n, int pos, double weight); + +int inputNeuron(neuron *n, int pos, double data); + +double rawValue(neuron *n); + +double outputNeuron(neuron *n); + +layer createLayer(int size, ...); + +net createNet(int layers, ...); + +double *propagateLayer(layer *l, int size, double *data); + +double *propagate(net *nt, ...); -- 2.39.5