diff options
Diffstat (limited to 'nnet.c')
| -rw-r--r-- | nnet.c | 174 |
1 files changed, 174 insertions, 0 deletions
@@ -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; +} |
