From 19efa5f7d6984dce0d092dc3bab1a23a391575c5 Mon Sep 17 00:00:00 2001 From: Julien Chemillier Date: Tue, 5 Jul 2022 08:13:25 +0200 Subject: [PATCH] Seperation in files of cnn.c --- src/mnist_cnn/cnn.c | 526 +-------------------------------- src/mnist_cnn/cnn.h | 105 ++----- src/mnist_cnn/creation.c | 162 ++++++++++ src/mnist_cnn/creation.h | 46 +++ src/mnist_cnn/free.c | 106 +++++++ src/mnist_cnn/free.h | 46 +++ src/mnist_cnn/function.c | 93 ++++++ src/mnist_cnn/function.h | 43 +++ src/mnist_cnn/initialisation.c | 52 ++++ src/mnist_cnn/initialisation.h | 33 +++ src/mnist_cnn/make.c | 78 +++++ src/mnist_cnn/make.h | 26 ++ src/mnist_cnn/struct.h | 44 +++ 13 files changed, 757 insertions(+), 603 deletions(-) create mode 100644 src/mnist_cnn/creation.c create mode 100644 src/mnist_cnn/creation.h create mode 100644 src/mnist_cnn/free.c create mode 100644 src/mnist_cnn/free.h create mode 100644 src/mnist_cnn/function.c create mode 100644 src/mnist_cnn/function.h create mode 100644 src/mnist_cnn/initialisation.c create mode 100644 src/mnist_cnn/initialisation.h create mode 100644 src/mnist_cnn/make.c create mode 100644 src/mnist_cnn/make.h create mode 100644 src/mnist_cnn/struct.h diff --git a/src/mnist_cnn/cnn.c b/src/mnist_cnn/cnn.c index 9e51997..ee5ca40 100644 --- a/src/mnist_cnn/cnn.c +++ b/src/mnist_cnn/cnn.c @@ -1,342 +1,19 @@ #include #include -#include #include #include - +#include "function.h" +#include "make.h" #include "cnn.h" -#define PADING_INPUT 2 // Augmente les dimensions de l'image d'entrée -#define RAND_FLT() ((float)rand())/((float)RAND_MAX) // Génère un flotant entre 0 et 1 - -// Les dérivées sont l'opposé -#define TANH 1 -#define SIGMOID 2 -#define RELU 3 -#define SOFTMAX 4 - -#define ZERO 0 -#define GLOROT_NORMAL 1 -#define GLOROT_UNIFROM 2 -#define HE_NORMAL 3 -#define HE_UNIFORM 4 - -// Penser à mettre srand(time(NULL)); (pour les proba de dropout) - - -float max(float a, float b) { - return a 0) - return 1; - return 0; -} - -float tanh_(float x) { - return tanh(x); -} - -float tanh_derivative(float x) { - float a = tanh(x); - return 1 - a*a; -} - -void apply_softmax_input(float ***input, int depth, int rows, int columns) { - int i, j, k; - float m = FLT_MIN; - float sum=0; - for (i=0; i100) { - printf("Erreur, la probabilité de dropout n'est pas respecté, elle doit être comprise entre 0 et 100\n"); - } - Network* network = malloc(sizeof(Network)); - network->max_size = max_size; - network->dropout = dropout; - network->initialisation = initialisation; - network->size = 1; - network->input = malloc(sizeof(float***)*max_size); - network->kernel = malloc(sizeof(Kernel)*(max_size-1)); - create_a_cube_input_layer(network, 0, input_depth, input_dim); - int i, j; - network->dim = malloc(sizeof(int*)*max_size); - for (i=0; idim[i] = malloc(sizeof(int)*2); - } - network->dim[0][0] = input_dim; - network->dim[0][1] = input_depth; - return network; -} - -Network* create_network_lenet5(int dropout, int activation, int initialisation) { - /* Renvoie un réseau suivant l'architecture LeNet5 */ - Network* network; - network = create_network(8, dropout, initialisation, 32, 1); - add_convolution(network, 6, 5, activation); - add_average_pooling(network, 2, activation); - add_convolution(network, 16, 5, activation); - add_average_pooling_flatten(network, 2, activation); - add_dense(network, 120, 84, activation); - add_dense(network, 84, 10, activation); - add_dense(network, 10, 10, SOFTMAX); - return network; -} - -void create_a_cube_input_layer(Network* network, int pos, int depth, int dim) { - /* Créé et alloue de la mémoire à une couche de type input cube */ - int i, j; - network->input[pos] = malloc(sizeof(float**)*depth); - for (i=0; iinput[pos][i] = malloc(sizeof(float*)*dim); - for (j=0; jinput[pos][i][j] = malloc(sizeof(float)*dim); - } - } - network->dim[pos][0] = dim; - network->dim[pos][1] = depth; -} - -void create_a_line_input_layer(Network* network, int pos, int dim) { - /* Créé et alloue de la mémoire à une couche de type ligne */ - int i; - network->input[pos] = malloc(sizeof(float**)); - network->input[pos][0] = malloc(sizeof(float*)); - network->input[pos][0][0] = malloc(sizeof(float)*dim); -} - -void initialisation_1d_matrix(int initialisation, float* matrix, int rows, int n) { //NOT FINISHED - /* Initialise une matrice 1d rows de float en fonction du type d'initialisation */ - int i; - float lower_bound = -6/sqrt((double)n); - float distance = -lower_bound-lower_bound; - for (i=0; isize; - if (network->max_size == n) { - printf("Impossible de rajouter une couche d'average pooling, le réseau est déjà plein\n"); - return; - } - network->kernel[n].cnn = NULL; - network->kernel[n].nn = NULL; - network->kernel[n].activation = activation + 100*kernel_size; - create_a_cube_input_layer(network, n, network->dim[n-1][1], network->dim[n-1][0]/2); - network->size++; -} - -void add_average_pooling_flatten(Network* network, int kernel_size, int activation) { - /* Ajoute au réseau une couche d'average pooling valide de dimension dim*dim qui aplatit */ - int n = network->size; - if (network->max_size == n) { - printf("Impossible de rajouter une couche d'average pooling, le réseau est déjà plein\n"); - return; - } - network->kernel[n].cnn = NULL; - network->kernel[n].nn = NULL; - network->kernel[n].activation = activation + 100*kernel_size; - int dim = (network->dim[n-1][0]*network->dim[n-1][0]*network->dim[n-1][1])/(kernel_size*kernel_size); - create_a_line_input_layer(network, n, dim); - network->size++; -} - -void add_convolution(Network* network, int nb_filter, int kernel_size, int activation) { - /* Ajoute une couche de convolution dim*dim au réseau et initialise les kernels */ - int n = network->size, i, j, k; - if (network->max_size == n) { - printf("Impossible de rajouter une couche de convolution, le réseau est déjà plein\n"); - return; - } - int r = network->dim[n-1][1]; - int c = nb_filter; - network->kernel[n].nn = NULL; - network->kernel[n].cnn = malloc(sizeof(Kernel_cnn)); - network->kernel[n].activation = activation; - network->kernel[n].cnn->k_size = kernel_size; - network->kernel[n].cnn->rows = r; - network->kernel[n].cnn->columns = c; - network->kernel[n].cnn->w = malloc(sizeof(float***)*r); - network->kernel[n].cnn->d_w = malloc(sizeof(float***)*r); - for (i=0; ikernel[n].cnn->w[i] = malloc(sizeof(float**)*c); - network->kernel[n].cnn->d_w[i] = malloc(sizeof(float**)*c); - for (j=0; jkernel[n].cnn->w[i][j] = malloc(sizeof(float*)*kernel_size); - network->kernel[n].cnn->d_w[i][j] = malloc(sizeof(float*)*kernel_size); - for (k=0; kkernel[n].cnn->w[i][j][k] = malloc(sizeof(float)*kernel_size); - network->kernel[n].cnn->d_w[i][j][k] = malloc(sizeof(float)*kernel_size); - } - } - } - network->kernel[n].cnn->bias = malloc(sizeof(float**)*c); - network->kernel[n].cnn->d_bias = malloc(sizeof(float**)*c); - for (i=0; ikernel[n].cnn->bias[i] = malloc(sizeof(float*)*kernel_size); - network->kernel[n].cnn->d_bias[i] = malloc(sizeof(float*)*kernel_size); - for (j=0; jkernel[n].cnn->bias[i][j] = malloc(sizeof(float)*kernel_size); - network->kernel[n].cnn->d_bias[i][j] = malloc(sizeof(float)*kernel_size); - } - } - create_a_cube_input_layer(network, n, c, network->dim[n-1][0] - 2*(kernel_size/2)); - int n_int = network->dim[n-1][0]*network->dim[n-1][0]*network->dim[n-1][1]; - int n_out = network->dim[n][0]*network->dim[n][0]*network->dim[n][1]; - initialisation_3d_matrix(network->initialisation, network->kernel[n].cnn->bias, c, kernel_size, kernel_size, n_int+n_out); - initialisation_3d_matrix(ZERO, network->kernel[n].cnn->d_bias, c, kernel_size, kernel_size, n_int+n_out); - initialisation_4d_matrix(network->initialisation, network->kernel[n].cnn->w, r, c, kernel_size, kernel_size, n_int+n_out); - initialisation_4d_matrix(ZERO, network->kernel[n].cnn->d_w, r, c, kernel_size, kernel_size, n_int+n_out); - network->size++; -} - -void add_dense(Network* network, int input_units, int output_units, int activation) { - /* Ajoute une couche dense au réseau et initialise les poids et les biais*/ - int n = network->size; - if (network->max_size == n) { - printf("Impossible de rajouter une couche dense, le réseau est déjà plein\n"); - return; - } - network->kernel[n].cnn = NULL; - network->kernel[n].nn = malloc(sizeof(Kernel_nn)); - network->kernel[n].activation = activation; - network->kernel[n].nn->input_units = input_units; - network->kernel[n].nn->output_units = output_units; - network->kernel[n].nn->bias = malloc(sizeof(float)*output_units); - network->kernel[n].nn->d_bias = malloc(sizeof(float)*output_units); - network->kernel[n].nn->weights = malloc(sizeof(float*)*input_units); - network->kernel[n].nn->d_weights = malloc(sizeof(float*)*input_units); - for (int i=0; ikernel[n].nn->weights[i] = malloc(sizeof(float)*output_units); - network->kernel[n].nn->d_weights[i] = malloc(sizeof(float)*output_units); - } - initialisation_1d_matrix(network->initialisation, network->kernel[n].nn->bias, output_units, output_units+input_units); - initialisation_1d_matrix(ZERO, network->kernel[n].nn->d_bias, output_units, output_units+input_units); - initialisation_2d_matrix(network->initialisation, network->kernel[n].nn->weights, input_units, output_units, output_units+input_units); - initialisation_2d_matrix(ZERO, network->kernel[n].nn->d_weights, input_units, output_units, output_units+input_units); - create_a_line_input_layer(network, n, output_units); - network->size++; -} - void write_image_in_newtork_32(int** image, int height, int width, float** input) { - /* Ecrit une image 28*28 au centre d'un tableau 32*32 et met à 0 le reste */ - for (int i=0; i < height+2*PADING_INPUT; i++) { for (int j=PADING_INPUT; j < width+2*PADING_INPUT; j++) { if (iheight+PADING_INPUT || jwidth+PADING_INPUT) { @@ -349,199 +26,7 @@ void write_image_in_newtork_32(int** image, int height, int width, float** input } } -void make_convolution(float*** input, Kernel_cnn* kernel, float*** output, int output_dim) { - /* Effectue une convolution sans stride */ - //NOT FINISHED, MISS CONDITIONS ON THE CONVOLUTION - float f; - int i, j, k, a, b, c, n=kernel->k_size; - for (i=0; icolumns; i++) { - for (j=0; jbias[i][j][k]; - for (a=0; arows; a++) { - for (b=0; bw[a][i][b][c]*input[a][j+a][k+b]; - } - } - } - output[i][j][k] = f; - } - } - } -} - -void make_average_pooling(float*** input, float*** output, int size, int output_depth, int output_dim) { - /* Effecute un average pooling avec stride=size */ - //NOT FINISHED, MISS CONDITIONS ON THE POOLING - float average; - int i, j, k, a, b, n=size*size; - for (i=0; ibias[i]; - for (j=0; jweights[i][j]*input[j]; - } - output[i] = f; - } -} - -void free_a_cube_input_layer(Network* network, int pos, int depth, int dim) { - /* Libère la mémoire allouée à une couche de type input cube */ - int i, j, k; - for (i=0; iinput[pos][i][j]); - } - free(network->input[pos][i]); - } - free(network->input[pos]); -} - -void free_a_line_input_layer(Network* network, int pos) { - /* Libère la mémoire allouée à une couche de type input line */ - free(network->input[pos][0][0]); - free(network->input[pos][0]); - free(network->input[pos]); -} - -void free_average_pooling(Network* network, int pos) { - /* Libère l'espace mémoie et supprime une couche d'average pooling classique */ - free_a_cube_input_layer(network, pos, network->dim[pos-1][1], network->dim[pos-1][0]/2); -} - -void free_average_pooling_flatten(Network* network, int pos) { - /* Libère l'espace mémoie et supprime une couche d'average pooling flatten */ - free_a_line_input_layer(network, pos); -} - -void free_convolution(Network* network, int pos) { - /* Libère l'espace mémoire et supprime une couche de convolution */ - int i, j, k, c = network->kernel[pos].cnn->columns; - int k_size = network->kernel[pos].cnn->k_size; - int r = network->kernel[pos].cnn->rows; - free_a_cube_input_layer(network, pos, c, network->dim[pos-1][0] - 2*(k_size/2)); - for (i=0; ikernel[pos].cnn->bias[i][j]); - free(network->kernel[pos].cnn->d_bias[i][j]); - } - free(network->kernel[pos].cnn->bias[i]); - free(network->kernel[pos].cnn->d_bias[i]); - } - free(network->kernel[pos].cnn->bias); - free(network->kernel[pos].cnn->d_bias); - - for (i=0; ikernel[pos].cnn->w[i][j][k]); - free(network->kernel[pos].cnn->d_w[i][j][k]); - } - free(network->kernel[pos].cnn->w[i][j]); - free(network->kernel[pos].cnn->d_w[i][j]); - } - free(network->kernel[pos].cnn->w[i]); - free(network->kernel[pos].cnn->d_w[i]); - } - free(network->kernel[pos].cnn->w); - free(network->kernel[pos].cnn->d_w); - - free(network->kernel[pos].cnn); -} - -void free_dense(Network* network, int pos) { - /* Libère l'espace mémoire et supprime une couche dense */ - free_a_line_input_layer(network, pos); - int i, dim = network->kernel[pos].nn->output_units; - for (int i=0; ikernel[pos].nn->weights[i]); - free(network->kernel[pos].nn->d_weights[i]); - } - free(network->kernel[pos].nn->weights); - free(network->kernel[pos].nn->d_weights); - - free(network->kernel[pos].nn->bias); - free(network->kernel[pos].nn->d_bias); - - free(network->kernel[pos].nn); -} - -void free_network_creation(Network* network) { - /* Libère l'espace alloué dans la fonction 'create_network' */ - free_a_cube_input_layer(network, 0, network->dim[0][1], network->dim[0][0]); - - for (int i=0; imax_size; i++) { - free(network->dim[i]); - } - free(network->dim); - - free(network->kernel); - free(network->input); - - free(network); -} - -void free_network_lenet5(Network* network) { - /* Libère l'espace alloué dans la fonction 'create_network_lenet5' */ - free_dense(network, 6); - free_dense(network, 5); - free_dense(network, 4); - free_average_pooling_flatten(network, 3); - free_convolution(network, 2); - free_average_pooling(network, 1); - free_convolution(network, 0); - free_network_creation(network); - if (network->size != network->max_size) { - printf("Attention, le réseau LeNet5 n'est pas complet"); - } -} - void forward_propagation(Network* network) { - /* Propage en avant le cnn */ for (int i=0; i < network->size-1; i++) { if (network->kernel[i].nn==NULL && network->kernel[i].cnn!=NULL) { make_convolution(network->input[i], network->kernel[i].cnn, network->input[i+1], network->dim[i+1][0]); @@ -573,7 +58,6 @@ void forward_propagation(Network* network) { } void backward_propagation(Network* network, float wanted_number) { - /* Propage en arrière le cnn */ float* wanted_output = generate_wanted_output(wanted_number); int n = network->size-1; float loss = compute_cross_entropy_loss(network->input[n][0][0], wanted_output, network->dim[n][0]); @@ -608,7 +92,6 @@ void backward_propagation(Network* network, float wanted_number) { } float compute_cross_entropy_loss(float* output, float* wanted_output, int len) { - /* Renvoie l'erreur du réseau neuronal pour une sortie */ float loss=0.; for (int i=0; i -#include -#include -#include -#include +#include "struct.h" #ifndef DEF_CNN_H #define DEF_CNN_H -typedef struct Kernel_cnn { - int k_size; - int rows; - int columns; - int b; - float*** bias; // De dimension columns*k_size*k_size - float*** d_bias; // De dimension columns*k_size*k_size - float**** w; // De dimension rows*columns*k_size*k_size - float**** d_w; // De dimension rows*columns*k_size*k_size -} Kernel_cnn; - -typedef struct Kernel_nn { - int input_units; - int output_units; - float* bias; // De dimension output_units - float* d_bias; // De dimension output_units - float** weights; // De dimension input_units*output_units - float** d_weights; // De dimension input_units*output_units -} Kernel_nn; - -typedef struct Kernel { - Kernel_cnn* cnn; - Kernel_nn* nn; - int activation; // Vaut l'activation sauf pour un pooling où il: vaut kernel_size*100 + activation -} Kernel; - -typedef struct Layer { - -} Layer; - -typedef struct Network{ - int dropout; // Contient la probabilité d'abandon entre 0 et 100 (inclus) - int initialisation; // Contient le type d'initialisation - int max_size; // Taille maximale du réseau après initialisation - int size; // Taille actuelle du réseau - int** dim; // Contient les dimensions de l'input (width*depth) - Kernel* kernel; - float**** input; -} Network; - -float max(float a, float b); -float sigmoid(float x); -float sigmoid_derivative(float x); -float relu(float x); -float relu_derivative(float x); -float tanh_(float x); -float tanh_derivative(float x); -void apply_softmax_input(float ***input, int depth, int rows, int columns); -void apply_function_input(float (*f)(float), float*** input, int depth, int rows, int columns); -void choose_apply_function_input(int activation, float*** input, int depth, int rows, int columns); +/* +* Renvoie si oui ou non (1 ou 0) le neurone va être abandonné +*/ int will_be_drop(int dropout_prob); -Network* create_network(int max_size, int dropout, int initialisation, int input_dim, int input_depth); -Network* create_network_lenet5(int dropout, int activation, int initialisation); -void create_a_cube_input_layer(Network* network, int pos, int depth, int dim); -void create_a_line_input_layer(Network* network, int pos, int dim); -void initialisation_1d_matrix(int initialisation, float* matrix, int rows, int n); //NOT FINISHED (UNIFORM AND VARIATIONS) -void initialisation_2d_matrix(int initialisation, float** matrix, int rows, int columns, int n); //NOT FINISHED -void initialisation_3d_matrix(int initialisation, float*** matrix, int depth, int rows, int columns, int n); //NOT FINISHED -void initialisation_4d_matrix(int initialisation, float**** matrix, int rows, int columns, int rows1, int columns1, int n); //NOT FINISHED -void add_average_pooling(Network* network, int kernel_size, int activation); -void add_average_pooling_flatten(Network* network, int kernel_size, int activation); -void add_convolution(Network* network, int nb_filter, int kernel_size, int activation); -void add_dense(Network* network, int input_units, int output_units, int activation); + +/* +* Ecrit une image 28*28 au centre d'un tableau 32*32 et met à 0 le reste +*/ void write_image_in_newtork_32(int** image, int height, int width, float** input); -void make_convolution(float*** input, Kernel_cnn* kernel, float*** output, int output_dim); -void make_average_pooling(float*** input, float*** output, int size, int output_depth, int output_dim); -void make_average_pooling_flattened(float*** input, float* output, int size, int input_depth, int input_dim); -void make_fully_connected(float* input, Kernel_nn* kernel, float* output, int size_input, int size_output); -void free_a_cube_input_layer(Network* network, int pos, int depth, int dim); -void free_a_line_input_layer(Network* network, int pos); -void free_average_pooling(Network* network, int pos); -void free_average_pooling_flatten(Network* network, int pos); -void free_convolution(Network* network, int pos); -void free_dense(Network* network, int pos); -void free_network_creation(Network* network); -void free_network_lenet5(Network* network); -float compute_cross_entropy_loss(float* output, float* wanted_output, int len); + +/* +* Propage en avant le cnn +*/ void forward_propagation(Network* network); + +/* +* Propage en arrière le cnn +*/ void backward_propagation(Network* network, float wanted_number); //NOT FINISHED + +/* +* Renvoie l'erreur du réseau neuronal pour une sortie +*/ float compute_cross_entropy_loss(float* output, float* wanted_output, int len); + +/* +* On considère que la sortie voulue comporte 10 éléments +*/ float* generate_wanted_output(float wanted_number); - #endif \ No newline at end of file diff --git a/src/mnist_cnn/creation.c b/src/mnist_cnn/creation.c new file mode 100644 index 0000000..53a3b76 --- /dev/null +++ b/src/mnist_cnn/creation.c @@ -0,0 +1,162 @@ +#include +#include +#include "creation.h" +#include "function.h" +#include "initialisation.h" + +Network* create_network(int max_size, int dropout, int initialisation, int input_dim, int input_depth) { + if (dropout<0 || dropout>100) { + printf("Erreur, la probabilité de dropout n'est pas respecté, elle doit être comprise entre 0 et 100\n"); + } + Network* network = malloc(sizeof(Network)); + network->max_size = max_size; + network->dropout = dropout; + network->initialisation = initialisation; + network->size = 1; + network->input = malloc(sizeof(float***)*max_size); + network->kernel = malloc(sizeof(Kernel)*(max_size-1)); + create_a_cube_input_layer(network, 0, input_depth, input_dim); + int i, j; + network->dim = malloc(sizeof(int*)*max_size); + for (i=0; idim[i] = malloc(sizeof(int)*2); + } + network->dim[0][0] = input_dim; + network->dim[0][1] = input_depth; + return network; +} + +Network* create_network_lenet5(int dropout, int activation, int initialisation) { + Network* network; + network = create_network(8, dropout, initialisation, 32, 1); + add_convolution(network, 6, 5, activation); + add_average_pooling(network, 2, activation); + add_convolution(network, 16, 5, activation); + add_average_pooling_flatten(network, 2, activation); + add_dense(network, 120, 84, activation); + add_dense(network, 84, 10, activation); + add_dense(network, 10, 10, SOFTMAX); + return network; +} + +void create_a_cube_input_layer(Network* network, int pos, int depth, int dim) { + int i, j; + network->input[pos] = malloc(sizeof(float**)*depth); + for (i=0; iinput[pos][i] = malloc(sizeof(float*)*dim); + for (j=0; jinput[pos][i][j] = malloc(sizeof(float)*dim); + } + } + network->dim[pos][0] = dim; + network->dim[pos][1] = depth; +} + +void create_a_line_input_layer(Network* network, int pos, int dim) { + int i; + network->input[pos] = malloc(sizeof(float**)); + network->input[pos][0] = malloc(sizeof(float*)); + network->input[pos][0][0] = malloc(sizeof(float)*dim); +} + +void add_average_pooling(Network* network, int kernel_size, int activation) { + int n = network->size; + if (network->max_size == n) { + printf("Impossible de rajouter une couche d'average pooling, le réseau est déjà plein\n"); + return; + } + network->kernel[n].cnn = NULL; + network->kernel[n].nn = NULL; + network->kernel[n].activation = activation + 100*kernel_size; + create_a_cube_input_layer(network, n, network->dim[n-1][1], network->dim[n-1][0]/2); + network->size++; +} + +void add_average_pooling_flatten(Network* network, int kernel_size, int activation) { + int n = network->size; + if (network->max_size == n) { + printf("Impossible de rajouter une couche d'average pooling, le réseau est déjà plein\n"); + return; + } + network->kernel[n].cnn = NULL; + network->kernel[n].nn = NULL; + network->kernel[n].activation = activation + 100*kernel_size; + int dim = (network->dim[n-1][0]*network->dim[n-1][0]*network->dim[n-1][1])/(kernel_size*kernel_size); + create_a_line_input_layer(network, n, dim); + network->size++; +} + +void add_convolution(Network* network, int nb_filter, int kernel_size, int activation) { + int n = network->size, i, j, k; + if (network->max_size == n) { + printf("Impossible de rajouter une couche de convolution, le réseau est déjà plein\n"); + return; + } + int r = network->dim[n-1][1]; + int c = nb_filter; + network->kernel[n].nn = NULL; + network->kernel[n].cnn = malloc(sizeof(Kernel_cnn)); + network->kernel[n].activation = activation; + network->kernel[n].cnn->k_size = kernel_size; + network->kernel[n].cnn->rows = r; + network->kernel[n].cnn->columns = c; + network->kernel[n].cnn->w = malloc(sizeof(float***)*r); + network->kernel[n].cnn->d_w = malloc(sizeof(float***)*r); + for (i=0; ikernel[n].cnn->w[i] = malloc(sizeof(float**)*c); + network->kernel[n].cnn->d_w[i] = malloc(sizeof(float**)*c); + for (j=0; jkernel[n].cnn->w[i][j] = malloc(sizeof(float*)*kernel_size); + network->kernel[n].cnn->d_w[i][j] = malloc(sizeof(float*)*kernel_size); + for (k=0; kkernel[n].cnn->w[i][j][k] = malloc(sizeof(float)*kernel_size); + network->kernel[n].cnn->d_w[i][j][k] = malloc(sizeof(float)*kernel_size); + } + } + } + network->kernel[n].cnn->bias = malloc(sizeof(float**)*c); + network->kernel[n].cnn->d_bias = malloc(sizeof(float**)*c); + for (i=0; ikernel[n].cnn->bias[i] = malloc(sizeof(float*)*kernel_size); + network->kernel[n].cnn->d_bias[i] = malloc(sizeof(float*)*kernel_size); + for (j=0; jkernel[n].cnn->bias[i][j] = malloc(sizeof(float)*kernel_size); + network->kernel[n].cnn->d_bias[i][j] = malloc(sizeof(float)*kernel_size); + } + } + create_a_cube_input_layer(network, n, c, network->dim[n-1][0] - 2*(kernel_size/2)); + int n_int = network->dim[n-1][0]*network->dim[n-1][0]*network->dim[n-1][1]; + int n_out = network->dim[n][0]*network->dim[n][0]*network->dim[n][1]; + initialisation_3d_matrix(network->initialisation, network->kernel[n].cnn->bias, c, kernel_size, kernel_size, n_int+n_out); + initialisation_3d_matrix(ZERO, network->kernel[n].cnn->d_bias, c, kernel_size, kernel_size, n_int+n_out); + initialisation_4d_matrix(network->initialisation, network->kernel[n].cnn->w, r, c, kernel_size, kernel_size, n_int+n_out); + initialisation_4d_matrix(ZERO, network->kernel[n].cnn->d_w, r, c, kernel_size, kernel_size, n_int+n_out); + network->size++; +} + +void add_dense(Network* network, int input_units, int output_units, int activation) { + int n = network->size; + if (network->max_size == n) { + printf("Impossible de rajouter une couche dense, le réseau est déjà plein\n"); + return; + } + network->kernel[n].cnn = NULL; + network->kernel[n].nn = malloc(sizeof(Kernel_nn)); + network->kernel[n].activation = activation; + network->kernel[n].nn->input_units = input_units; + network->kernel[n].nn->output_units = output_units; + network->kernel[n].nn->bias = malloc(sizeof(float)*output_units); + network->kernel[n].nn->d_bias = malloc(sizeof(float)*output_units); + network->kernel[n].nn->weights = malloc(sizeof(float*)*input_units); + network->kernel[n].nn->d_weights = malloc(sizeof(float*)*input_units); + for (int i=0; ikernel[n].nn->weights[i] = malloc(sizeof(float)*output_units); + network->kernel[n].nn->d_weights[i] = malloc(sizeof(float)*output_units); + } + initialisation_1d_matrix(network->initialisation, network->kernel[n].nn->bias, output_units, output_units+input_units); + initialisation_1d_matrix(ZERO, network->kernel[n].nn->d_bias, output_units, output_units+input_units); + initialisation_2d_matrix(network->initialisation, network->kernel[n].nn->weights, input_units, output_units, output_units+input_units); + initialisation_2d_matrix(ZERO, network->kernel[n].nn->d_weights, input_units, output_units, output_units+input_units); + create_a_line_input_layer(network, n, output_units); + network->size++; +} \ No newline at end of file diff --git a/src/mnist_cnn/creation.h b/src/mnist_cnn/creation.h new file mode 100644 index 0000000..5d7940a --- /dev/null +++ b/src/mnist_cnn/creation.h @@ -0,0 +1,46 @@ +#include "struct.h" + +#ifndef DEF_CREATION_H +#define DEF_CREATION_H + +/* +* Créé un réseau qui peut contenir max_size couche (dont celle d'input et d'output) +*/ +Network* create_network(int max_size, int dropout, int initialisation, int input_dim, int input_depth); + +/* +* Renvoie un réseau suivant l'architecture LeNet5 +*/ +Network* create_network_lenet5(int dropout, int activation, int initialisation); + +/* +* Créé et alloue de la mémoire à une couche de type input cube +*/ +void create_a_cube_input_layer(Network* network, int pos, int depth, int dim); + +/* +* Créé et alloue de la mémoire à une couche de type ligne +*/ +void create_a_line_input_layer(Network* network, int pos, int dim); + +/* +* Ajoute au réseau une couche d'average pooling valide de dimension dim*dim +*/ +void add_average_pooling(Network* network, int kernel_size, int activation); + +/* +* Ajoute au réseau une couche d'average pooling valide de dimension dim*dim qui aplatit +*/ +void add_average_pooling_flatten(Network* network, int kernel_size, int activation); + +/* +* Ajoute une couche de convolution dim*dim au réseau et initialise les kernels +*/ +void add_convolution(Network* network, int nb_filter, int kernel_size, int activation); + +/* +* Ajoute une couche dense au réseau et initialise les poids et les biais +*/ +void add_dense(Network* network, int input_units, int output_units, int activation); + +#endif \ No newline at end of file diff --git a/src/mnist_cnn/free.c b/src/mnist_cnn/free.c new file mode 100644 index 0000000..cb6a293 --- /dev/null +++ b/src/mnist_cnn/free.c @@ -0,0 +1,106 @@ +#include +#include +#include "free.h" + +void free_a_cube_input_layer(Network* network, int pos, int depth, int dim) { + int i, j, k; + for (i=0; iinput[pos][i][j]); + } + free(network->input[pos][i]); + } + free(network->input[pos]); +} + +void free_a_line_input_layer(Network* network, int pos) { + free(network->input[pos][0][0]); + free(network->input[pos][0]); + free(network->input[pos]); +} + +void free_average_pooling(Network* network, int pos) { + free_a_cube_input_layer(network, pos, network->dim[pos-1][1], network->dim[pos-1][0]/2); +} + +void free_average_pooling_flatten(Network* network, int pos) { + free_a_line_input_layer(network, pos); +} + +void free_convolution(Network* network, int pos) { + int i, j, k, c = network->kernel[pos].cnn->columns; + int k_size = network->kernel[pos].cnn->k_size; + int r = network->kernel[pos].cnn->rows; + free_a_cube_input_layer(network, pos, c, network->dim[pos-1][0] - 2*(k_size/2)); + for (i=0; ikernel[pos].cnn->bias[i][j]); + free(network->kernel[pos].cnn->d_bias[i][j]); + } + free(network->kernel[pos].cnn->bias[i]); + free(network->kernel[pos].cnn->d_bias[i]); + } + free(network->kernel[pos].cnn->bias); + free(network->kernel[pos].cnn->d_bias); + + for (i=0; ikernel[pos].cnn->w[i][j][k]); + free(network->kernel[pos].cnn->d_w[i][j][k]); + } + free(network->kernel[pos].cnn->w[i][j]); + free(network->kernel[pos].cnn->d_w[i][j]); + } + free(network->kernel[pos].cnn->w[i]); + free(network->kernel[pos].cnn->d_w[i]); + } + free(network->kernel[pos].cnn->w); + free(network->kernel[pos].cnn->d_w); + + free(network->kernel[pos].cnn); +} + +void free_dense(Network* network, int pos) { + free_a_line_input_layer(network, pos); + int i, dim = network->kernel[pos].nn->output_units; + for (int i=0; ikernel[pos].nn->weights[i]); + free(network->kernel[pos].nn->d_weights[i]); + } + free(network->kernel[pos].nn->weights); + free(network->kernel[pos].nn->d_weights); + + free(network->kernel[pos].nn->bias); + free(network->kernel[pos].nn->d_bias); + + free(network->kernel[pos].nn); +} + +void free_network_creation(Network* network) { + free_a_cube_input_layer(network, 0, network->dim[0][1], network->dim[0][0]); + + for (int i=0; imax_size; i++) { + free(network->dim[i]); + } + free(network->dim); + + free(network->kernel); + free(network->input); + + free(network); +} + +void free_network_lenet5(Network* network) { + free_dense(network, 6); + free_dense(network, 5); + free_dense(network, 4); + free_average_pooling_flatten(network, 3); + free_convolution(network, 2); + free_average_pooling(network, 1); + free_convolution(network, 0); + free_network_creation(network); + if (network->size != network->max_size) { + printf("Attention, le réseau LeNet5 n'est pas complet"); + } +} diff --git a/src/mnist_cnn/free.h b/src/mnist_cnn/free.h new file mode 100644 index 0000000..8eee7c3 --- /dev/null +++ b/src/mnist_cnn/free.h @@ -0,0 +1,46 @@ +#include "struct.h" + +#ifndef DEF_FREE_H +#define DEF_FREE_H + +/* +* Libère la mémoire allouée à une couche de type input cube +*/ +void free_a_cube_input_layer(Network* network, int pos, int depth, int dim); + +/* +* Libère la mémoire allouée à une couche de type input line +*/ +void free_a_line_input_layer(Network* network, int pos); + +/* +* Libère l'espace mémoie et supprime une couche d'average pooling classique +*/ +void free_average_pooling(Network* network, int pos); + +/* +* Libère l'espace mémoie et supprime une couche d'average pooling flatten +*/ +void free_average_pooling_flatten(Network* network, int pos); + +/* +* Libère l'espace mémoire et supprime une couche de convolution +*/ +void free_convolution(Network* network, int pos); + +/* +* Libère l'espace mémoire et supprime une couche dense +*/ +void free_dense(Network* network, int pos); + +/* +* Libère l'espace alloué dans la fonction 'create_network' +*/ +void free_network_creation(Network* network); + +/* +* Libère l'espace alloué dans la fonction 'create_network_lenet5' +*/ +void free_network_lenet5(Network* network); + +#endif \ No newline at end of file diff --git a/src/mnist_cnn/function.c b/src/mnist_cnn/function.c new file mode 100644 index 0000000..5f2bb82 --- /dev/null +++ b/src/mnist_cnn/function.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include "function.h" + +float max(float a, float b) { + return a 0) + return 1; + return 0; +} + +float tanh_(float x) { + return tanh(x); +} + +float tanh_derivative(float x) { + float a = tanh(x); + return 1 - a*a; +} + +void apply_softmax_input(float ***input, int depth, int rows, int columns) { + int i, j, k; + float m = FLT_MIN; + float sum=0; + for (i=0; i +#include +#include "initialisation.h" + + +void initialisation_1d_matrix(int initialisation, float* matrix, int rows, int n) { //NOT FINISHED + int i; + float lower_bound = -6/sqrt((double)n); + float distance = -lower_bound-lower_bound; + for (i=0; i +#include "make.h" + +void make_convolution(float*** input, Kernel_cnn* kernel, float*** output, int output_dim) { + //NOT FINISHED, MISS CONDITIONS ON THE CONVOLUTION + float f; + int i, j, k, a, b, c, n=kernel->k_size; + for (i=0; icolumns; i++) { + for (j=0; jbias[i][j][k]; + for (a=0; arows; a++) { + for (b=0; bw[a][i][b][c]*input[a][j+a][k+b]; + } + } + } + output[i][j][k] = f; + } + } + } +} + +void make_average_pooling(float*** input, float*** output, int size, int output_depth, int output_dim) { + //NOT FINISHED, MISS CONDITIONS ON THE POOLING + float average; + int i, j, k, a, b, n=size*size; + for (i=0; ibias[i]; + for (j=0; jweights[i][j]*input[j]; + } + output[i] = f; + } +} \ No newline at end of file diff --git a/src/mnist_cnn/make.h b/src/mnist_cnn/make.h new file mode 100644 index 0000000..98c30d7 --- /dev/null +++ b/src/mnist_cnn/make.h @@ -0,0 +1,26 @@ +#include "struct.h" + +#ifndef DEF_MAKE_H +#define DEF_MAKE_H + +/* +* Effectue une convolution sans stride +*/ +void make_convolution(float*** input, Kernel_cnn* kernel, float*** output, int output_dim); + +/* +* Effecute un average pooling avec stride=size +*/ +void make_average_pooling(float*** input, float*** output, int size, int output_depth, int output_dim); + +/* +* Effectue un average pooling avec stride=size et aplatissement +*/ +void make_average_pooling_flattened(float*** input, float* output, int size, int input_depth, int input_dim); + +/* +* Effecute une full connection +*/ +void make_fully_connected(float* input, Kernel_nn* kernel, float* output, int size_input, int size_output); + +#endif \ No newline at end of file diff --git a/src/mnist_cnn/struct.h b/src/mnist_cnn/struct.h new file mode 100644 index 0000000..113bf03 --- /dev/null +++ b/src/mnist_cnn/struct.h @@ -0,0 +1,44 @@ +#ifndef DEF_STRUCT_H +#define DEF_STRUCT_H + +typedef struct Kernel_cnn { + int k_size; + int rows; + int columns; + int b; + float*** bias; // De dimension columns*k_size*k_size + float*** d_bias; // De dimension columns*k_size*k_size + float**** w; // De dimension rows*columns*k_size*k_size + float**** d_w; // De dimension rows*columns*k_size*k_size +} Kernel_cnn; + +typedef struct Kernel_nn { + int input_units; + int output_units; + float* bias; // De dimension output_units + float* d_bias; // De dimension output_units + float** weights; // De dimension input_units*output_units + float** d_weights; // De dimension input_units*output_units +} Kernel_nn; + +typedef struct Kernel { + Kernel_cnn* cnn; + Kernel_nn* nn; + int activation; // Vaut l'activation sauf pour un pooling où il: vaut kernel_size*100 + activation +} Kernel; + +typedef struct Layer { + +} Layer; + +typedef struct Network{ + int dropout; // Contient la probabilité d'abandon entre 0 et 100 (inclus) + int initialisation; // Contient le type d'initialisation + int max_size; // Taille maximale du réseau après initialisation + int size; // Taille actuelle du réseau + int** dim; // Contient les dimensions de l'input (width*depth) + Kernel* kernel; + float**** input; +} Network; + +#endif \ No newline at end of file