2022-03-24 13:42:03 +01:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <math.h>
# include <time.h>
2022-03-25 19:19:27 +01:00
# include "struct/neuron.c"
2022-03-24 13:42:03 +01:00
2022-03-25 19:19:27 +01:00
# 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)
2022-03-24 13:42:03 +01:00
2022-03-26 18:50:09 +01:00
Reseau * reseau_neuronal ;
2022-03-24 13:42:03 +01:00
2022-03-26 18:50:09 +01:00
void creation_du_reseau_neuronal ( int * neurones_par_couche ) ;
void suppression_du_reseau_neuronal ( int * neurones_par_couche ) ;
void forward_propagation ( int * neurones_par_couche ) ;
int * creation_de_la_sortie_voulue ( int * neurones_par_couche , int pos_nombre_voulu ) ;
void backward_propagation ( int * neurones_par_couche , int * sortie_voulue ) ;
void modification_du_reseau_neuronal ( int * neurones_par_couche ) ;
void initialisation_du_reseau_neuronal ( int * neurones_par_couche ) ;
2022-03-24 13:42:03 +01:00
2022-03-26 18:50:09 +01:00
void creation_du_reseau_neuronal ( int * neurones_par_couche ) {
2022-03-24 13:42:03 +01:00
/* Créé les différentes variables dans la variable du réseau neuronal à
2022-03-25 14:26:46 +01:00
partir du nombre de couches et de la liste du nombre de neurones par couche */
2022-03-24 13:42:03 +01:00
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche = ( Couche * ) malloc ( sizeof ( Couche ) * reseau_neuronal - > nb_couche ) ; // Création des différentes couches
for ( int i = 0 ; i < reseau_neuronal - > nb_couche ; i + + ) {
2022-03-24 13:42:03 +01:00
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ i ] . nb_neurone = neurones_par_couche [ i ] ; // nombre de neurones pour la couche
reseau_neuronal - > couche [ i ] . neurone = ( Neurone * ) malloc ( sizeof ( Neurone ) * neurones_par_couche [ i ] ) ; // Création des différents neurones dans la couche
2022-03-24 13:42:03 +01:00
2022-03-26 18:50:09 +01:00
if ( i ! = reseau_neuronal - > nb_couche - 1 ) { // On exclut la dernière couche dont les neurones ne contiennent pas de poids sortants
2022-03-25 14:26:46 +01:00
for ( int j = 0 ; j < neurones_par_couche [ i ] ; j + + ) {
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ i ] . neurone [ j ] . poids_sortants = ( float * ) malloc ( sizeof ( float ) * neurones_par_couche [ i + 1 ] ) ; // Création des poids sortants du neurone
2022-03-24 13:42:03 +01:00
}
}
}
}
2022-03-26 18:50:09 +01:00
void suppression_du_reseau_neuronal ( int * neurones_par_couche ) {
2022-03-24 13:42:03 +01:00
/* 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
nombre de neurone par couche */
2022-03-26 18:50:09 +01:00
for ( int i = 0 ; i < reseau_neuronal - > nb_couche ; i + + ) {
if ( i ! = reseau_neuronal - > nb_couche - 1 ) { // On exclut la dernière couche dont les neurones ne contiennent pas de poids sortants
2022-03-25 14:26:46 +01:00
for ( int j = 0 ; j < neurones_par_couche [ i ] ; j + + ) {
2022-03-26 18:50:09 +01:00
free ( reseau_neuronal - > couche [ i ] . neurone [ j ] . poids_sortants ) ; // On libère la variables des poids sortants
2022-03-24 13:42:03 +01:00
}
}
2022-03-26 18:50:09 +01:00
free ( reseau_neuronal - > couche [ i ] . neurone ) ; // On libère enfin la liste des neurones de la couche
2022-03-24 13:42:03 +01:00
}
free ( reseau_neuronal ) ; // Pour finir, on libère le réseau neronal contenant la liste des couches
}
2022-03-26 18:50:09 +01:00
void forward_propagation ( int * neurones_par_couche ) {
2022-03-24 13:42:03 +01:00
/* Effectue une propagation en avant du réseau neuronal à partir du nombre
2022-03-25 14:26:46 +01:00
de couches et de la liste du nombre de neurones par couche */
2022-03-24 13:42:03 +01:00
2022-03-26 18:50:09 +01:00
for ( int i = 1 ; i < reseau_neuronal - > nb_couche ; i + + ) { // La première couche contient déjà des valeurs
2022-03-24 13:42:03 +01:00
for ( int j = 0 ; j < neurones_par_couche [ i ] ; j + + ) { // Pour chaque neurone de la couche
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ i ] . neurone [ j ] . z = reseau_neuronal - > couche [ i ] . neurone [ j ] . biais ; // On réinitialise l'utilisation actuelle du neurone à son biais
2022-03-24 13:42:03 +01:00
for ( int k = 0 ; k < neurones_par_couche [ i - 1 ] ; k + + ) {
2022-03-26 18:50:09 +01:00
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 ] ; // ???
2022-03-24 13:42:03 +01:00
}
2022-03-26 18:50:09 +01:00
if ( i < reseau_neuronal - > nb_couche - 1 ) { // Pour toutes les couches sauf la dernière on utilise la fonction relu
if ( reseau_neuronal - > couche [ i ] . neurone [ j ] . z < 0 )
reseau_neuronal - > couche [ i ] . neurone [ j ] . activation = 0 ;
2022-03-24 13:42:03 +01:00
else
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ i ] . neurone [ j ] . activation = reseau_neuronal - > couche [ i ] . neurone [ j ] . z ;
2022-03-24 13:42:03 +01:00
}
else { // Pour la dernière couche on utilise la fonction sigmoid permettant d'obtenir un résultat entre 0 et 1 étant une probabilité
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ i ] . neurone [ j ] . activation = 1 / ( 1 + exp ( reseau_neuronal - > couche [ i ] . neurone [ j ] . activation ) ) ;
2022-03-24 13:42:03 +01:00
}
}
}
}
2022-03-26 18:50:09 +01:00
int * creation_de_la_sortie_voulue ( int * neurones_par_couche , int pos_nombre_voulu ) {
2022-03-25 14:26:46 +01:00
/* Renvoie la liste des sorties voulues à partir du nombre
de couches , de la liste du nombre de neurones par couche et de la
2022-03-24 13:42:03 +01:00
position du résultat voulue , */
int * sortie_voulue = ( int * ) malloc ( sizeof ( int ) ) ;
2022-03-26 18:50:09 +01:00
for ( int i = 0 ; i < neurones_par_couche [ reseau_neuronal - > nb_couche - 1 ] ; i + + ) // On initialise toutes les sorties à 0 par défault
2022-03-24 13:42:03 +01:00
sortie_voulue [ i ] = 0 ;
sortie_voulue [ pos_nombre_voulu ] = 1 ; // Seule la sortie voulue vaut 1
return sortie_voulue ;
}
2022-03-26 18:50:09 +01:00
void backward_propagation ( int * neurones_par_couche , int * sortie_voulue ) {
2022-03-24 13:42:03 +01:00
/* Effectue une propagation en arrière du réseau neuronal à partir du
2022-03-25 14:26:46 +01:00
nombre de couches , de la liste du nombre de neurone par couche et de
2022-03-24 13:42:03 +01:00
la liste des sorties voulues */
// On commence par parcourir tous les neurones de la couche finale
2022-03-26 18:50:09 +01:00
for ( int i = 0 ; i < neurones_par_couche [ reseau_neuronal - > nb_couche - 1 ] ; i + + ) {
2022-03-24 13:42:03 +01:00
// On applique la formule de propagation en arrière
2022-03-26 18:50:09 +01:00
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 ) ;
2022-03-24 13:42:03 +01:00
2022-03-26 18:50:09 +01:00
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 - > 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 - > 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 ;
2022-03-24 13:42:03 +01:00
}
// ???
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ reseau_neuronal - > nb_couche - 1 ] . neurone [ i ] . dbiais = reseau_neuronal - > couche [ reseau_neuronal - > nb_couche - 1 ] . neurone [ i ] . dz ;
2022-03-24 13:42:03 +01:00
}
2022-03-26 18:50:09 +01:00
for ( int i = reseau_neuronal - > nb_couche - 2 ; i > 0 ; i - - ) { // On remonte les couche de l'avant dernière jusqu'à la première
2022-03-25 14:26:46 +01:00
for ( int j = 0 ; j < neurones_par_couche [ i ] ; j + + ) {
2022-03-26 18:50:09 +01:00
if ( reseau_neuronal - > couche [ i ] . neurone [ j ] . z > = 0 ) // ??? ...
reseau_neuronal - > couche [ i ] . neurone [ j ] . dz = reseau_neuronal - > couche [ i ] . neurone [ j ] . dactivation ;
2022-03-24 13:42:03 +01:00
else // ??? ...
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ i ] . neurone [ j ] . dz = 0 ;
2022-03-24 13:42:03 +01:00
2022-03-25 14:26:46 +01:00
for ( int k = 0 ; k < neurones_par_couche [ i - 1 ] ; k + + ) {
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ i - 1 ] . neurone [ k ] . dw [ j ] = reseau_neuronal - > couche [ i ] . neurone [ j ] . dz * reseau_neuronal - > couche [ i - 1 ] . neurone [ k ] . activation ;
2022-03-24 13:42:03 +01:00
if ( i > 1 ) // ??? ...
2022-03-26 18:50:09 +01:00
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 ;
2022-03-24 13:42:03 +01:00
}
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ i ] . neurone [ j ] . dbiais = reseau_neuronal - > couche [ i ] . neurone [ j ] . dz ; // ??? ...
2022-03-24 13:42:03 +01:00
}
}
}
2022-03-26 18:50:09 +01:00
void modification_du_reseau_neuronal ( int * neurones_par_couche ) {
2022-03-24 13:42:03 +01:00
/* 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 */
2022-03-26 18:50:09 +01:00
for ( int i = 0 ; i < reseau_neuronal - > nb_couche - 1 ; i + + ) { // on exclut la dernière couche
2022-03-25 14:26:46 +01:00
for ( int j = 0 ; i < neurones_par_couche [ i ] ; j + + ) {
2022-03-26 18:50:09 +01:00
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
2022-03-25 14:26:46 +01:00
for ( int k = 0 ; k < neurones_par_couche [ i + 1 ] ; k + + ) {
2022-03-26 18:50:09 +01:00
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
2022-03-24 13:42:03 +01:00
}
}
}
}
2022-03-26 18:50:09 +01:00
void initialisation_du_reseau_neuronal ( int * neurones_par_couche ) {
2022-03-24 13:42:03 +01:00
/* 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 */
srand ( time ( 0 ) ) ;
2022-03-26 18:50:09 +01:00
for ( int i = 0 ; i < reseau_neuronal - > nb_couche - 1 ; i + + ) { // on exclut la dernière couche
2022-03-25 14:26:46 +01:00
for ( int j = 0 ; j < neurones_par_couche [ i ] - 1 ; j + + ) {
// Initialisation des bornes supérieure et inférieure
2022-03-24 13:42:03 +01:00
double borne_superieure = 1 / sqrt ( neurones_par_couche [ i ] ) ;
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é
2022-03-26 18:50:09 +01:00
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 - > couche [ i ] . neurone [ j ] . dw [ k ] = 0.0 ; // ... ???
2022-03-24 13:42:03 +01:00
}
if ( i > 0 ) // Pour tous les neurones n'étant pas dans la première couche
2022-03-26 18:50:09 +01:00
reseau_neuronal - > couche [ i ] . neurone [ j ] . biais = borne_inferieure + ( ( double ) rand ( ) ) / ( ( double ) RAND_MAX ) * ( borne_superieure - borne_inferieure ) ; // On initialise le biais aléatoirement
2022-03-24 13:42:03 +01:00
}
}
2022-03-26 18:50:09 +01:00
double borne_superieure = 1 / sqrt ( neurones_par_couche [ reseau_neuronal - > nb_couche - 1 ] ) ;
2022-03-24 13:42:03 +01:00
double borne_inferieure = - borne_superieure ;
2022-03-26 18:50:09 +01:00
for ( int j = 0 ; j < neurones_par_couche [ reseau_neuronal - > nb_couche - 1 ] ; j + + ) // Pour chaque neurone de la dernière couche
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
2022-03-25 14:26:46 +01:00
}