Add Reseau structure

This commit is contained in:
Julien Chemillier 2022-03-26 18:50:09 +01:00
parent 35b985840c
commit 95f8d76b46
2 changed files with 62 additions and 57 deletions

View File

@ -8,31 +8,31 @@
#define TAUX_APPRENTISSAGE 0.15 // Définit le taux d'apprentissage du réseau neuronal, donc la rapidité d'adaptation du modèle (compris entre 0 et 1) #define TAUX_APPRENTISSAGE 0.15 // Définit le taux d'apprentissage du réseau neuronal, donc la rapidité d'adaptation du modèle (compris entre 0 et 1)
Couche* reseau_neuronal; Reseau* reseau_neuronal;
void creation_du_reseau_neuronal(int nb_couches, int* neurones_par_couche); void creation_du_reseau_neuronal(int* neurones_par_couche);
void suppression_du_reseau_neuronal(int nb_couches, int* neurones_par_couche); void suppression_du_reseau_neuronal(int* neurones_par_couche);
void forward_propagation(int nb_couches, int* neurones_par_couche); void forward_propagation(int* neurones_par_couche);
int* creation_de_la_sortie_voulue(int nb_couches, int* neurones_par_couche, int pos_nombre_voulu); int* creation_de_la_sortie_voulue(int* neurones_par_couche, int pos_nombre_voulu);
void backward_propagation(int nb_couches, int* neurones_par_couche, int* sortie_voulue); void backward_propagation(int* neurones_par_couche, int* sortie_voulue);
void modification_du_reseau_neuronal(int nb_couches, int* neurones_par_couche); void modification_du_reseau_neuronal(int* neurones_par_couche);
void initialisation_du_reseau_neuronal(int nb_couches, int* neurones_par_couche); void initialisation_du_reseau_neuronal(int* neurones_par_couche);
void creation_du_reseau_neuronal(int nb_couches, int* neurones_par_couche) { void creation_du_reseau_neuronal(int* neurones_par_couche) {
/* Créé les différentes variables dans la variable du réseau neuronal à /* Créé les différentes variables dans la variable du réseau neuronal à
partir du nombre de couches et de la liste du nombre de neurones par couche */ partir du nombre de couches et de la liste du nombre de neurones par couche */
reseau_neuronal = (Couche*)malloc(sizeof(Couche)*nb_couches); // Création des différentes couches reseau_neuronal->couche = (Couche*)malloc(sizeof(Couche)*reseau_neuronal->nb_couche); // Création des différentes couches
for (int i=0; i<nb_couches; i++) { for (int i=0; i<reseau_neuronal->nb_couche; i++) {
reseau_neuronal[i].nb_neurone = neurones_par_couche[i]; // nombre de neurones pour la couche reseau_neuronal->couche[i].nb_neurone = neurones_par_couche[i]; // nombre de neurones pour la couche
reseau_neuronal[i].neurone = (Neurone*)malloc(sizeof(Neurone)*neurones_par_couche[i]); // Création des différents neurones dans la couche reseau_neuronal->couche[i].neurone = (Neurone*)malloc(sizeof(Neurone)*neurones_par_couche[i]); // Création des différents neurones dans la couche
if (i!=nb_couches-1) { // On exclut la dernière couche dont les neurones ne contiennent pas de poids sortants if (i!=reseau_neuronal->nb_couche-1) { // On exclut la dernière couche dont les neurones ne contiennent pas de poids sortants
for (int j=0; j<neurones_par_couche[i]; j++) { for (int j=0; j<neurones_par_couche[i]; j++) {
reseau_neuronal[i].neurone[j].poids_sortants = (float*)malloc(sizeof(float)*neurones_par_couche[i+1]) ;// Création des poids sortants du neurone reseau_neuronal->couche[i].neurone[j].poids_sortants = (float*)malloc(sizeof(float)*neurones_par_couche[i+1]) ;// Création des poids sortants du neurone
} }
} }
} }
@ -41,18 +41,18 @@ void creation_du_reseau_neuronal(int nb_couches, int* neurones_par_couche) {
void suppression_du_reseau_neuronal(int nb_couches, int* neurones_par_couche) { void suppression_du_reseau_neuronal(int* neurones_par_couche) {
/* Libère l'espace mémoire alloué aux différentes variables dans la fonction /* Libère l'espace mémoire alloué aux différentes variables dans la fonction
'creation_du_reseau_neuronal' à partir du nombre de couche et de la liste du 'creation_du_reseau_neuronal' à partir du nombre de couche et de la liste du
nombre de neurone par couche */ nombre de neurone par couche */
for (int i=0; i<nb_couches; i++) { for (int i=0; i<reseau_neuronal->nb_couche; i++) {
if (i!=nb_couches-1) { // On exclut la dernière couche dont les neurones ne contiennent pas de poids sortants if (i!=reseau_neuronal->nb_couche-1) { // On exclut la dernière couche dont les neurones ne contiennent pas de poids sortants
for (int j=0; j<neurones_par_couche[i]; j++) { for (int j=0; j<neurones_par_couche[i]; j++) {
free(reseau_neuronal[i].neurone[j].poids_sortants); // On libère la variables des poids sortants free(reseau_neuronal->couche[i].neurone[j].poids_sortants); // On libère la variables des poids sortants
} }
} }
free(reseau_neuronal[i].neurone); // On libère enfin la liste des neurones de la couche free(reseau_neuronal->couche[i].neurone); // On libère enfin la liste des neurones de la couche
} }
free(reseau_neuronal); // Pour finir, on libère le réseau neronal contenant la liste des couches free(reseau_neuronal); // Pour finir, on libère le réseau neronal contenant la liste des couches
} }
@ -60,26 +60,26 @@ void suppression_du_reseau_neuronal(int nb_couches, int* neurones_par_couche) {
void forward_propagation(int nb_couches, int* neurones_par_couche) { void forward_propagation(int* neurones_par_couche) {
/* Effectue une propagation en avant du réseau neuronal à partir du nombre /* Effectue une propagation en avant du réseau neuronal à partir du nombre
de couches et de la liste du nombre de neurones par couche */ de couches et de la liste du nombre de neurones par couche */
for (int i=1; i<nb_couches; i++) { // La première couche contient déjà des valeurs for (int i=1; i<reseau_neuronal->nb_couche; i++) { // La première couche contient déjà des valeurs
for (int j=0; j<neurones_par_couche[i];j++) { // Pour chaque neurone de la couche for (int j=0; j<neurones_par_couche[i];j++) { // Pour chaque neurone de la couche
reseau_neuronal[i].neurone[j].z = reseau_neuronal[i].neurone[j].biais; // On réinitialise l'utilisation actuelle du neurone à son biais reseau_neuronal->couche[i].neurone[j].z = reseau_neuronal->couche[i].neurone[j].biais; // On réinitialise l'utilisation actuelle du neurone à son biais
for (int k=0; k<neurones_par_couche[i-1]; k++) { for (int k=0; k<neurones_par_couche[i-1]; k++) {
reseau_neuronal[i].neurone[j].z += reseau_neuronal[i-1].neurone[k].activation * reseau_neuronal[i-1].neurone[k].z * reseau_neuronal[i-1].neurone[k].poids_sortants[i]; // ??? reseau_neuronal->couche[i].neurone[j].z += reseau_neuronal->couche[i-1].neurone[k].activation * reseau_neuronal->couche[i-1].neurone[k].z * reseau_neuronal->couche[i-1].neurone[k].poids_sortants[i]; // ???
} }
if (i<nb_couches-1) { // Pour toutes les couches sauf la dernière on utilise la fonction relu if (i<reseau_neuronal->nb_couche-1) { // Pour toutes les couches sauf la dernière on utilise la fonction relu
if (reseau_neuronal[i].neurone[j].z < 0) if (reseau_neuronal->couche[i].neurone[j].z < 0)
reseau_neuronal[i].neurone[j].activation = 0; reseau_neuronal->couche[i].neurone[j].activation = 0;
else else
reseau_neuronal[i].neurone[j].activation = reseau_neuronal[i].neurone[j].z; reseau_neuronal->couche[i].neurone[j].activation = reseau_neuronal->couche[i].neurone[j].z;
} }
else{ // Pour la dernière couche on utilise la fonction sigmoid permettant d'obtenir un résultat entre 0 et 1 étant une probabilité else{ // Pour la dernière couche on utilise la fonction sigmoid permettant d'obtenir un résultat entre 0 et 1 étant une probabilité
reseau_neuronal[i].neurone[j].activation = 1/(1 + exp(reseau_neuronal[i].neurone[j].activation)); reseau_neuronal->couche[i].neurone[j].activation = 1/(1 + exp(reseau_neuronal->couche[i].neurone[j].activation));
} }
} }
} }
@ -88,13 +88,13 @@ void forward_propagation(int nb_couches, int* neurones_par_couche) {
int* creation_de_la_sortie_voulue(int nb_couches, int* neurones_par_couche, int pos_nombre_voulu) { int* creation_de_la_sortie_voulue(int* neurones_par_couche, int pos_nombre_voulu) {
/* Renvoie la liste des sorties voulues à partir du nombre /* Renvoie la liste des sorties voulues à partir du nombre
de couches, de la liste du nombre de neurones par couche et de la de couches, de la liste du nombre de neurones par couche et de la
position du résultat voulue, */ position du résultat voulue, */
int* sortie_voulue = (int*)malloc(sizeof(int)); int* sortie_voulue = (int*)malloc(sizeof(int));
for (int i=0; i<neurones_par_couche[nb_couches-1]; i++) // On initialise toutes les sorties à 0 par défault for (int i=0; i<neurones_par_couche[reseau_neuronal->nb_couche-1]; i++) // On initialise toutes les sorties à 0 par défault
sortie_voulue[i]=0; sortie_voulue[i]=0;
sortie_voulue[pos_nombre_voulu]=1; // Seule la sortie voulue vaut 1 sortie_voulue[pos_nombre_voulu]=1; // Seule la sortie voulue vaut 1
return sortie_voulue; return sortie_voulue;
@ -103,37 +103,37 @@ int* creation_de_la_sortie_voulue(int nb_couches, int* neurones_par_couche, int
void backward_propagation(int nb_couches, int* neurones_par_couche, int* sortie_voulue) { void backward_propagation(int* neurones_par_couche, int* sortie_voulue) {
/* Effectue une propagation en arrière du réseau neuronal à partir du /* Effectue une propagation en arrière du réseau neuronal à partir du
nombre de couches, de la liste du nombre de neurone par couche et de nombre de couches, de la liste du nombre de neurone par couche et de
la liste des sorties voulues*/ la liste des sorties voulues*/
// On commence par parcourir tous les neurones de la couche finale // On commence par parcourir tous les neurones de la couche finale
for (int i=0; i<neurones_par_couche[nb_couches-1]; i++) { for (int i=0; i<neurones_par_couche[reseau_neuronal->nb_couche-1]; i++) {
// On applique la formule de propagation en arrière // On applique la formule de propagation en arrière
reseau_neuronal[nb_couches-1].neurone[i].dz = (reseau_neuronal[nb_couches-1].neurone[i].activation - sortie_voulue[i]) * (reseau_neuronal[nb_couches-1].neurone[i].activation) * (1- reseau_neuronal[nb_couches-1].neurone[i].activation); reseau_neuronal->couche[reseau_neuronal->nb_couche-1].neurone[i].dz = (reseau_neuronal->couche[reseau_neuronal->nb_couche-1].neurone[i].activation - sortie_voulue[i]) * (reseau_neuronal->couche[reseau_neuronal->nb_couche-1].neurone[i].activation) * (1- reseau_neuronal->couche[reseau_neuronal->nb_couche-1].neurone[i].activation);
for(int k=0; k<neurones_par_couche[nb_couches-2]; k++) { // Pour chaque neurone de l'avant dernière couche for(int k=0; k<neurones_par_couche[reseau_neuronal->nb_couche-2]; k++) { // Pour chaque neurone de l'avant dernière couche
reseau_neuronal[nb_couches-2].neurone[k].dw[i] = (reseau_neuronal[nb_couches-1].neurone[i].dz * reseau_neuronal[nb_couches-2].neurone[k].activation); reseau_neuronal->couche[reseau_neuronal->nb_couche-2].neurone[k].dw[i] = (reseau_neuronal->couche[reseau_neuronal->nb_couche-1].neurone[i].dz * reseau_neuronal->couche[reseau_neuronal->nb_couche-2].neurone[k].activation);
reseau_neuronal[nb_couches-2].neurone[k].dactivation = reseau_neuronal[nb_couches-2].neurone[k].poids_sortants[i] * reseau_neuronal[nb_couches-1].neurone[i].dz; reseau_neuronal->couche[reseau_neuronal->nb_couche-2].neurone[k].dactivation = reseau_neuronal->couche[reseau_neuronal->nb_couche-2].neurone[k].poids_sortants[i] * reseau_neuronal->couche[reseau_neuronal->nb_couche-1].neurone[i].dz;
} }
// ??? // ???
reseau_neuronal[nb_couches-1].neurone[i].dbiais = reseau_neuronal[nb_couches-1].neurone[i].dz; reseau_neuronal->couche[reseau_neuronal->nb_couche-1].neurone[i].dbiais = reseau_neuronal->couche[reseau_neuronal->nb_couche-1].neurone[i].dz;
} }
for(int i=nb_couches-2; i>0; i--) { // On remonte les couche de l'avant dernière jusqu'à la première for(int i=reseau_neuronal->nb_couche-2; i>0; i--) { // On remonte les couche de l'avant dernière jusqu'à la première
for(int j=0; j<neurones_par_couche[i]; j++) { for(int j=0; j<neurones_par_couche[i]; j++) {
if(reseau_neuronal[i].neurone[j].z >= 0) // ??? ... if(reseau_neuronal->couche[i].neurone[j].z >= 0) // ??? ...
reseau_neuronal[i].neurone[j].dz = reseau_neuronal[i].neurone[j].dactivation; reseau_neuronal->couche[i].neurone[j].dz = reseau_neuronal->couche[i].neurone[j].dactivation;
else // ??? ... else // ??? ...
reseau_neuronal[i].neurone[j].dz = 0; reseau_neuronal->couche[i].neurone[j].dz = 0;
for(int k=0; k<neurones_par_couche[i-1]; k++) { for(int k=0; k<neurones_par_couche[i-1]; k++) {
reseau_neuronal[i-1].neurone[k].dw[j] = reseau_neuronal[i].neurone[j].dz * reseau_neuronal[i-1].neurone[k].activation; reseau_neuronal->couche[i-1].neurone[k].dw[j] = reseau_neuronal->couche[i].neurone[j].dz * reseau_neuronal->couche[i-1].neurone[k].activation;
if(i>1) // ??? ... if(i>1) // ??? ...
reseau_neuronal[i-1].neurone[k].dactivation = reseau_neuronal[i-1].neurone[k].poids_sortants[j] * reseau_neuronal[i].neurone[j].dz; reseau_neuronal->couche[i-1].neurone[k].dactivation = reseau_neuronal->couche[i-1].neurone[k].poids_sortants[j] * reseau_neuronal->couche[i].neurone[j].dz;
} }
reseau_neuronal[i].neurone[j].dbiais = reseau_neuronal[i].neurone[j].dz; // ??? ... reseau_neuronal->couche[i].neurone[j].dbiais = reseau_neuronal->couche[i].neurone[j].dz; // ??? ...
} }
} }
@ -142,15 +142,15 @@ void backward_propagation(int nb_couches, int* neurones_par_couche, int* sortie_
void modification_du_reseau_neuronal(int nb_couches, int* neurones_par_couche) { void modification_du_reseau_neuronal(int* neurones_par_couche) {
/* Modifie les poids et le biais des neurones du réseau neuronal à partir /* Modifie les poids et le biais des neurones du réseau neuronal à partir
du nombre de couches et de la liste du nombre de neurone par couche */ du nombre de couches et de la liste du nombre de neurone par couche */
for (int i=0; i<nb_couches-1; i++) { // on exclut la dernière couche for (int i=0; i<reseau_neuronal->nb_couche-1; i++) { // on exclut la dernière couche
for (int j=0; i<neurones_par_couche[i]; j++) { for (int j=0; i<neurones_par_couche[i]; j++) {
reseau_neuronal[i].neurone[j].biais = reseau_neuronal[i].neurone[j].biais - (TAUX_APPRENTISSAGE * reseau_neuronal[i].neurone[j].dbiais); // On modifie le biais du neurone à partir des données de la propagation en arrière reseau_neuronal->couche[i].neurone[j].biais = reseau_neuronal->couche[i].neurone[j].biais - (TAUX_APPRENTISSAGE * reseau_neuronal->couche[i].neurone[j].dbiais); // On modifie le biais du neurone à partir des données de la propagation en arrière
for (int k=0; k<neurones_par_couche[i+1]; k++) { for (int k=0; k<neurones_par_couche[i+1]; k++) {
reseau_neuronal[i].neurone[j].poids_sortants[k] = reseau_neuronal[i].neurone[j].poids_sortants[k] - (TAUX_APPRENTISSAGE * reseau_neuronal[i].neurone[j].dw[k]); // On modifie le poids du neurone à partir des données de la propagation en arrière reseau_neuronal->couche[i].neurone[j].poids_sortants[k] = reseau_neuronal->couche[i].neurone[j].poids_sortants[k] - (TAUX_APPRENTISSAGE * reseau_neuronal->couche[i].neurone[j].dw[k]); // On modifie le poids du neurone à partir des données de la propagation en arrière
} }
} }
} }
@ -159,25 +159,25 @@ void modification_du_reseau_neuronal(int nb_couches, int* neurones_par_couche) {
void initialisation_du_reseau_neuronal(int nb_couches, int* neurones_par_couche) { void initialisation_du_reseau_neuronal(int* neurones_par_couche) {
/* Initialise les variables du réseau neuronal (activation, biais, poids, ...) /* Initialise les variables du réseau neuronal (activation, biais, poids, ...)
en suivant de la méthode de Xavier ...... à partir du nombre de couches et de la liste du nombre de neurone par couche */ en suivant de la méthode de Xavier ...... à partir du nombre de couches et de la liste du nombre de neurone par couche */
srand(time(0)); srand(time(0));
for (int i=0; i<nb_couches-1; i++) { // on exclut la dernière couche for (int i=0; i<reseau_neuronal->nb_couche-1; i++) { // on exclut la dernière couche
for (int j=0; j<neurones_par_couche[i]-1; j++) { for (int j=0; j<neurones_par_couche[i]-1; j++) {
// Initialisation des bornes supérieure et inférieure // Initialisation des bornes supérieure et inférieure
double borne_superieure = 1/sqrt(neurones_par_couche[i]); double borne_superieure = 1/sqrt(neurones_par_couche[i]);
double borne_inferieure = - borne_superieure; double borne_inferieure = - borne_superieure;
for (int k=0; k<neurones_par_couche[i+1]-1; k++) { // Pour chaque neurone de la couche suivante auquel le neurone est relié for (int k=0; k<neurones_par_couche[i+1]-1; k++) { // Pour chaque neurone de la couche suivante auquel le neurone est relié
reseau_neuronal[i].neurone[j].poids_sortants[k] = borne_inferieure + ((double)rand())/((double)RAND_MAX)*(borne_superieure - borne_inferieure); // Initialisation des poids sortants aléatoirement reseau_neuronal->couche[i].neurone[j].poids_sortants[k] = borne_inferieure + ((double)rand())/((double)RAND_MAX)*(borne_superieure - borne_inferieure); // Initialisation des poids sortants aléatoirement
reseau_neuronal[i].neurone[j].dw[k] = 0.0; // ... ??? reseau_neuronal->couche[i].neurone[j].dw[k] = 0.0; // ... ???
} }
if(i>0) // Pour tous les neurones n'étant pas dans la première couche if(i>0) // Pour tous les neurones n'étant pas dans la première couche
reseau_neuronal[i].neurone[j].biais = borne_inferieure + ((double)rand())/((double)RAND_MAX)*(borne_superieure - borne_inferieure); // On initialise le biais aléatoirement reseau_neuronal->couche[i].neurone[j].biais = borne_inferieure + ((double)rand())/((double)RAND_MAX)*(borne_superieure - borne_inferieure); // On initialise le biais aléatoirement
} }
} }
double borne_superieure = 1/sqrt(neurones_par_couche[nb_couches-1]); double borne_superieure = 1/sqrt(neurones_par_couche[reseau_neuronal->nb_couche-1]);
double borne_inferieure = - borne_superieure; double borne_inferieure = - borne_superieure;
for (int j=0; j<neurones_par_couche[nb_couches-1]; j++) // Pour chaque neurone de la dernière couche for (int j=0; j<neurones_par_couche[reseau_neuronal->nb_couche-1]; j++) // Pour chaque neurone de la dernière couche
reseau_neuronal[nb_couches-1].neurone[j].biais = borne_inferieure + ((double)rand())/((double)RAND_MAX)*(borne_superieure - borne_inferieure); // On initialise le biais aléatoirement reseau_neuronal->couche[reseau_neuronal->nb_couche-1].neurone[j].biais = borne_inferieure + ((double)rand())/((double)RAND_MAX)*(borne_superieure - borne_inferieure); // On initialise le biais aléatoirement
} }

View File

@ -15,3 +15,8 @@ typedef struct Couche{
int nb_neurone; // Nombre de neurones dans la couche (longueur de la liste ci-dessous) int nb_neurone; // Nombre de neurones dans la couche (longueur de la liste ci-dessous)
Neurone* neurone; // Liste des neurones dans la couche Neurone* neurone; // Liste des neurones dans la couche
} Couche; } Couche;
typedef struct Reseau{
int nb_couche;
Couche* couche;
} Reseau;