Update backpropagation.c

This commit is contained in:
augustin64 2022-11-03 18:13:01 +01:00
parent 9d03611744
commit 4637d62e73
9 changed files with 86 additions and 55 deletions

View File

@ -65,10 +65,10 @@ $(BUILDDIR)/mnist_%.o: $(MNIST_SRCDIR)/%.c $(MNIST_SRCDIR)/include/%.h
# #
cnn: $(BUILDDIR)/cnn-main; cnn: $(BUILDDIR)/cnn-main;
$(BUILDDIR)/cnn-main: $(CNN_SRCDIR)/main.c $(BUILDDIR)/cnn_train.o $(BUILDDIR)/cnn_cnn.o $(BUILDDIR)/cnn_creation.o $(BUILDDIR)/cnn_initialisation.o $(BUILDDIR)/cnn_make.o $(BUILDDIR)/cnn_neuron_io.o $(BUILDDIR)/cnn_function.o $(BUILDDIR)/cnn_utils.o $(BUILDDIR)/cnn_free.o $(BUILDDIR)/cnn_convolution.o $(BUILDDIR)/colors.o $(BUILDDIR)/mnist.o $(BUILDDIR)/cnn-main: $(CNN_SRCDIR)/main.c $(BUILDDIR)/cnn_train.o $(BUILDDIR)/cnn_cnn.o $(BUILDDIR)/cnn_creation.o $(BUILDDIR)/cnn_initialisation.o $(BUILDDIR)/cnn_make.o $(BUILDDIR)/cnn_neuron_io.o $(BUILDDIR)/cnn_function.o $(BUILDDIR)/cnn_utils.o $(BUILDDIR)/cnn_free.o $(BUILDDIR)/cnn_convolution.o $(BUILDDIR)/cnn_backpropagation.o $(BUILDDIR)/colors.o $(BUILDDIR)/mnist.o
$(CC) $(CFLAGS) $^ -o $@ $(CC) $(CFLAGS) $^ -o $@
$(BUILDDIR)/cnn-main-cuda: $(BUILDDIR)/cnn_main.o $(BUILDDIR)/cnn_train.o $(BUILDDIR)/cnn_cnn.o $(BUILDDIR)/cnn_creation.o $(BUILDDIR)/cnn_initialisation.o $(BUILDDIR)/cnn_make.o $(BUILDDIR)/cnn_neuron_io.o $(BUILDDIR)/cnn_function.o $(BUILDDIR)/cnn_utils.o $(BUILDDIR)/cnn_free.o $(BUILDDIR)/cnn_cuda_convolution.o $(BUILDDIR)/colors.o $(BUILDDIR)/mnist.o $(BUILDDIR)/cnn-main-cuda: $(BUILDDIR)/cnn_main.o $(BUILDDIR)/cnn_train.o $(BUILDDIR)/cnn_cnn.o $(BUILDDIR)/cnn_creation.o $(BUILDDIR)/cnn_initialisation.o $(BUILDDIR)/cnn_make.o $(BUILDDIR)/cnn_neuron_io.o $(BUILDDIR)/cnn_function.o $(BUILDDIR)/cnn_utils.o $(BUILDDIR)/cnn_free.o $(BUILDDIR)/cnn_cuda_convolution.o $(BUILDDIR)/cnn_backpropagation.o $(BUILDDIR)/colors.o $(BUILDDIR)/mnist.o
$(NVCC) $(NVCCFLAGS) $^ -o $@ $(NVCC) $(NVCCFLAGS) $^ -o $@
$(BUILDDIR)/cnn_%.o: $(CNN_SRCDIR)/%.c $(CNN_SRCDIR)/include/%.h $(BUILDDIR)/cnn_%.o: $(CNN_SRCDIR)/%.c $(CNN_SRCDIR)/include/%.h

View File

