/// <summary> /// Afficher le contenu d'un réseau /// </summary> public static void AfficherReseau(Reseau reseau) { Console.WriteLine(); // couche d'entrée traitée à part Couche couche = reseau.Couches[0]; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Couche entrée ({0} neurones)", couche.Neurones.Length); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Sortie:"); Console.ForegroundColor = ConsoleColor.Yellow; foreach (Neurone neurone in couche.Neurones) { Console.WriteLine(neurone.Sortie.ToString("+0.0000;-0.0000")); Console.WriteLine(); } Console.ResetColor(); for (int i = 1; i < reseau.Couches.Length; i++) { couche = reseau.Couches[i]; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Couche {0} ({1} neurones)", i, couche.Neurones.Length); Console.ResetColor(); Console.Write("Poids, "); Console.ForegroundColor = ConsoleColor.Blue; Console.Write("biais, "); Console.ForegroundColor = ConsoleColor.Green; Console.Write("somme, "); Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("sortie, "); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("Gradiant:"); Console.ResetColor(); foreach (Neurone neurone in couche.Neurones) { for (int n = 0; n < neurone.Poids.Length; n++) { Console.Write("{0} ", neurone.Poids[n].ToString("+0.0000;-0.0000")); } Console.ForegroundColor = ConsoleColor.Blue; Console.Write("{0} ", neurone.Biais.ToString("+0.0000;-0.0000")); Console.ForegroundColor = ConsoleColor.Green; Console.Write("{0} ", neurone.Somme.ToString("+0.0000;-0.0000")); Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("{0} ", neurone.Sortie.ToString("+0.0000;-0.0000")); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine(neurone.Erreur.ToString("+0.0000;-0.0000")); Console.ResetColor(); Console.WriteLine(); } } }
/// <summary> /// Règle une valeur aléatoire comprise entre -1 et +1 pour les poids des couches du réseau autres que la couche d'entrée /// </summary> /// <param name="reseau"></param> public static void PoidsAleatoires(Reseau reseau, bool bias) { Random rnd = new Random(); // on laisse les valeurs par défaut (1) des poids de la couche d'entrée // d'ou le démarrage à 1 for (int c = 1; c < reseau.Couches.Length; c++) { Couche couche = reseau.Couches[c]; foreach (Neurone neurone in couche.Neurones) { for (int i = 0; i < neurone.Poids.Length; i++) { neurone.Poids[i] = 2 * rnd.NextDouble() - 1; if (bias) { neurone.Biais = 2 * rnd.NextDouble() - 1; } } } } }
/// <summary> /// Initialise la couche /// </summary> /// <param name="transfert">Fonction de transfert</param> /// <param name="transfertDerivee">Nom utilisé</param> /// <param name="topologie">Topologie du réseau</param> /// <param name="seuil">Seuil de la fonction de transfert</param> /// <param name="nbEntrees">Nb d'entrées des neurones de la couche d'entrée</param> protected override void Initialiser(Func<double, double> transfert, double seuil, Func<double, double> transfertDerivee, int nbEntrees, int[] topologie) { Couches = new Couche[1]; Couches[0] = new Couche(topologie[0], nbEntrees, transfert, seuil); }
/// <summary> /// Propagation des erreurs entre couche1 et couche2 sur les poids et les biais /// </summary> /// <param name="pas">Pas d'apprentissage</param> /// <param name="couche1"></param> /// <param name="couche2"></param> /// <remarks> /// couche1 => couche2 /// </remarks> private void Propager(Couche couche1, Couche couche2, double pas) { for (int c2 = 0; c2 < couche2.Neurones.Length; c2++) { Neurone neurone2 = couche2.Neurones[c2]; for (int c1 = 0; c1 < couche1.Neurones.Length; c1++) { neurone2.Poids[c1] += pas * neurone2.Erreur * couche1.Neurones[c1].Sortie; } neurone2.Biais += pas * neurone2.Erreur; } }
/// <summary> /// Calcule de l'erreur (gradiant local) des neurones des couches cachées /// </summary> /// <param name="couche1">Couche cachée N</param> /// <param name="couche2">Couche N + 1</param> /// <returns></returns> private void CalculerDeltaH(Couche couche1, Couche couche2) { for (int k = 0; k < couche1.Neurones.Length; k++) { Neurone neuroneH = couche1.Neurones[k]; double somme = 0.0; for (int i = 0; i < couche2.Neurones.Length; i++) { Neurone neurone2 = couche2.Neurones[i]; somme += neurone2.Poids[k] * neurone2.Erreur; } neuroneH.Erreur = neuroneH.TransfertDerivee(neuroneH.Somme + neuroneH.Biais) * somme; //Debug.WriteLine("Gradiant H: " + neuroneH.Erreur.ToString()); } }
/// <summary> /// Initialiser le réseau /// </summary> /// <param name="transfert">Fonction de transfert</param> /// <param name="nbEntrees">Nb d'entrées des neurones de la couche d'entrée</param> /// <param name="transfertDerivee">Null ou dérivée de la fonction de transfert</param> /// <param name="seuil">Seuil de la fonction de transfert de la couche</param> /// <param name="topologie">Topologie du réseau</param> protected override void Initialiser(Func<double, double> transfert, double seuil, Func<double, double> transfertDerivee, int nbEntrees, int[] topologie) { Couches = new Couche[topologie.Length]; // couche d'entrée Couches[0] = new Couche(topologie[0], nbEntrees, FonctionsTransfert.Identite, 0); foreach (Neurone neurone in Couches[0].Neurones) { for (int i = 0; i < neurone.Poids.Length; i++) { neurone.Poids[i] = 1; } } // couches cachées for (int c = 1; c < Couches.Length - 1; c++) { //Couches[c] = new Couche(topologie[c], Couches[c - 1].Neurones.Length, FonctionsTransfert.HyperTan, 0, FonctionsTransfert.HyperTanDerivee); Couches[c] = new Couche(topologie[c], Couches[c - 1].Neurones.Length, FonctionsTransfert.Sigmoide, 0.5, FonctionsTransfert.SigmoideDerivee); Couches[c].Position = c; } // couche de sortie Couches[Couches.Length - 1] = new Couche(topologie[Couches.Length - 1], Couches[Couches.Length - 2].Neurones.Length, FonctionsTransfert.Sigmoide, 0.5, FonctionsTransfert.SigmoideDerivee); Couches[Couches.Length - 1].Position = Couches.Length - 1; }