/// <summary> /// Effectue une prédiction sur un modèle /// </summary> /// <param name="dataVector"></param> /// <returns>true si le vecteur d'entrée correspond au modèle pour lequel le réseau a été entraîné</returns> public override bool Predire(double[] dataVector) { Neurone neurone = Couches[0].Neurones[0]; double sortie = neurone.CalculerSortie(dataVector); return(sortie > Couches[0].Seuil); }
/// <summary> /// Cacule la matrice des erreurs effectuées par le réseau sur le jeu de tests fournis /// </summary> /// <param name="tests">Jeu de tests</param> /// <param name="cibles">Cible pour chaque jeu de test</param> /// <returns> /// Matrice des erreurs contenant l'erreur commise par chaque neurone de la couche de sortie /// </returns> private double[] CalculerErreur(double[][] tests, double[] cibles) { Couche coucheSortie = Couches[Couches.Length - 1]; double[] erreurs = new double[coucheSortie.Neurones.Length]; for (int n = 0; n < coucheSortie.Neurones.Length; n++) { Neurone neurone = coucheSortie.Neurones[n]; double somme = 0.0; for (int i = 0; i < tests.Length; i++) { double sortie = neurone.CalculerSortie(tests[i]); double ecart = cibles[i] - sortie; // calcule l'erreur faite par le réseau lors de l'estimation de la cible // sur le neurone en cours de la dernière couche somme += ecart * ecart; } erreurs[n] = 0.5 * somme; } return(erreurs); }
/// <summary> /// Entraine le réseau /// </summary> /// <param name="maxIteration">Nombre d'itérations max</param> /// <param name="pas">Pas d'apprentissage</param> /// <param name="lettreCible">Lettre pour laquelle on entraîne le réseau</param> /// <param name="jeuEssai">Jeu d'essai pour entraîner le réseau</param> /// <param name="biais">Biais initial</param> /// <returns>L'erreur du réseau à la fin de son entraînement</returns> public double[] Entrainer(Dictionary <string, double[]> jeuEssai, string lettreCible, int maxIteration, double pas, double biais) { // on entraîne le réseau Neurone neurone = Couches[0].Neurones[0]; // un seul neurone dans le Perceptron double erreurCible = 0; double[] erreurCourante = new double[] { double.MaxValue }; int iteration = 0; // valeurs initiales neurone.Poids = new double[neurone.NbEntrees]; neurone.Biais = biais; while (iteration < maxIteration && erreurCourante[0] > erreurCible) { // pour chaque élément de test foreach (string lettre in jeuEssai.Keys) { // récupère le jeu d'entraînement courant double[] entraineur = jeuEssai[lettre]; // détermine si c'est la valeur cible (1) ou pas (-1) int valeurCible = (lettre == lettreCible) ? 1 : 0; // la fonction de transfert doit donc produire des -1 ou des 1 double sortie = neurone.CalculerSortie(entraineur); // de combien la sortie s'écarte de la cible double ecart = valeurCible - sortie; if (ecart != 0) { // réévalue le poids de chaque entrée (règle de RosenBlatt) for (int p = 0; p < neurone.NbEntrees; p++) { neurone.Poids[p] = neurone.Poids[p] + (pas * ecart * entraineur[p]); } // réévalue le biais // le biais est considéré comme une entrée supplémentaire avec un coefficient toujours égal à 1 neurone.Biais = neurone.Biais + (pas * ecart); } } ++iteration; Debug.WriteLine("Itération: " + iteration.ToString()); // on a un biais et un jeu de poids candidat // calcule l'erreur faite par le réseau dans l'estimation de notre jeu d'essai avec notre candidat double[][] tests = jeuEssai.Select(jeu => jeu.Value).ToArray(); double[] cibles = jeuEssai.Select(jeu => (jeu.Key == lettreCible) ? 1.0 : 0.0).ToArray(); double[][] c = jeuEssai.Select(jeu => cibles).ToArray(); erreurCourante = CalculerErreur(tests, cibles); } return(erreurCourante); }
/// <summary> /// Evaluer une entrée fournie par le réseau /// </summary> /// <param name="jeuEssai"></param> public void Calculer(double[] jeuEssai) { // on en fait une copie locale double[] entraineur = new double[jeuEssai.Length]; Array.Copy(jeuEssai, entraineur, jeuEssai.Length); // première dimension: une valeur par neurone de la couche // deuxième dimension: le vecteur des entrées appliquée au neurone double[][] testeurs = new double[Couches[0].Neurones.Length][]; for (int i = 0; i < Couches[0].Neurones.Length; i++) { testeurs[i] = new double[] { entraineur[i] }; } foreach (Couche couche in Couches) { if (testeurs == null) { // on réamorce la boucle de calcul testeurs = new double[couche.Neurones.Length][]; for (int i = 0; i < couche.Neurones.Length; i++) { // les neurones de chaque couche interne reçoivent le même jeu d'entrée contrairement aux neurones de la couche d'entrée testeurs[i] = entraineur; } } for (int n = 0; n < couche.Neurones.Length; n++) { Neurone neurone = couche.Neurones[n]; neurone.CalculerSortie(testeurs[n]); } // on récupère les sorties des neurones de la couche courante entraineur = new double[couche.Neurones.Length]; for (int i = 0; i < couche.Neurones.Length; i++) { Neurone neurone = couche.Neurones[i]; entraineur[i] = neurone.Sortie; } testeurs = null; } }