@ -1,5 +1,7 @@
#include <math.h> #include <math.h>
#include "backpropagation.h"
#include "include/backpropagation.h"
#include "include/struct.h"
int min(int a, int b) { int min(int a, int b) {
@ -7,7 +9,7 @@ int min(int a, int b) {
} }
int max(int a, int b) { int max(int a, int b) {
return a>b?a:b; return a > b ? a : b;
} }
// Euh..... tout peut être faux à cause de la source // Euh..... tout peut être faux à cause de la source
@ -15,10 +17,10 @@ void rms_backward(float* input, float* input_z, float* output, int size) {
/* Input et output ont la même taille /* Input et output ont la même taille
On considère que la dernière couche a utilisée softmax */ On considère que la dernière couche a utilisée softmax */
float sum=0; float sum=0;
for (int i=0; i<size; i++) for (int i=0; i < size; i++)
sum += exp(input_z[i]); sum += exp(input_z[i]);
float denom = sum*sum; float denom = sum*sum;
for (int i=0; i<size; i++){ for (int i=0; i < size; i++){
float e_i = exp(input_z[i]); float e_i = exp(input_z[i]);
input[i] = 2*(input[i]-output[i])*((e_i*(sum-e_i))/denom); // ∂E/∂out_i * ∂out_i/∂net_i = 𝛿_i input[i] = 2*(input[i]-output[i])*((e_i*(sum-e_i))/denom); // ∂E/∂out_i * ∂out_i/∂net_i = 𝛿_i
} }
@ -31,9 +33,9 @@ void backward_2d_pooling(float*** input, float*** output, int input_width, int o
int size = output_width - input_width + 1; // Taille du pooling int size = output_width - input_width + 1; // Taille du pooling
int n = size*size; // Nombre d'éléments dans le pooling int n = size*size; // Nombre d'éléments dans le pooling
for (int a=0; a<depth; a++) for (int a=0; a < depth; a++)
for (int b=0; b<input_width; b++) for (int b=0; b < input_width; b++)
for (int c=0; c<input_width; c++) for (int c=0; c < input_width; c++)
input[a][b][c] = 0; input[a][b][c] = 0;
for (int i=0; i < depth; i++) { for (int i=0; i < depth; i++) {
@ -51,24 +53,25 @@ void backward_2d_pooling(float*** input, float*** output, int input_width, int o
void backward_fully_connected(Kernel_nn* ker, float* input, float* input_z, float* output, int size_input, int size_output, ptr d_function, int is_first) { void backward_fully_connected(Kernel_nn* ker, float* input, float* input_z, float* output, int size_input, int size_output, ptr d_function, int is_first) {
// Bias // Bias
for (int j=0; j<size_output; j++) { for (int j=0; j < size_output; j++) {
ker->d_bias[j] = ouput[j]; ker->d_bias[j] = output[j];
} }
// Weights // Weights
for (int i=0; i<size_input; i++) { for (int i=0; i < size_input; i++) {
for (int j=0; j<size_output; j++) { for (int j=0; j < size_output; j++) {
ker->d_weights[i][j] = input[i]*output[j]; ker->d_weights[i][j] = input[i]*output[j];
} }
} }
// Input // Input
if (is_first==1) // Pas besoin de backpropager dans l'input if (is_first==1) {// Pas besoin de backpropager dans l'input
return; return;
}
for (int i=0; i<size_input; i++) { for (int i=0; i < size_input; i++) {
float tmp=0; float tmp=0;
for (int j=0; j<size_output; j++) { for (int j=0; j < size_output; j++) {
tmp += output[j]*ker->weights[i][j]; tmp += output[j]*ker->weights[i][j];
} }
input[i] = tmp*derivative_function(input_z[i]); input[i] = tmp*derivative_function(input_z[i]);
@ -77,16 +80,16 @@ void backward_fully_connected(Kernel_nn* ker, float* input, float* input_z, floa
void backward_linearisation(Kernel_nn* ker, float*** input, float*** input_z, float* output, int depth_input, int dim_input, int size_output, ptr d_function) { void backward_linearisation(Kernel_nn* ker, float*** input, float*** input_z, float* output, int depth_input, int dim_input, int size_output, ptr d_function) {
// Bias // Bias
for (int j=0; j<size_output; j++) { for (int j=0; j < size_output; j++) {
ker->d_bias[j] += output[j]; ker->d_bias[j] += output[j];
} }
// Weights // Weights
int cpt = 0; int cpt = 0;
for (int i=0; i<depth_input; i++) { for (int i=0; i < depth_input; i++) {
for (int k=0; k<dim_input; k++) { for (int k=0; k < dim_input; k++) {
for (int l=0; l<dim_input; l++) { for (int l=0; l < dim_input; l++) {
for (int j=0; j<size_output) { for (int j=0; j < size_output; j++) {
ker->d_weights[cpt][j] += input[i][k][l]*output[j]; ker->d_weights[cpt][j] += input[i][k][l]*output[j];
cpt++; cpt++;
} }
@ -96,11 +99,11 @@ void backward_linearisation(Kernel_nn* ker, float*** input, float*** input_z, fl
// Input // Input
cpt = 0; cpt = 0;
for (int i=0; i<depth_input; i++) { for (int i=0; i < depth_input; i++) {
for (int k=0; k<dim_input; k++) { for (int k=0; k < dim_input; k++) {
for (int l=0; l<dim_input; l++) { for (int l=0; l < dim_input; l++) {
float tmp=0; float tmp=0;
for (int j=0; j<size_output; j++) { for (int j=0; j < size_output; j++) {
tmp += output[j]*ker->weights[cpt][j]; tmp += output[j]*ker->weights[cpt][j];
} }
input[i][k][l] = tmp*derivative_function(input_z[i][k][l]); input[i][k][l] = tmp*derivative_function(input_z[i][k][l]);
@ -112,9 +115,9 @@ void backward_linearisation(Kernel_nn* ker, float*** input, float*** input_z, fl
void backward_convolution(Kernel_cnn* ker, float*** input, float*** input_z, float*** output, int depth_input, int dim_input, int depth_output, int dim_output, ptr d_function, int is_first) { void backward_convolution(Kernel_cnn* ker, float*** input, float*** input_z, float*** output, int depth_input, int dim_input, int depth_output, int dim_output, ptr d_function, int is_first) {
// Bias // Bias
for (int i=0; i<depth_output; i++) { for (int i=0; i < depth_output; i++) {
for (int j=0; j<dim_output; j++) { for (int j=0; j < dim_output; j++) {
for (int k=0; k<dim_output; k++) { for (int k=0; k < dim_output; k++) {
ker->d_bias[i][j][k] += output[i][j][k]; ker->d_bias[i][j][k] += output[i][j][k];
} }
} }
@ -122,18 +125,18 @@ void backward_convolution(Kernel_cnn* ker, float*** input, float*** input_z, flo
// Weights // Weights
int k_size = dim_input - dim_output +1; int k_size = dim_input - dim_output +1;
int var = dim_input - k_size +1 int var = dim_input - k_size +1;
for (int h=0; h<depth_input; h++) { for (int h=0; h < depth_input; h++) {
for (int i=0; i<depth_output; i++) { for (int i=0; i < depth_output; i++) {
for (int j=0; j<k_size; j++) { for (int j=0; j < k_size; j++) {
for (int k=0; k<k_size; k++) { for (int k=0; k < k_size; k++) {
float tmp = 0; float tmp = 0;
for (int l=0; l<dim_output; l++) { for (int l=0; l < dim_output; l++) {
for (int m=0; m<dim_output; m++) { for (int m=0; m < dim_output; m++) {
tmp += input[h][l+j][m+k]*output[i][l][m]; tmp += input[h][l+j][m+k]*output[i][l][m];
} }
} }
ker->d_weights[h][i][j][k] += tmp; ker->d_w[h][i][j][k] += tmp;
} }
} }
} }
@ -143,18 +146,18 @@ void backward_convolution(Kernel_cnn* ker, float*** input, float*** input_z, flo
if (is_first==1) // Pas besoin de backpropager dans l'input if (is_first==1) // Pas besoin de backpropager dans l'input
return; return;
for (int i=0; i<depth_input; i++) { for (int i=0; i < depth_input; i++) {
for (int j=0; j<dim_input; j++) { for (int j=0; j < dim_input; j++) {
for (int k=0; k<dim_input; k++) { for (int k=0; k < dim_input; k++) {
float tmp = 0; float tmp = 0;
for (int l=0; l<depth_output; l++) { for (int l=0; l < depth_output; l++) {
int min_m = k_size - max(k_size, dim_input-i); int min_m = k_size - max(k_size, dim_input-i);
int max_m = min(k_size, i+1); int max_m = min(k_size, i+1);
int min_n = k_size - max(k_size, dim_input-j; int min_n = k_size - max(k_size, dim_input-j);
int max_n = min(k_size, j+1); int max_n = min(k_size, j+1);
for (int m=min_m; m < max_m; m++) { for (int m=min_m; m < max_m; m++) {
for (int n=min_n; n < max_n; n++) { for (int n=min_n; n < max_n; n++) {
tmp += output[l][i-m][j-n]*ker->weights[i][l][m][n]; tmp += output[l][i-m][j-n]*ker->w[i][l][m][n];
} }
} }
} }
@ -168,4 +171,4 @@ void backward_convolution(Kernel_cnn* ker, float*** input, float*** input_z, flo
// Only last_... have been done, we have to deal with the d_... part // Only last_... have been done, we have to deal with the d_... part
// It's EASY but it needs to be done // It's EASY but it needs to be done
// The first layer needs to be a convolution or a fully conneted one // The first layer needs to be a convolution or a fully connected one

View File

@ -5,7 +5,7 @@
#include "include/function.h" #include "include/function.h"
float max(float a, float b) { float max_float(float a, float b) {
return a < b ? b:a; return a < b ? b:a;
} }
@ -19,7 +19,7 @@ float sigmoid_derivative(float x) {
} }
float relu(float x) { float relu(float x) {
return max(0, x); return max_float(0, x);
} }
float relu_derivative(float x) { float relu_derivative(float x) {
@ -43,7 +43,7 @@ void apply_softmax_input(float ***input, int depth, int rows, int columns) {
for (int i=0; i < depth; i++) { for (int i=0; i < depth; i++) {
for (int j=0; j < rows; j++) { for (int j=0; j < rows; j++) {
for (int k=0; k < columns; k++) { for (int k=0; k < columns; k++) {
m = max(m, input[i][j][k]); m = max_float(m, input[i][j][k]);
} }
} }
} }

View File

@ -1,4 +1,6 @@
#include "function.h" #include "function.h"
#include "struct.h"
#ifndef DEF_BACKPROPAGATION_H #ifndef DEF_BACKPROPAGATION_H
#define DEF_BACKPROPAGATION_H #define DEF_BACKPROPAGATION_H

View File

@ -14,7 +14,7 @@ typedef ptr (*pm)();
/* /*
* Fonction max pour les floats * Fonction max pour les floats
*/ */
float max(float a, float b); float max_float(float a, float b);
float sigmoid(float x); float sigmoid(float x);

View File

@ -24,6 +24,12 @@ typedef struct TrainParameters {
float accuracy; float accuracy;
} TrainParameters; } TrainParameters;
/*
* Renvoie l'indice maximal d'un tableau tab de taille n
*/
int indice_max(float* tab, int n);
/* /*
* Fonction auxiliaire d'entraînement destinée à être exécutée sur plusieurs threads à la fois * Fonction auxiliaire d'entraînement destinée à être exécutée sur plusieurs threads à la fois
*/ */

View File

@ -10,6 +10,7 @@ void make_average_pooling(float*** input, float*** output, int size, int output_
// output[output_depth][output_dim][output_dim] // output[output_depth][output_dim][output_dim]
float average; float average;
int n = size*size; int n = size*size;
for (int i=0; i < output_depth; i++) { for (int i=0; i < output_depth; i++) {
for (int j=0; j < output_dim; j++) { for (int j=0; j < output_dim; j++) {
for (int k=0; k < output_dim; k++) { for (int k=0; k < output_dim; k++) {
@ -29,6 +30,7 @@ void make_dense(Kernel_nn* kernel, float* input, float* output, int size_input,
// input[size_input] // input[size_input]
// output[size_output] // output[size_output]
float f; float f;
for (int i=0; i < size_output; i++) { for (int i=0; i < size_output; i++) {
f = kernel->bias[i]; f = kernel->bias[i];
for (int j=0; j < size_input; j++) { for (int j=0; j < size_input; j++) {
@ -41,13 +43,13 @@ void make_dense(Kernel_nn* kernel, float* input, float* output, int size_input,
void make_dense_linearised(Kernel_nn* kernel, float*** input, float* output, int depth_input, int dim_input, int size_output) { void make_dense_linearised(Kernel_nn* kernel, float*** input, float* output, int depth_input, int dim_input, int size_output) {
// input[depth_input][dim_input][dim_input] // input[depth_input][dim_input][dim_input]
// output[size_output] // output[size_output]
int n = depth_input*dim_input*dim_input;
float f; float f;
for (int l=0; l<size_output; l++) {
for (int l=0; l < size_output; l++) {
f = 0; f = 0;
for (int i=0; i<depth_input; i++) { for (int i=0; i < depth_input; i++) {
for (int j=0; j<dim_input; j++) { for (int j=0; j < dim_input; j++) {
for (int k=0; k<dim_input; k++) { for (int k=0; k < dim_input; k++) {
f += input[i][j][k]*kernel->weights[k + j*dim_input + i*depth_input][l]; f += input[i][j][k]*kernel->weights[k + j*dim_input + i*depth_input][l];
} }
} }

View File

@ -17,9 +17,24 @@
#include "include/train.h" #include "include/train.h"
int indice_max(float* tab, int n) {
int indice = -1;
float maxi = FLT_MIN;
for (int i=0; i < n; i++) {
if (tab[i] > maxi) {
maxi = tab[i];
indice = i;
}
}
return indice;
}
void* train_thread(void* parameters) { void* train_thread(void* parameters) {
TrainParameters* param = (TrainParameters*)parameters; TrainParameters* param = (TrainParameters*)parameters;
Network* network = param->network; Network* network = param->network;
int maxi;
int*** images = param->images; int*** images = param->images;
int* labels = (int*)param->labels; int* labels = (int*)param->labels;
@ -37,8 +52,10 @@ void* train_thread(void* parameters) {
forward_propagation(network); forward_propagation(network);
backward_propagation(network, labels[i]); backward_propagation(network, labels[i]);
// TODO get_indice_max(network last layer) maxi = indice_max(network->input[network->size-1][0][0], network->width[network->size-1]);
// TODO if indice_max == labels[i] then accuracy += 1. if (maxi == labels[i]) {
accuracy += 1.;
}
} else { } else {
printf_error("Dataset de type JPG non implémenté\n"); printf_error("Dataset de type JPG non implémenté\n");
exit(1); exit(1);

View File

@ -1,5 +1,6 @@
#include "update.h" #include "include/update.h"
#include "include/struct.h"
void update_weights(Network* network) { void update_weights(Network* network) {
int n = network->size; int n = network->size;