dense: Add random offset option

This commit is contained in:
augustin64 2023-05-25 11:00:49 +02:00
parent a2cd6ef551
commit 3183339b7a
3 changed files with 92 additions and 26 deletions

View File

@ -28,7 +28,7 @@ void help(char* call);
* network: réseau neuronal * network: réseau neuronal
* height, width: dimensions de l'image * height, width: dimensions de l'image
*/ */
void write_image_in_network(int** image, Network* network, int height, int width); void write_image_in_network(int** image, Network* network, int height, int width, bool random_offset);
/* /*
* Sous fonction de 'train' assignée à un thread * Sous fonction de 'train' assignée à un thread
@ -49,7 +49,7 @@ void* train_thread(void* parameters);
* nb_images_to_process: nombre d'images sur lesquelles entraîner le réseau (-1 si non utilisé) * nb_images_to_process: nombre d'images sur lesquelles entraîner le réseau (-1 si non utilisé)
* start: index auquel démarrer si nb_images_to_process est utilisé (0 si non utilisé) * start: index auquel démarrer si nb_images_to_process est utilisé (0 si non utilisé)
*/ */
void train(int epochs, char* recovery, char* image_file, char* label_file, char* out, char* delta, int nb_images_to_process, int start); void train(int epochs, char* recovery, char* image_file, char* label_file, char* out, char* delta, int nb_images_to_process, int start, bool random_offset);
/* /*
* Échange deux éléments d'un tableau * Échange deux éléments d'un tableau
@ -66,7 +66,7 @@ void knuth_shuffle(int* tab, int n);
* modele: nom du fichier contenant le réseau neuronal * modele: nom du fichier contenant le réseau neuronal
* entree: nom du fichier contenant les images à reconnaître * entree: nom du fichier contenant les images à reconnaître
*/ */
float** recognize(char* modele, char* entree); float** recognize(char* modele, char* entree, bool random_offset);
/* /*
* Renvoie les prédictions d'images sur stdout * Renvoie les prédictions d'images sur stdout
@ -74,7 +74,7 @@ float** recognize(char* modele, char* entree);
* entree: fichier contenant les images * entree: fichier contenant les images
* sortie: vaut 'text' ou 'json', spécifie le format auquel afficher les prédictions * sortie: vaut 'text' ou 'json', spécifie le format auquel afficher les prédictions
*/ */
void print_recognize(char* modele, char* entree, char* sortie); void print_recognize(char* modele, char* entree, char* sortie, bool random_offset);
/* /*
* Teste un réseau neuronal avec un fichier d'images ainsi que leurs propriétés * Teste un réseau neuronal avec un fichier d'images ainsi que leurs propriétés
@ -83,7 +83,7 @@ void print_recognize(char* modele, char* entree, char* sortie);
* fichier_labels: nom du fichier contenant les labels * fichier_labels: nom du fichier contenant les labels
* preview_fails: faut-il afficher les images qui ne sont pas correctement reconnues ? * preview_fails: faut-il afficher les images qui ne sont pas correctement reconnues ?
*/ */
void test(char* modele, char* fichier_images, char* fichier_labels, bool preview_fails); void test(char* modele, char* fichier_images, char* fichier_labels, bool preview_fails, bool random_offset);
int main(int argc, char* argv[]); int main(int argc, char* argv[]);

View File

@ -22,8 +22,8 @@
#define PRINT_BIAIS false #define PRINT_BIAIS false
// Mettre à 1 pour désactiver // Mettre à 1 pour désactiver
#define DROPOUT 0.7 #define DROPOUT 1
#define ENTRY_DROPOUT 0.85 #define ENTRY_DROPOUT 1
bool drop(float prob); bool drop(float prob);

View File

