mirror of
https://github.com/augustin64/projet-tipe
synced 2025-02-02 19:39:39 +01:00
Update backpropagation.c
This commit is contained in:
parent
9d03611744
commit
4637d62e73
4
Makefile
4
Makefile
@ -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
|
||||||
|
@ -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
|
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user