diff --git a/src/cnn/creation.c b/src/cnn/creation.c index 4b7c207..c1017d7 100644 --- a/src/cnn/creation.c +++ b/src/cnn/creation.c @@ -14,7 +14,7 @@ Network* create_network(int max_size, int dropout, int initialisation, int input network->initialisation = initialisation; network->size = 1; network->input = (float****)malloc(sizeof(float***)*max_size); - network->kernel = (Kernel**)malloc(sizeof(Kernel*)*(max_size-1)); + network->kernel = (Kernel**)malloc(sizeof(Kernel*)*max_size); network->width = (int*)malloc(sizeof(int*)*max_size); network->depth = (int*)malloc(sizeof(int*)*max_size); for (int i=0; i < max_size; i++) { @@ -32,12 +32,12 @@ Network* create_network_lenet5(int dropout, int activation, int initialisation) Network* network = create_network(8, dropout, initialisation, 32, 1); network->kernel[0]->activation = activation; add_convolution(network, 6, 5, activation); - add_average_pooling(network, 2, activation); + add_2d_average_pooling(network, 2); add_convolution(network, 16, 5, activation); - add_average_pooling_flatten(network, 2, activation); + add_2d_average_pooling(network, 2); + add_dense_linearisation(network, 160, 120, activation); add_dense(network, 120, 84, activation); - add_dense(network, 84, 10, activation); - add_dense(network, 10, 10, SOFTMAX); + add_dense(network, 84, 10, SOFTMAX); return network; } @@ -57,9 +57,11 @@ void create_a_line_input_layer(Network* network, int pos, int dim) { network->input[pos] = (float***)malloc(sizeof(float**)); network->input[pos][0] = (float**)malloc(sizeof(float*)); network->input[pos][0][0] = (float*)malloc(sizeof(float)*dim); + network->width[pos] = dim; + network->depth[pos] = 1; } -void add_average_pooling(Network* network, int kernel_size, int activation) { +void add_2d_average_pooling(Network* network, int kernel_size) { 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"); @@ -67,12 +69,12 @@ void add_average_pooling(Network* network, int kernel_size, int activation) { } network->kernel[n]->cnn = NULL; network->kernel[n]->nn = NULL; - network->kernel[n]->activation = activation + 100*kernel_size; + network->kernel[n]->activation = 100*kernel_size; // Ne contient pas de fonction d'activation create_a_cube_input_layer(network, n, network->depth[n-1], network->width[n-1]/2); network->size++; } -void add_average_pooling_flatten(Network* network, int kernel_size, int activation) { +void add_average_pooling_flatten(Network* network, int kernel_size) { // NEED TO BE VERIFIED 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"); @@ -80,7 +82,7 @@ void add_average_pooling_flatten(Network* network, int kernel_size, int activati } network->kernel[n]->cnn = NULL; network->kernel[n]->nn = NULL; - network->kernel[n]->activation = activation + 100*kernel_size; + network->kernel[n]->activation = 100*kernel_size; // Ne contient pas de fonction d'activation int dim = (network->width[n-1]*network->width[n-1]*network->depth[n-1])/(kernel_size*kernel_size); create_a_line_input_layer(network, n, dim); network->size++; @@ -92,6 +94,7 @@ void add_convolution(Network* network, int depth_output, int kernel_size, int ac printf("Impossible de rajouter une couche de convolution, le réseau est déjà plein \n"); return; } + int bias_size = network->width[n-1] - 2*(kernel_size/2); int depth_input = network->depth[n-1]; network->kernel[n]->nn = NULL; network->kernel[n]->activation = activation; @@ -118,14 +121,14 @@ void add_convolution(Network* network, int depth_output, int kernel_size, int ac cnn->bias = (float***)malloc(sizeof(float**)*depth_output); cnn->d_bias = (float***)malloc(sizeof(float**)*depth_output); for (int i=0; i < depth_output; i++) { - cnn->bias[i] = (float**)malloc(sizeof(float*)*kernel_size); - cnn->d_bias[i] = (float**)malloc(sizeof(float*)*kernel_size); - for (int j=0; j < kernel_size; j++) { - cnn->bias[i][j] = (float*)malloc(sizeof(float)*kernel_size); - cnn->d_bias[i][j] = (float*)malloc(sizeof(float)*kernel_size); + cnn->bias[i] = (float**)malloc(sizeof(float*)*bias_size); + cnn->d_bias[i] = (float**)malloc(sizeof(float*)*bias_size); + for (int j=0; j < bias_size; j++) { + cnn->bias[i][j] = (float*)malloc(sizeof(float)*bias_size); + cnn->d_bias[i][j] = (float*)malloc(sizeof(float)*bias_size); } } - create_a_cube_input_layer(network, n, depth_output, network->width[n-1] - 2*(kernel_size/2)); + create_a_cube_input_layer(network, n, depth_output, bias_size); int n_int = network->width[n-1]*network->width[n-1]*network->depth[n-1]; int n_out = network->width[n]*network->width[n]*network->depth[n]; initialisation_3d_matrix(network->initialisation, cnn->bias, depth_output, kernel_size, kernel_size, n_int+n_out); @@ -160,5 +163,37 @@ void add_dense(Network* network, int input_units, int output_units, int activati initialisation_2d_matrix(network->initialisation, nn->weights, input_units, output_units, output_units+input_units); initialisation_2d_matrix(ZERO, nn->d_weights, input_units, output_units, output_units+input_units); create_a_line_input_layer(network, n, output_units); + network->size++; +} + +void add_dense_linearisation(Network* network, int input_units, int output_units, int activation) { + // Can replace input_units by a research of this dim + + 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 = (Kernel_nn*)malloc(sizeof(Kernel_nn)); + Kernel_nn* nn = network->kernel[n]->nn; + network->kernel[n]->activation = activation; + nn->input_units = input_units; + nn->output_units = output_units; + + nn->bias = (float*)malloc(sizeof(float)*output_units); + nn->d_bias = (float*)malloc(sizeof(float)*output_units); + nn->weights = (float**)malloc(sizeof(float*)*input_units); + nn->d_weights = (float**)malloc(sizeof(float*)*input_units); + for (int i=0; i < input_units; i++) { + nn->weights[i] = (float*)malloc(sizeof(float)*output_units); + nn->d_weights[i] = (float*)malloc(sizeof(float)*output_units); + } + initialisation_1d_matrix(network->initialisation, nn->bias, output_units, output_units+input_units); + initialisation_1d_matrix(ZERO, nn->d_bias, output_units, output_units+input_units); + initialisation_2d_matrix(network->initialisation, nn->weights, input_units, output_units, output_units+input_units); + initialisation_2d_matrix(ZERO, 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/cnn/include/creation.h b/src/cnn/include/creation.h index 54a516e..0bad98d 100644 --- a/src/cnn/include/creation.h +++ b/src/cnn/include/creation.h @@ -26,21 +26,26 @@ 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); +void add_2d_average_pooling(Network* network, int kernel_size); /* * 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); +void add_average_pooling_flatten(Network* network, int kernel_size); /* -* Ajoute une couche de convolution dim*dim au réseau et initialise les kernels +* Ajoute au réseau une couche de convolution dim*dim 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 +* Ajoute au réseau une couche dense et initialise les poids et les biais */ void add_dense(Network* network, int input_units, int output_units, int activation); +/* +* Ajoute au réseau une couche dense qui aplatit +*/ +void add_dense_linearisation(Network* network, int input_units, int output_units, int activation); + #endif \ No newline at end of file diff --git a/src/cnn/include/struct.h b/src/cnn/include/struct.h index eecd2ec..706a8ab 100644 --- a/src/cnn/include/struct.h +++ b/src/cnn/include/struct.h @@ -23,7 +23,8 @@ typedef struct Kernel_nn { typedef struct Kernel { Kernel_cnn* cnn; // NULL si ce n'est pas un cnn Kernel_nn* nn; // NULL si ce n'est pas un nn - int activation; // Vaut l'activation sauf pour un pooling où il: vaut kernel_size*100 + activation + int activation; // Vaut l'activation sauf pour un pooling où il: vaut pooling_size*100 + activation + int linearisation; // Vaut 1 si c'est la linéarisation d'une couche, 0 sinon ?? Ajouter dans les autres } Kernel; diff --git a/src/cnn/main.c b/src/cnn/main.c index 2aa8d23..0b74aef 100644 --- a/src/cnn/main.c +++ b/src/cnn/main.c @@ -30,35 +30,48 @@ void write_image_in_network_32(int** image, int height, int width, float** input } void forward_propagation(Network* network) { - int output_dim, output_depth; + int activation, input_width, input_depth, output_width, output_depth; + int n = network->size; + float*** input; float*** output; - for (int i=0; i < network->size-1; i++) { - if (network->kernel[i]->nn==NULL && network->kernel[i]->cnn!=NULL) { //CNN - output = network->input[i+1]; - output_dim = network->width[i+1]; - output_depth = network->depth[i+1]; - make_convolution(network->input[i], network->kernel[i]->cnn, output, output_dim); - choose_apply_function_input(network->kernel[i]->activation, output, output_depth, output_dim, output_dim); + Kernel* k_i_1; + Kernel* k_i; + for (int i=0; i < n-1; i++) { + k_i_1 = network->kernel[i+1]; + k_i = network->kernel[i]; + input_width = network->width[i]; + input_depth = network->depth[i]; + output_width = network->width[i+1]; + output_depth = network->depth[i+1]; + activation = network->kernel[i]->activation; + input = network->input[i]; + output = network->input[i+1]; + + if (k_i_1->nn==NULL && k_i_1->cnn!=NULL) { //CNN + printf("Convolution of cnn: %dx%d -> %dx%d\n", input_depth, input_width, output_depth, output_width); + make_convolution(input, k_i_1->cnn, output, output_width); + choose_apply_function_input(activation, output, output_depth, output_width, output_width); } - else if (network->kernel[i]->nn!=NULL && network->kernel[i]->cnn==NULL) { //NN - make_fully_connected(network->input[i][0][0], network->kernel[i]->nn, network->input[i+1][0][0], network->width[i], network->width[i+1]); - choose_apply_function_input(network->kernel[i]->activation, network->input[i+1], 1, 1, network->width[i+1]); + else if (k_i_1->nn!=NULL && k_i_1->cnn==NULL) { //NN + printf("Densification of nn\n"); + // Checked if it is a nn which linearise + make_fully_connected(network->input[i][0][0], network->kernel[i]->nn, network->input[i+1][0][0], input_width, output_width); + choose_apply_function_input(activation, output, 1, 1, output_width); } - else { //Pooling - if (network->size-2==i) { + else { //Pooling (Vérifier dedans) ?? + if (n-2==i) { printf("Le réseau ne peut pas finir par une pooling layer"); return; } - if (network->kernel[i+1]->nn!=NULL && network->kernel[i+1]->cnn==NULL) { - make_average_pooling_flattened(network->input[i], network->input[i+1][0][0], network->kernel[i]->activation/100, network->depth[i], network->width[i]); - choose_apply_function_input(network->kernel[i]->activation%100, network->input[i+1], 1, 1, network->width[i+1]); + if (1==1) { // Pooling sur une matrice + printf("Average pooling\n"); + make_average_pooling(input, output, activation/100, output_depth, output_width); } - else if (network->kernel[i+1]->nn==NULL && network->kernel[i+1]->cnn!=NULL) { - make_average_pooling(network->input[i], network->input[i+1], network->kernel[i]->activation/100, network->depth[i+1], network->width[i+1]); - choose_apply_function_input(network->kernel[i]->activation%100, network->input[i+1], network->depth[i+1], network->width[i+1], network->width[i+1]); + else if (1==0) { // Pooling sur un vecteur + printf("Error: Not implemented: forward: %d\n", i); } else { - printf("Le réseau ne peut pas contenir deux pooling layers collées"); + printf("Erreur: forward_propagation: %d -> %d %d\n", i, k_i_1->nn==NULL, k_i_1->cnn); return; } } @@ -128,6 +141,15 @@ float* generate_wanted_output(float wanted_number) { int main() { Network* network = create_network_lenet5(0, TANH, GLOROT_NORMAL); + for (int i=0; i<8; i++) { + printf("%d %d \n", network->depth[i], network->width[i]); + } + printf("Kernel:\n"); + for (int i=0; i<7; i++) { + if (network->kernel[i]->cnn!=NULL) { + printf("%d -> %d %d\n", i, network->kernel[i]->cnn->rows, network->kernel[i]->cnn->k_size); + } + } forward_propagation(network); return 0; } \ No newline at end of file diff --git a/src/cnn/make.c b/src/cnn/make.c index 7ac689b..1f57d54 100644 --- a/src/cnn/make.c +++ b/src/cnn/make.c @@ -5,6 +5,8 @@ void make_convolution(float*** input, Kernel_cnn* kernel, float*** output, int o //NOT FINISHED, MISS CONDITIONS ON THE CONVOLUTION float f; int n = kernel->k_size; + printf("Convolution output: %dx%dx%d, %dx%dx%d\n", kernel->columns, output_dim, output_dim, kernel->rows, n, n); + printf("BIS %d %d \n", kernel->columns, kernel->k_size); for (int i=0; i < kernel->columns; i++) { for (int j=0; j < output_dim; j++) { for (int k=0; k < output_dim; k++) { @@ -35,7 +37,7 @@ void make_average_pooling(float*** input, float*** output, int size, int output_ average += input[i][2*j +a][2*k +b]; } } - output[i][j][k] = average; + output[i][j][k] = average/n; } } }