@ -29,6 +29,7 @@ typedef struct TrainParameters {
int height; int height;
int width; int width;
float accuracy; float accuracy;
bool offset;
} TrainParameters; } TrainParameters;
@ -71,6 +72,7 @@ void help(char* call) {
printf("\t\t--delta | -d [FILENAME]\tFichier où écrire le réseau différentiel.\n"); printf("\t\t--delta | -d [FILENAME]\tFichier où écrire le réseau différentiel.\n");
printf("\t\t--nb-images | -N [int]\tNombres d'images à traiter.\n"); printf("\t\t--nb-images | -N [int]\tNombres d'images à traiter.\n");
printf("\t\t--start | -s [int]\tPremière image à traiter.\n"); printf("\t\t--start | -s [int]\tPremière image à traiter.\n");
printf("\t\t--offset \tActiver le décalage aléatoire.\n");
printf("\trecognize:\n"); printf("\trecognize:\n");
printf("\t\t--modele | -m [FILENAME]\tFichier contenant le réseau de neurones.\n"); printf("\t\t--modele | -m [FILENAME]\tFichier contenant le réseau de neurones.\n");
printf("\t\t--in | -i [FILENAME]\tFichier contenant les images à reconnaître.\n"); printf("\t\t--in | -i [FILENAME]\tFichier contenant les images à reconnaître.\n");
@ -80,16 +82,67 @@ void help(char* call) {
printf("\t\t--labels | -l [FILENAME]\tFichier contenant les labels.\n"); printf("\t\t--labels | -l [FILENAME]\tFichier contenant les labels.\n");
printf("\t\t--modele | -m [FILENAME]\tFichier contenant le réseau de neurones.\n"); printf("\t\t--modele | -m [FILENAME]\tFichier contenant le réseau de neurones.\n");
printf("\t\t--preview-fails | -p\tAfficher les images ayant échoué.\n"); printf("\t\t--preview-fails | -p\tAfficher les images ayant échoué.\n");
printf("\t\t--offset \tActiver le décalage aléatoire.\n");
} }
void write_image_in_network(int** image, Network* network, int height, int width) { void write_image_in_network(int** image, Network* network, int height, int width, bool random_offset) {
for (int i=0; i < height; i++) { int i_offset = 0;
for (int j=0; j < width; j++) { int j_offset = 0;
if (!drop(ENTRY_DROPOUT)) { int min_col = 0;
network->layers[0]->neurons[i*height+j]->z = (float)image[i][j] / 255.0f; int min_ligne = 0;
if (random_offset) {
int sum_colonne[width];
int sum_ligne[height];
for (int i=0; i < width; i++) {
sum_colonne[i] = 0;
}
for (int j=0; j < height; j++) {
sum_ligne[j] = 0;
}
for (int i=0; i < width; i++) {
for (int j=0; j < height; j++) {
sum_ligne[i] += image[i][j];
sum_colonne[j] += image[i][j];
}
}
min_ligne = -1;
while (sum_ligne[min_ligne+1] == 0 && min_ligne < width+1) {
min_ligne++;
}
int max_ligne = width;
while (sum_ligne[max_ligne-1] == 0 && max_ligne > 0) {
max_ligne--;
}
min_col = -1;
while (sum_colonne[min_col+1] == 0 && min_col < height+1) {
min_col++;
}
int max_col = height;
while (sum_colonne[max_col-1] == 0 && max_col > 0) {
max_col--;
}
i_offset = 27-max_ligne+min_ligne == 0 ? 0 : rand()%(27-max_ligne+min_ligne);
j_offset = 27 - max_col + min_col == 0 ? 0 : rand()%(27-max_col+min_col);
}
for (int i=0; i < width; i++) {
for (int j=0; j < height; j++) {
int adjusted_i = i + min_ligne - i_offset;
int adjusted_j = j + min_col - j_offset;
// Make sure not to be out of the image
if (!drop(ENTRY_DROPOUT) && adjusted_i < height && adjusted_j < width && adjusted_i >= 0 && adjusted_j >= 0) {
network->layers[0]->neurons[i*height+j]->z = (float)image[adjusted_i][adjusted_j] / 255.0f;
} else { } else {
network->layers[0]->neurons[i*height+j]->z = 0; network->layers[0]->neurons[i*height+j]->z = 0.;
} }
} }
} }
@ -114,7 +167,7 @@ void* train_thread(void* parameters) {
int* desired_output; int* desired_output;
for (int i=start; i < start+nb_images; i++) { for (int i=start; i < start+nb_images; i++) {
write_image_in_network(images[shuffle[i]], network, height, width); write_image_in_network(images[shuffle[i]], network, height, width, param->offset);
desired_output = desired_output_creation(network, labels[shuffle[i]]); desired_output = desired_output_creation(network, labels[shuffle[i]]);
forward_propagation(network, true); forward_propagation(network, true);
backward_propagation(network, desired_output); backward_propagation(network, desired_output);
@ -134,7 +187,7 @@ void* train_thread(void* parameters) {
} }
void train(int epochs, char* recovery, char* image_file, char* label_file, char* out, char* delta, int nb_images_to_process, int start) { void train(int epochs, char* recovery, char* image_file, char* label_file, char* out, char* delta, int nb_images_to_process, int start, bool offset) {
// Entraînement du réseau sur le set de données MNIST // Entraînement du réseau sur le set de données MNIST
Network* network; Network* network;
Network* delta_network; Network* delta_network;
@ -207,6 +260,7 @@ void train(int epochs, char* recovery, char* image_file, char* label_file, char*
train_parameters[j]->width = width; train_parameters[j]->width = width;
train_parameters[j]->nb_images = BATCHES / nb_threads; train_parameters[j]->nb_images = BATCHES / nb_threads;
train_parameters[j]->shuffle_indices = shuffle_indices; train_parameters[j]->shuffle_indices = shuffle_indices;
train_parameters[j]->offset = offset;
} }
for (int i=0; i < epochs; i++) { for (int i=0; i < epochs; i++) {
@ -245,7 +299,7 @@ void train(int epochs, char* recovery, char* image_file, char* label_file, char*
if (delta != NULL) if (delta != NULL)
write_delta_network(delta, delta_network); write_delta_network(delta, delta_network);
test(out, "data/mnist/t10k-images-idx3-ubyte", "data/mnist/t10k-labels-idx1-ubyte", false); test(out, "data/mnist/t10k-images-idx3-ubyte", "data/mnist/t10k-labels-idx1-ubyte", false, offset);
} }
write_network(out, network); write_network(out, network);
if (delta != NULL) { if (delta != NULL) {
@ -283,7 +337,7 @@ void knuth_shuffle(int* tab, int n) {
} }
} }
float** recognize(char* modele, char* entree) { float** recognize(char* modele, char* entree, bool offset) {
Network* network = read_network(modele); Network* network = read_network(modele);
Layer* last_layer = network->layers[network->nb_layers-1]; Layer* last_layer = network->layers[network->nb_layers-1];
@ -299,7 +353,7 @@ float** recognize(char* modele, char* entree) {
for (int i=0; i < nb_images; i++) { for (int i=0; i < nb_images; i++) {
results[i] = (float*)malloc(sizeof(float)*last_layer->nb_neurons); results[i] = (float*)malloc(sizeof(float)*last_layer->nb_neurons);
write_image_in_network(images[i], network, height, width); write_image_in_network(images[i], network, height, width, offset);
forward_propagation(network, false); forward_propagation(network, false);
for (int j=0; j < last_layer->nb_neurons; j++) { for (int j=0; j < last_layer->nb_neurons; j++) {
@ -310,7 +364,7 @@ float** recognize(char* modele, char* entree) {
return results; return results;
} }
void print_recognize(char* modele, char* entree, char* sortie) { void print_recognize(char* modele, char* entree, char* sortie, bool offset) {
Network* network = read_network(modele); Network* network = read_network(modele);
int nb_last_layer = network->layers[network->nb_layers-1]->nb_neurons; int nb_last_layer = network->layers[network->nb_layers-1]->nb_neurons;
@ -319,7 +373,7 @@ void print_recognize(char* modele, char* entree, char* sortie) {
int* parameters = read_mnist_images_parameters(entree); int* parameters = read_mnist_images_parameters(entree);
int nb_images = parameters[0]; int nb_images = parameters[0];
float** results = recognize(modele, entree); float** results = recognize(modele, entree, offset);
if (! strcmp(sortie, "json")) { if (! strcmp(sortie, "json")) {
printf("{\n"); printf("{\n");
@ -356,7 +410,7 @@ void print_recognize(char* modele, char* entree, char* sortie) {
} }
} }
void test(char* modele, char* fichier_images, char* fichier_labels, bool preview_fails) { void test(char* modele, char* fichier_images, char* fichier_labels, bool preview_fails, bool offset) {
Network* network = read_network(modele); Network* network = read_network(modele);
int nb_last_layer = network->layers[network->nb_layers-1]->nb_neurons; int nb_last_layer = network->layers[network->nb_layers-1]->nb_neurons;
@ -368,7 +422,7 @@ void test(char* modele, char* fichier_images, char* fichier_labels, bool preview
int height = parameters[2]; int height = parameters[2];
int*** images = read_mnist_images(fichier_images); int*** images = read_mnist_images(fichier_images);
float** results = recognize(modele, fichier_images); float** results = recognize(modele, fichier_images, offset);
unsigned int* labels = read_mnist_labels(fichier_labels); unsigned int* labels = read_mnist_labels(fichier_labels);
float accuracy = 0.; float accuracy = 0.;
@ -402,6 +456,8 @@ int main(int argc, char* argv[]) {
char* recovery = NULL; char* recovery = NULL;
char* out = NULL; char* out = NULL;
char* delta = NULL; char* delta = NULL;
bool offset = false;
int i = 2; int i = 2;
while (i < argc) { while (i < argc) {
// Utiliser un switch serait sans doute plus élégant // Utiliser un switch serait sans doute plus élégant
@ -429,6 +485,9 @@ int main(int argc, char* argv[]) {
} else if ((! strcmp(argv[i], "--start"))||(! strcmp(argv[i], "-s"))) { } else if ((! strcmp(argv[i], "--start"))||(! strcmp(argv[i], "-s"))) {
start = strtol(argv[i+1], NULL, 10); start = strtol(argv[i+1], NULL, 10);
i += 2; i += 2;
} else if (! strcmp(argv[i], "--offset")) {
offset = true;
i++;
} else { } else {
printf("%s : Argument non reconnu\n", argv[i]); printf("%s : Argument non reconnu\n", argv[i]);
i++; i++;
@ -446,8 +505,8 @@ int main(int argc, char* argv[]) {
printf("Pas de fichier de sortie spécifié, default: out.bin\n"); printf("Pas de fichier de sortie spécifié, default: out.bin\n");
out = "out.bin"; out = "out.bin";
} }
// Entraînement en sourçant neural_network.c // Entraînement (dans neural_network.c)
train(epochs, recovery, images, labels, out, delta, nb_images, start); train(epochs, recovery, images, labels, out, delta, nb_images, start, offset);
return 0; return 0;
} }
if (! strcmp(argv[1], "recognize")) { if (! strcmp(argv[1], "recognize")) {
@ -481,7 +540,7 @@ int main(int argc, char* argv[]) {
if (! out) { if (! out) {
out = "text"; out = "text";
} }
print_recognize(modele, in, out); print_recognize(modele, in, out, false);
// Reconnaissance puis affichage des données sous le format spécifié // Reconnaissance puis affichage des données sous le format spécifié
return 0; return 0;
} }
@ -490,6 +549,7 @@ int main(int argc, char* argv[]) {
char* images = NULL; char* images = NULL;
char* labels = NULL; char* labels = NULL;
bool preview_fails = false; bool preview_fails = false;
bool offset = false;
int i = 2; int i = 2;
while (i < argc) { while (i < argc) {
if ((! strcmp(argv[i], "--images"))||(! strcmp(argv[i], "-i"))) { if ((! strcmp(argv[i], "--images"))||(! strcmp(argv[i], "-i"))) {
@ -504,9 +564,15 @@ int main(int argc, char* argv[]) {
} else if ((! strcmp(argv[i], "--preview-fails"))||(! strcmp(argv[i], "-p"))) { } else if ((! strcmp(argv[i], "--preview-fails"))||(! strcmp(argv[i], "-p"))) {
preview_fails = true; preview_fails = true;
i++; i++;
} else if (! strcmp(argv[i], "--offset")) {
offset = true;
i++;
} else {
printf("%s : Argument non reconnu\n", argv[i]);
i++;
} }
} }
test(modele, images, labels, preview_fails); test(modele, images, labels, preview_fails, offset);
return 0; return 0;
} }
printf("Option choisie non reconnue: %s\n", argv[1]); printf("Option choisie non reconnue: %s\n", argv[1]);