diff --git a/src/mnist/main.c b/src/mnist/main.c index a083e1e..0fa206e 100644 --- a/src/mnist/main.c +++ b/src/mnist/main.c @@ -2,22 +2,82 @@ #include #include +#include "neural_network.c" +#include "neuron_io.c" +#include "mnist.c" + + void help(char* call) { printf("Usage: %s ( train | recognize ) [OPTIONS]\n\n", call); printf("OPTIONS:\n"); printf("\ttrain:\n"); - printf("\t\t--batches | -b [int]\tNombre de batches\n"); - printf("\t\t--couches | -c [int]\tNombres de couches\n"); - printf("\t\t--neurons | -n [int]\tNombre de neurones sur la première couche\n"); - printf("\t\t--images | -i [FILENAME]\tFichier contenant les images\n"); - printf("\t\t--labels | -l [FILENAME]\tFichier contenant les labels\n"); - printf("\t\t--out | -o [FILENAME]\tFichier où écrire le réseau de neurones\n"); + printf("\t\t--batches | -b [int]\tNombre de batches.\n"); + printf("\t\t--couches | -c [int]\tNombres de couches.\n"); + printf("\t\t--neurons | -n [int]\tNombre de neurones sur la première couche.\n"); + printf("\t\t--recover | -r [FILENAME]\tRécupérer depuis un modèle existant.\n"); + printf("\t\t--images | -i [FILENAME]\tFichier contenant les images.\n"); + printf("\t\t--labels | -l [FILENAME]\tFichier contenant les labels.\n"); + printf("\t\t--out | -o [FILENAME]\tFichier où écrire le réseau de neurones.\n"); printf("\trecognize:\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--out | -o (text|json)\tFormat de sortie\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--out | -o (text|json)\tFormat de sortie.\n"); } + +void ecrire_image_dans_reseau(int** image, Reseau* reseau, int height, int width) { + for (int i=0; i < height; i++) { + for (int j=0; j < width; j++) { + reseau->couches[0]->neurones[i*height+j]->activation = (float)image[i][j] / 255.0; + } + } +} + + +void train(int batches, int couches, int neurons, char* recovery, char* image_file, char* label_file, char* out) { + Reseau* reseau; + + //int* repartition = malloc(sizeof(int)*couches); + int* sortie_voulue; + int repartition[5] = {784, 100, 75, 40, 10}; + //generer_repartition(couches, repartition); + + /* + * On repart d'un réseau déjà créée stocké dans un fichier + * ou on repart de zéro si aucune backup n'est fournie + * */ + if (! recovery) { + reseau = malloc(sizeof(Reseau)); + creation_du_reseau_neuronal(reseau, repartition, couches); + } else { + reseau = lire_reseau(recovery); + printf("Backup restorée.\n"); + } + + // Chargement des images du set de données MNIST + int* parameters = read_mnist_images_parameters(image_file); + int nb_images = parameters[0]; + int height = parameters[1]; + int width = parameters[2]; + + int*** images = read_mnist_images(image_file); + unsigned int* labels = read_mnist_labels(label_file); + + for (int i=0; i < batches; i++) { + printf("Batch [%d/%d]\n", i, batches); + for (int j=0; j < nb_images; j++) { + printf("\rImage [%d/%d]", j, nb_images); + ecrire_image_dans_reseau(images[j], reseau, height, width); + sortie_voulue = creation_de_la_sortie_voulue(reseau, labels[j]); + forward_propagation(reseau); + backward_propagation(reseau, sortie_voulue); + } + printf("\n"); + ecrire_reseau(out, reseau); + } +} + + int main(int argc, char* argv[]) { if (argc < 2) { printf("Pas d'action spécifiée\n"); @@ -30,6 +90,7 @@ int main(int argc, char* argv[]) { int neurons = 784; char* images = NULL; char* labels = NULL; + char* recovery = NULL; char* out = NULL; int i=2; while (i < argc) { @@ -50,6 +111,9 @@ int main(int argc, char* argv[]) { } else if ((! strcmp(argv[i], "--labels"))||(! strcmp(argv[i], "-l"))) { labels = argv[i+1]; i += 2; + } else if ((! strcmp(argv[i], "--recover"))||(! strcmp(argv[i], "-r"))) { + recovery = argv[i+1]; + i += 2; } else if ((! strcmp(argv[i], "--out"))||(! strcmp(argv[i], "-o"))) { out = argv[i+1]; i += 2; @@ -71,6 +135,7 @@ int main(int argc, char* argv[]) { out = "out.bin"; } // Entraînement en sourçant neural_network.c + train(batches, couches, neurons, recovery, images, labels, out); exit(0); } if (! strcmp(argv[1], "recognize")) { diff --git a/src/mnist/neural_network.c b/src/mnist/neural_network.c index e3a711b..32a0696 100644 --- a/src/mnist/neural_network.c +++ b/src/mnist/neural_network.c @@ -100,11 +100,14 @@ int* creation_de_la_sortie_voulue(Reseau* reseau_neuronal, int pos_nombre_voulu) /* Renvoie la liste des sorties voulues à partir du nombre de couches, de la liste du nombre de neurones par couche et de la position du résultat voulue, */ + int nb_neurones = reseau_neuronal->couches[reseau_neuronal->nb_couches-1]->nb_neurones; - int* sortie_voulue = (int*)malloc(sizeof(int)); - for (int i=0; icouches[reseau_neuronal->nb_couches-1]->nb_neurones; i++) // On initialise toutes les sorties à 0 par défault - sortie_voulue[i]=0; - sortie_voulue[pos_nombre_voulu]=1; // Seule la sortie voulue vaut 1 + int* sortie_voulue = (int*)malloc(sizeof(int)*nb_neurones); + + for (int i=0; i < nb_neurones; i++) // On initialise toutes les sorties à 0 par défault + sortie_voulue[i] = 0; + + sortie_voulue[pos_nombre_voulu] = 1; // Seule la sortie voulue vaut 1 return sortie_voulue; } diff --git a/src/mnist/neuron_io.c b/src/mnist/neuron_io.c index 36ead94..4157b0e 100644 --- a/src/mnist/neuron_io.c +++ b/src/mnist/neuron_io.c @@ -60,7 +60,6 @@ Reseau* lire_reseau(char* filename) { uint32_t magic_number; uint32_t nb_couches; uint32_t tmp; - reseau->nb_couches = nb_couches; fread(&magic_number, sizeof(uint32_t), 1, ptr); if (magic_number != MAGIC_NUMBER) { @@ -69,6 +68,7 @@ Reseau* lire_reseau(char* filename) { } fread(&nb_couches, sizeof(uint32_t), 1, ptr); + reseau->nb_couches = nb_couches; Couche** couches = malloc(sizeof(Couche*)*nb_couches); @@ -77,7 +77,7 @@ Reseau* lire_reseau(char* filename) { reseau->couches = couches; for (int i=0; i < nb_couches; i++) { - couches[i] = malloc(sizeof(int)+sizeof(Neurone**)); + couches[i] = malloc(sizeof(Couche)); fread(&tmp, sizeof(tmp), 1, ptr); couches[i]->nb_neurones = tmp; nb_neurones_couche[i] = tmp;