tipe/src/cnn/creation.c

375 lines
16 KiB
C
Raw Normal View History

2022-07-05 08:13:25 +02:00
#include <stdio.h>
#include <stdlib.h>
2022-10-24 12:54:51 +02:00
2023-05-12 16:16:34 +02:00
#include "../common/include/memory_management.h"
#include "../common/include/colors.h"
#include "../common/include/utils.h"
2022-10-24 12:54:51 +02:00
#include "include/initialisation.h"
2022-09-16 14:53:35 +02:00
#include "include/function.h"
2022-10-24 12:54:51 +02:00
#include "include/creation.h"
2022-07-05 08:13:25 +02:00
2023-05-13 17:22:47 +02:00
Network* create_network(int max_size, float learning_rate, int dropout, int activation, int initialisation, int input_width, int input_depth) {
if (dropout < 0 || dropout > 100) {
2023-03-08 20:48:34 +01:00
printf_error("La probabilité de dropout n'est pas respecté, elle doit être comprise entre 0 et 100\n");
2022-07-05 08:13:25 +02:00
}
Network* network = (Network*)nalloc(1, sizeof(Network));
2022-10-03 10:04:11 +02:00
network->learning_rate = learning_rate;
2023-01-17 15:34:29 +01:00
network->max_size = max_size;
network->dropout = dropout;
network->initialisation = initialisation;
network->size = 1;
network->input = (float****)nalloc(max_size, sizeof(float***));
network->input_z = (float****)nalloc(max_size, sizeof(float***));
network->kernel = (Kernel**)nalloc(max_size-1, sizeof(Kernel*));
network->width = (int*)nalloc(max_size, sizeof(int*));
network->depth = (int*)nalloc(max_size, sizeof(int*));
2023-01-17 15:25:34 +01:00
for (int i=0; i < max_size-1; i++) {
network->kernel[i] = (Kernel*)nalloc(1, sizeof(Kernel));
2022-07-05 08:13:25 +02:00
}
2023-03-08 20:48:34 +01:00
network->kernel[0]->linearisation = DOESNT_LINEARISE;
2023-03-13 18:47:32 +01:00
network->kernel[0]->activation = activation;
2023-05-13 17:22:47 +02:00
network->width[0] = input_width;
2023-01-17 15:34:29 +01:00
network->depth[0] = input_depth;
network->kernel[0]->nn = NULL;
network->kernel[0]->cnn = NULL;
2023-05-13 17:22:47 +02:00
create_a_cube_input_layer(network, 0, input_depth, input_width);
create_a_cube_input_z_layer(network, 0, input_depth, input_width);
2022-07-05 08:13:25 +02:00
return network;
}
2023-05-13 17:22:47 +02:00
Network* create_network_lenet5(float learning_rate, int dropout, int activation, int initialisation, int input_width, int input_depth) {
Network* network = create_network(8, learning_rate, dropout, activation, initialisation, input_width, input_depth);
add_convolution(network, 5, 6, 1, 0, activation);
add_average_pooling(network, 2, 2, 0);
add_convolution(network, 5, 16, 1, 0, activation);
add_average_pooling(network, 2, 2, 0);
add_dense_linearisation(network, 120, activation);
add_dense(network, 84, activation);
add_dense(network, 10, SOFTMAX);
2022-07-05 08:13:25 +02:00
return network;
}
2023-05-13 17:22:47 +02:00
Network* create_simple_one(float learning_rate, int dropout, int activation, int initialisation, int input_width, int input_depth) {
Network* network = create_network(3, learning_rate, dropout, activation, initialisation, input_width, input_depth);
2023-01-21 18:59:59 +01:00
add_dense_linearisation(network, 80, activation);
add_dense(network, 10, SOFTMAX);
return network;
}
2022-07-05 08:13:25 +02:00
void create_a_cube_input_layer(Network* network, int pos, int depth, int dim) {
network->input[pos] = (float***)nalloc(depth, sizeof(float**));
for (int i=0; i < depth; i++) {
network->input[pos][i] = (float**)nalloc(dim, sizeof(float*));
for (int j=0; j < dim; j++) {
network->input[pos][i][j] = (float*)nalloc(dim, sizeof(float));
2022-07-05 08:13:25 +02:00
}
}
2022-09-12 17:56:44 +02:00
network->width[pos] = dim;
network->depth[pos] = depth;
2022-07-05 08:13:25 +02:00
}
2022-10-31 20:08:42 +01:00
void create_a_cube_input_z_layer(Network* network, int pos, int depth, int dim) {
network->input_z[pos] = (float***)nalloc(depth, sizeof(float**));
2022-10-31 20:08:42 +01:00
for (int i=0; i < depth; i++) {
network->input_z[pos][i] = (float**)nalloc(dim, sizeof(float*));
2022-10-31 20:08:42 +01:00
for (int j=0; j < dim; j++) {
network->input_z[pos][i][j] = (float*)nalloc(dim, sizeof(float));
2022-10-31 20:08:42 +01:00
}
}
network->width[pos] = dim;
network->depth[pos] = depth;
}
2022-07-05 08:13:25 +02:00
void create_a_line_input_layer(Network* network, int pos, int dim) {
network->input[pos] = (float***)nalloc(1, sizeof(float**));
network->input[pos][0] = (float**)nalloc(1, sizeof(float*));
network->input[pos][0][0] = (float*)nalloc(dim, sizeof(float));
2022-09-19 18:39:49 +02:00
network->width[pos] = dim;
network->depth[pos] = 1;
2022-07-05 08:13:25 +02:00
}
2022-10-31 20:08:42 +01:00
void create_a_line_input_z_layer(Network* network, int pos, int dim) {
network->input_z[pos] = (float***)nalloc(1, sizeof(float**));
network->input_z[pos][0] = (float**)nalloc(1, sizeof(float*));
network->input_z[pos][0][0] = (float*)nalloc(dim, sizeof(float));
2022-10-31 20:08:42 +01:00
network->width[pos] = dim;
network->depth[pos] = 1;
}
void add_average_pooling(Network* network, int kernel_size, int stride, int padding) {
2022-07-05 08:13:25 +02:00
int n = network->size;
2022-09-30 15:50:29 +02:00
int k_pos = n-1;
2022-07-05 08:13:25 +02:00
if (network->max_size == n) {
printf_error("Impossible de rajouter une couche d'average pooling, le réseau est déjà plein\n");
2022-07-05 08:13:25 +02:00
return;
}
2023-05-13 17:22:47 +02:00
int input_width = network->width[k_pos];
int output_width = (2*padding + input_width - (kernel_size - stride))/stride;
2022-09-30 15:50:29 +02:00
network->kernel[k_pos]->cnn = NULL;
network->kernel[k_pos]->nn = NULL;
network->kernel[k_pos]->stride = stride;
network->kernel[k_pos]->padding = padding;
2022-11-12 14:20:13 +01:00
network->kernel[k_pos]->activation = IDENTITY; // Ne contient pas de fonction d'activation
2023-03-08 20:48:34 +01:00
network->kernel[k_pos]->linearisation = DOESNT_LINEARISE;
network->kernel[k_pos]->pooling = AVG_POOLING;
2023-05-13 17:22:47 +02:00
create_a_cube_input_layer(network, n, network->depth[n-1], output_width);
create_a_cube_input_z_layer(network, n, network->depth[n-1], output_width);
2023-01-30 09:39:45 +01:00
network->size++;
}
void add_max_pooling(Network* network, int kernel_size, int stride, int padding) {
2023-01-30 09:39:45 +01:00
int n = network->size;
int k_pos = n-1;
if (network->max_size == n) {
printf_error("Impossible de rajouter une couche de max pooling, le réseau est déjà plein\n");
2023-01-30 09:39:45 +01:00
return;
}
2023-05-13 17:22:47 +02:00
int input_width = network->width[k_pos];
int output_width = (2*padding + input_width - (kernel_size - stride))/stride;
2023-01-30 09:39:45 +01:00
network->kernel[k_pos]->cnn = NULL;
network->kernel[k_pos]->nn = NULL;
network->kernel[k_pos]->activation = IDENTITY; // Ne contient pas de fonction d'activation
2023-03-08 20:48:34 +01:00
network->kernel[k_pos]->linearisation = DOESNT_LINEARISE;
network->kernel[k_pos]->pooling = MAX_POOLING;
2023-05-13 17:22:47 +02:00
create_a_cube_input_layer(network, n, network->depth[n-1], output_width);
create_a_cube_input_z_layer(network, n, network->depth[n-1], output_width);
2022-07-05 08:13:25 +02:00
network->size++;
}
void add_convolution(Network* network, int kernel_size, int number_of_kernels, int stride, int padding, int activation) {
int n = network->size;
2022-09-30 15:50:29 +02:00
int k_pos = n-1;
2022-07-05 08:13:25 +02:00
if (network->max_size == n) {
printf_error("Impossible de rajouter une couche de convolution, le réseau est déjà plein \n");
2022-07-05 08:13:25 +02:00
return;
}
2023-05-13 17:22:47 +02:00
int input_depth = network->depth[k_pos];
int input_width = network->width[k_pos];
2023-05-13 17:22:47 +02:00
int output_width = (2*padding + input_width - (kernel_size - stride))/stride;
int output_depth = number_of_kernels;
2023-05-13 17:22:47 +02:00
int bias_size = output_width;
2022-09-30 15:50:29 +02:00
network->kernel[k_pos]->nn = NULL;
network->kernel[k_pos]->stride = stride;
network->kernel[k_pos]->padding = padding;
2022-09-30 15:50:29 +02:00
network->kernel[k_pos]->activation = activation;
2023-03-08 20:48:34 +01:00
network->kernel[k_pos]->linearisation = DOESNT_LINEARISE;
network->kernel[k_pos]->pooling = NO_POOLING;
network->kernel[k_pos]->cnn = (Kernel_cnn*)nalloc(1, sizeof(Kernel_cnn));
2022-09-30 15:50:29 +02:00
Kernel_cnn* cnn = network->kernel[k_pos]->cnn;
2022-09-10 18:23:16 +02:00
cnn->k_size = kernel_size;
2023-05-13 17:22:47 +02:00
cnn->rows = input_depth;
cnn->columns = output_depth;
2023-05-13 17:22:47 +02:00
cnn->weights = (float****)nalloc(input_depth, sizeof(float***));
cnn->d_weights = (float****)nalloc(input_depth, sizeof(float***));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_CNN_WEIGHTS
2023-05-13 17:22:47 +02:00
cnn->s_d_weights = (float****)nalloc(input_depth, sizeof(float***));
cnn->v_d_weights = (float****)nalloc(input_depth, sizeof(float***));
2023-03-27 18:17:50 +02:00
#endif
2023-05-13 17:22:47 +02:00
for (int i=0; i < input_depth; i++) {
cnn->weights[i] = (float***)nalloc(output_depth, sizeof(float**));
cnn->d_weights[i] = (float***)nalloc(output_depth, sizeof(float**));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_CNN_WEIGHTS
2023-05-13 17:22:47 +02:00
cnn->s_d_weights[i] = (float***)nalloc(output_depth, sizeof(float**));
cnn->v_d_weights[i] = (float***)nalloc(output_depth, sizeof(float**));
2023-03-27 18:17:50 +02:00
#endif
2023-05-13 17:22:47 +02:00
for (int j=0; j < output_depth; j++) {
cnn->weights[i][j] = (float**)nalloc(kernel_size, sizeof(float*));
cnn->d_weights[i][j] = (float**)nalloc(kernel_size, sizeof(float*));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_CNN_WEIGHTS
cnn->s_d_weights[i][j] = (float**)nalloc(kernel_size, sizeof(float*));
cnn->v_d_weights[i][j] = (float**)nalloc(kernel_size, sizeof(float*));
#endif
for (int k=0; k < kernel_size; k++) {
cnn->weights[i][j][k] = (float*)nalloc(kernel_size, sizeof(float));
cnn->d_weights[i][j][k] = (float*)nalloc(kernel_size, sizeof(float));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_CNN_WEIGHTS
cnn->s_d_weights[i][j][k] = (float*)nalloc(kernel_size, sizeof(float));
cnn->v_d_weights[i][j][k] = (float*)nalloc(kernel_size, sizeof(float));
#endif
2023-01-28 22:04:38 +01:00
for (int l=0; l < kernel_size; l++) {
cnn->d_weights[i][j][k][l] = 0.;
2023-03-27 18:17:50 +02:00
#ifdef ADAM_CNN_WEIGHTS
cnn->s_d_weights[i][j][k][l] = 0.;
cnn->v_d_weights[i][j][k][l] = 0.;
#endif
2023-01-28 22:04:38 +01:00
}
2022-07-05 08:13:25 +02:00
}
}
}
2023-05-13 17:22:47 +02:00
cnn->bias = (float***)nalloc(output_depth, sizeof(float**));
cnn->d_bias = (float***)nalloc(output_depth, sizeof(float**));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_CNN_BIAS
2023-05-13 17:22:47 +02:00
cnn->s_d_bias = (float***)nalloc(output_depth, sizeof(float**));
cnn->v_d_bias = (float***)nalloc(output_depth, sizeof(float**));
2023-03-27 18:17:50 +02:00
#endif
2023-05-13 17:22:47 +02:00
for (int i=0; i < output_depth; i++) {
2023-03-18 13:25:58 +01:00
cnn->bias[i] = (float**)nalloc(bias_size, sizeof(float*));
cnn->d_bias[i] = (float**)nalloc(bias_size, sizeof(float*));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_CNN_BIAS
cnn->s_d_bias[i] = (float**)nalloc(bias_size, sizeof(float*));
cnn->v_d_bias[i] = (float**)nalloc(bias_size, sizeof(float*));
#endif
2023-03-18 13:25:58 +01:00
for (int j=0; j < bias_size; j++) {
cnn->bias[i][j] = (float*)nalloc(bias_size, sizeof(float));
cnn->d_bias[i][j] = (float*)nalloc(bias_size, sizeof(float));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_CNN_BIAS
cnn->s_d_bias[i][j] = (float*)nalloc(bias_size, sizeof(float));
cnn->v_d_bias[i][j] = (float*)nalloc(bias_size, sizeof(float));
#endif
2023-03-18 13:25:58 +01:00
for (int k=0; k < bias_size; k++) {
cnn->d_bias[i][j][k] = 0.;
2023-03-27 18:17:50 +02:00
#ifdef ADAM_CNN_BIAS
cnn->s_d_bias[i][j][k] = 0.;
cnn->v_d_bias[i][j][k] = 0.;
#endif
2023-03-18 13:25:58 +01:00
}
}
2022-07-05 08:13:25 +02:00
}
2023-03-18 13:25:58 +01:00
int n_in = network->width[n-1]*network->width[n-1]*network->depth[n-1];
2022-11-04 10:54:32 +01:00
int n_out = network->width[n]*network->width[n]*network->depth[n];
2023-05-13 17:22:47 +02:00
initialisation_3d_matrix(network->initialisation, cnn->bias, output_depth, output_width, output_width, n_in, n_out);
initialisation_4d_matrix(network->initialisation, cnn->weights, input_depth, output_depth, kernel_size, kernel_size, n_in, n_out);
create_a_cube_input_layer(network, n, output_depth, bias_size);
create_a_cube_input_z_layer(network, n, output_depth, bias_size);
2022-07-05 08:13:25 +02:00
network->size++;
}
2023-02-19 12:53:08 +01:00
void add_dense(Network* network, int size_output, int activation) {
2022-07-05 08:13:25 +02:00
int n = network->size;
2022-09-30 15:50:29 +02:00
int k_pos = n-1;
2023-02-19 12:50:27 +01:00
int size_input = network->width[k_pos];
2022-07-05 08:13:25 +02:00
if (network->max_size == n) {
printf_error("Impossible de rajouter une couche dense, le réseau est déjà plein\n");
2022-07-05 08:13:25 +02:00
return;
}
2022-09-30 15:50:29 +02:00
network->kernel[k_pos]->cnn = NULL;
network->kernel[k_pos]->stride = -1; // N'est pas utilisé dans une couche dense
network->kernel[k_pos]->padding = -1; // N'est pas utilisé dans une couche dense
2022-09-30 15:50:29 +02:00
network->kernel[k_pos]->activation = activation;
2023-03-08 20:48:34 +01:00
network->kernel[k_pos]->linearisation = DOESNT_LINEARISE;
network->kernel[k_pos]->pooling = NO_POOLING;
network->kernel[k_pos]->nn = (Kernel_nn*)nalloc(1, sizeof(Kernel_nn));
Kernel_nn* nn = network->kernel[k_pos]->nn;
2023-02-19 12:50:27 +01:00
nn->size_input = size_input;
2023-02-19 12:53:08 +01:00
nn->size_output = size_output;
nn->bias = (float*)nalloc(size_output, sizeof(float));
nn->d_bias = (float*)nalloc(size_output, sizeof(float));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_BIAS
nn->s_d_bias = (float*)nalloc(size_output, sizeof(float));
nn->v_d_bias = (float*)nalloc(size_output, sizeof(float));
#endif
2023-02-19 12:53:08 +01:00
for (int i=0; i < size_output; i++) {
2023-01-28 22:04:38 +01:00
nn->d_bias[i] = 0.;
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_BIAS
nn->s_d_bias[i] = 0.;
nn->v_d_bias[i] = 0.;
#endif
2023-01-28 22:04:38 +01:00
}
nn->weights = (float**)nalloc(size_input, sizeof(float*));
nn->d_weights = (float**)nalloc(size_input, sizeof(float*));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_WEIGHTS
nn->s_d_weights = (float**)nalloc(size_input, sizeof(float*));
nn->v_d_weights = (float**)nalloc(size_input, sizeof(float*));
#endif
2023-02-19 12:50:27 +01:00
for (int i=0; i < size_input; i++) {
nn->weights[i] = (float*)nalloc(size_output, sizeof(float));
nn->d_weights[i] = (float*)nalloc(size_output, sizeof(float));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_WEIGHTS
nn->s_d_weights[i] = (float*)nalloc(size_output, sizeof(float));
nn->v_d_weights[i] = (float*)nalloc(size_output, sizeof(float));
#endif
2023-02-19 12:53:08 +01:00
for (int j=0; j < size_output; j++) {
2023-01-28 22:04:38 +01:00
nn->d_weights[i][j] = 0.;
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_WEIGHTS
nn->s_d_weights[i][j] = 0.;
nn->v_d_weights[i][j] = 0.;
#endif
2023-01-28 22:04:38 +01:00
}
2022-07-05 08:13:25 +02:00
}
2023-03-09 06:57:51 +01:00
initialisation_1d_matrix(network->initialisation, nn->bias, size_output, size_input, size_output);
2023-02-19 12:53:08 +01:00
initialisation_2d_matrix(network->initialisation, nn->weights, size_input, size_output, size_input, size_output);
create_a_line_input_layer(network, n, size_output);
create_a_line_input_z_layer(network, n, size_output);
2022-09-19 18:39:49 +02:00
network->size++;
}
2023-02-19 12:53:08 +01:00
void add_dense_linearisation(Network* network, int size_output, int activation) {
2023-02-19 12:50:27 +01:00
// Can replace size_input by a research of this dim
2022-09-19 18:39:49 +02:00
int n = network->size;
2022-09-30 15:50:29 +02:00
int k_pos = n-1;
2023-02-19 12:50:27 +01:00
int size_input = network->depth[k_pos]*network->width[k_pos]*network->width[k_pos];
2022-09-19 18:39:49 +02:00
if (network->max_size == n) {
printf_error("Impossible de rajouter une couche dense, le réseau est déjà plein\n");
2022-09-19 18:39:49 +02:00
return;
}
2022-09-30 15:50:29 +02:00
network->kernel[k_pos]->cnn = NULL;
network->kernel[k_pos]->stride = -1; // N'est pas utilisé dans une couche dense
network->kernel[k_pos]->padding = -1; // N'est pas utilisé dans une couche dense
2022-09-30 15:50:29 +02:00
network->kernel[k_pos]->activation = activation;
2023-03-08 20:48:34 +01:00
network->kernel[k_pos]->linearisation = DO_LINEARISE;
network->kernel[k_pos]->pooling = NO_POOLING;
network->kernel[k_pos]->nn = (Kernel_nn*)nalloc(1, sizeof(Kernel_nn));
Kernel_nn* nn = network->kernel[k_pos]->nn;
2023-02-19 12:50:27 +01:00
nn->size_input = size_input;
2023-02-19 12:53:08 +01:00
nn->size_output = size_output;
2023-01-17 15:34:29 +01:00
nn->bias = (float*)nalloc(size_output, sizeof(float));
nn->d_bias = (float*)nalloc(size_output, sizeof(float));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_BIAS
nn->s_d_bias = (float*)nalloc(size_output, sizeof(float));
nn->v_d_bias = (float*)nalloc(size_output, sizeof(float));
#endif
2023-02-19 12:53:08 +01:00
for (int i=0; i < size_output; i++) {
2023-01-28 22:04:38 +01:00
nn->d_bias[i] = 0.;
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_BIAS
nn->s_d_bias[i] = 0.;
nn->v_d_bias[i] = 0.;
#endif
2023-01-28 22:04:38 +01:00
}
nn->weights = (float**)nalloc(size_input, sizeof(float*));
nn->d_weights = (float**)nalloc(size_input, sizeof(float*));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_WEIGHTS
nn->s_d_weights = (float**)nalloc(size_input, sizeof(float*));
nn->v_d_weights = (float**)nalloc(size_input, sizeof(float*));
#endif
2023-02-19 12:50:27 +01:00
for (int i=0; i < size_input; i++) {
nn->weights[i] = (float*)nalloc(size_output, sizeof(float));
nn->d_weights[i] = (float*)nalloc(size_output, sizeof(float));
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_WEIGHTS
nn->s_d_weights[i] = (float*)nalloc(size_output, sizeof(float));
nn->v_d_weights[i] = (float*)nalloc(size_output, sizeof(float));
#endif
2023-02-19 12:53:08 +01:00
for (int j=0; j < size_output; j++) {
2023-01-28 22:04:38 +01:00
nn->d_weights[i][j] = 0.;
2023-03-27 18:17:50 +02:00
#ifdef ADAM_DENSE_WEIGHTS
nn->s_d_weights[i][j] = 0.;
nn->v_d_weights[i][j] = 0.;
#endif
2023-01-28 22:04:38 +01:00
}
2022-09-19 18:39:49 +02:00
}
2023-03-09 06:57:51 +01:00
initialisation_1d_matrix(network->initialisation, nn->bias, size_output, size_input, size_output);
2023-02-19 12:53:08 +01:00
initialisation_2d_matrix(network->initialisation, nn->weights, size_input, size_output, size_input, size_output);
create_a_line_input_layer(network, n, size_output);
create_a_line_input_z_layer(network, n, size_output);
2022-07-05 08:13:25 +02:00
network->size++;
}