]> git.xolatile.top Git - soikk-nnet.git/commitdiff
Reorganized nnet
authorSoikk <76824648+Soikk@users.noreply.github.com>
Tue, 23 Aug 2022 11:37:28 +0000 (13:37 +0200)
committerSoikk <76824648+Soikk@users.noreply.github.com>
Tue, 23 Aug 2022 11:37:28 +0000 (13:37 +0200)
main.c [new file with mode: 0644]
nnet.c [new file with mode: 0644]
nnet.h [new file with mode: 0644]

diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..4316424
--- /dev/null
+++ b/main.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <stdlib.h>
+#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 (file)
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 (file)
index 0000000..81f7574
--- /dev/null
+++ b/nnet.h
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+
+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, ...);