aboutsummaryrefslogtreecommitdiff
path: root/nnet.c
diff options
context:
space:
mode:
authorSoikk2022-08-23 13:37:28 +0200
committerSoikk2022-08-23 13:37:28 +0200
commitc5aa7ab9060263d0e626b241a7269649a0403a63 (patch)
treeca7755607aabf58ba999bfb9ea741cf2bb5d5ac3 /nnet.c
parent5f54e35503ec4483d73c30f904fbbb5fc7d628e5 (diff)
downloadsoikk-nnet-c5aa7ab9060263d0e626b241a7269649a0403a63.tar.xz
soikk-nnet-c5aa7ab9060263d0e626b241a7269649a0403a63.tar.zst
Reorganized nnet
Diffstat (limited to 'nnet.c')
-rw-r--r--nnet.c174
1 files changed, 174 insertions, 0 deletions
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;
+}