## Fichier : incubateur.py # Auteur : Jovian Hersemeule # Classe python. Se charge d'entrainer un réseau de # neurones par algorithme génétique. from ReseauNeurones.cerveau import Cerveau from ReseauNeurones.generation import Generateur from Outils.IA_alphabeta import IA_minmax_alpha_beta from random import randint from os import system class Incubateur : def __init__(self): # Jovian 21 mars 2017 """ Construit l'incubateur. """ self.population = None # Cerveau list self.iter = 0 # int self.nom_structure = None # int self.nom_session = None # string self.tournoi = None # fonction de tournoi self.nom_tournoi = "Pas de tournoi" # nom du tournoi self.save_rate = None # nombre de générations entre chaque sauvegarde #(None pas de sauvegarde avant la fin) self.nb_elite_kept = 1 self.nb_elite_cross = 1 self.nb_mixte_cross = 1 self.nb_elite_mutate = 1 self.nb_weak_mutate = 1 self.nb_rd_generated = 1 self.generator = Generateur() def start_session(self, nom_structure, nom_session = "BasicTraining", nb_gen_max = None, nb_pop = 20, debug = False ): # Jovian 21 mars 2017 """ Permet de démarrer une session d'entraînement. Attention cela est une fonction blocante. Arg nom_structure : le nom de la structure du réseau. Arg nom_session : permet de choisir le nom du dossier pour cette session. Arg nb_gen_max : le nombre maximal de générations avant l'arrêt. Si None pas de limite. Arg nb_pop : nombre d'individus par génération. Arg debug : affiche des informations si vaut True. """ # Initialisation des attributs self.nom_structure = nom_structure self.nom_session = nom_session # Création des population self.population = [] self.iter = 1 for i in range(nb_pop): individual = Cerveau() individual.charger_structure( nom_structure, debug = debug ) individual.generer_poids( inf = -1.0, sup = 1.0, debug = debug ) individual.build_network( debug = debug ) self.population.append( individual ) # Sauvegarde des individus originaux self.save_population(debug = debug) # Ecriture du protocole self.write_protocole(debug = debug) # Entrainement self.train( nb_gen_max = nb_gen_max, debug = debug ) # Sauvegarde de la population self.save_population(debug = debug) def save_population(self, debug = False): # Jovian 30 mai 2017 """ Sauvegarde la totalité de la population. """ # Dossier chemin = "ReseauNeurones\\Base_Poids\\" + self.nom_session + "\\" chemin += "Generation" + str(self.iter) system("mkdir " + chemin) # Fichier chemin += "\\individu" chemin = chemin.replace("\\", "/") # Parcours for tp in enumerate(self.population) : k, individual = tp with open( chemin + str(k) + ".pds", "w" ) as flux : for v in individual.liste_poids : flux.write( str(v) + "\n" ) # Annonce if debug : print("|") print("Population sauvegardée.") def sort(self, debug = False): # Jovian 6 juin 2017 """ Classe la population par un système de tournoi. """ if debug : print("|\nClassement des individus.") # Création des intelligences à patir des cerveaux liste_IA = [ IA_minmax_alpha_beta(self.nom_session, brain.fct_eval, 1) for brain in self.population ] #liste_IA = [ IA_minmax_alpha_beta(self.nom_session, lambda x,y : 0, 1) for brain in self.population ] # Classement par tournoi tab_scores = self.tournoi( liste_IA ) if debug : print("Tableau des scores : ", tab_scores ) # Etablissement d'un classement à partir des scores : n = len(self.population) tab = [(tab_scores[i],i) for i in range(n)] tab.sort() tab_classement = [0] * n # Tableaux de rangs for i in range(n) : tab_classement[tab[i][1]] = n - 1 - i if debug : print("Rang des joueurs : ", tab_classement ) # Ordonnancement de la population en conséquence : nouveau = n*[None] for i in range(n) : nouveau[tab_classement[i]] = self.population[i] self.population = nouveau def generate(self, debug = False): # Jovian 2 juin 2017 """ Génère la génération suivante d'individus. """ # Annonce if debug : print("|\nGénération en cours de création : ", self.iter) # Liste des nouvaux chromosomes chrom_list = [] # Séparation faibles / forts mid = len(self.population) // 2 + 1 # Garder les meilleurs if debug and self.nb_elite_kept > 0 : print("On garde les ", self.nb_elite_kept, " meilleurs.") for k in range( self.nb_elite_kept ): chrom_list.append( self.population[k].liste_poids ) # Croiser les meilleurs if debug and self.nb_elite_cross > 0 : print("On croise les ", self.nb_elite_cross, " meilleurs.") for k in range( self.nb_elite_cross ): # Choisir deux individus à reproduire indA = randint(0, mid) indB = randint(0, mid) # Opérations génétiques chromA = self.population[indA].liste_poids chromB = self.population[indB].liste_poids chromCross = self.generator.cross_random( chromA, chromB ) # Ecriture du résultat chrom_list.append( chromCross ) # Croiser des individus aléatoirement if debug and self.nb_mixte_cross > 0 : print("On croise aléatoirement ", self.nb_mixte_cross, " individus.") for k in range( self.nb_mixte_cross ): # Choisir deux individus à reproduire indA = randint(0, len( self.population ) ) indB = randint(0, len( self.population ) ) # Opérations génétiques chromA = self.population[indA].liste_poids chromB = self.population[indB].liste_poids chromCross = self.generator.cross_random( chromA, chromB ) # Ecriture du résultat chrom_list.append( chromCross ) # Mutation des élites if debug and self.nb_elite_mutate > 0 : print("On mute les ", self.nb_elite_mutate, " meilleurs.") for k in range( self.nb_elite_mutate ): # Choisir indA = randint(0, mid) # Opérations génétique chromA = self.population[indA].liste_poids chromMuted = self.generator.mutate_total( chromA, nb = 1 ) # Ecriture du résultat chrom_list.append( chromMuted ) # Mutation des faibles if debug and self.nb_weak_mutate > 0 : print("On mute les ", self.nb_weak_mutate, " plus faibles.") for k in range( self.nb_weak_mutate ): # Choisir indA = randint(mid, len( self.population ) ) # Opérations génétique chromA = self.population[indA].liste_poids chromMuted = self.generator.mutate_total( chromA, nb = 1 ) # Ecriture du résultat chrom_list.append( chromMuted ) # Mise à jour des réseaux for k in range( self.nb_elite_kept, len(chrom_list) ) : self.population[k].donner_poids( chrom_list[k] ) self.population[k].build_network() # On complète la population en générant des membres aléatoirement if debug and len(self.population) - len(chrom_list) > 0 : print("On rajoute ", len(self.population) - len(chrom_list), " générés au hasard.") for k in range( len(chrom_list), len(self.population) ) : self.population[k].generer_poids() self.population[k].build_network() def train(self, nb_gen_max = None, debug = False): # Jovian 31 mai 2017 """ Entraîne le réseau. int nb_gen_max : Le nombre de générations avant l'arrêt (None pour boucle infinie) bool debug : Affichage d'informations de suivi """ last_save = self.iter if debug : print("Démarrage de l'entraînement à partir de la génération ", self.iter ) # Itération while self.iter < nb_gen_max : self.iter += 1 print("\n> Génération ", self.iter, " pour la session ", self.nom_session,".") # Classement self.sort(debug = debug) # Génération suivante self.generate(debug = debug) # Sauvegarde if self.save_rate != None and self.iter - last_save >= self.save_rate : last_save = self.iter self.save_population(debug = debug) # Fin de l'entraînement return None def write_protocole(self, debug = False): # Jovian 6 juin 2017 """ Sauvegarde les paramètres utilisés dans le dossier qui contient les résultats de l'entraînement. bool debug : Affichage d'informations de suivi """ # Chemin chemin = "ReseauNeurones/Base_Poids/" + self.nom_session chemin += "/Protocole.txt" # Ecriture with open( chemin, "w" ) as flux : flux.write( "Nom du tournoi : " + str(self.nom_tournoi) + "\n" ) flux.write( "Nombre de générations maximal : " + "inconnu" + "\n" ) flux.write( "Taille de population : " + str(len(self.population)) + "\n" ) flux.write( "\n\n" ) flux.write( "nb_elite_kept = " + str(self.nb_elite_kept) + "\n" ) flux.write( "nb_elite_cross = " + str(self.nb_elite_cross) + "\n" ) flux.write( "nb_elite_kept = " + str(self.nb_mixte_cross) + "\n" ) flux.write( "nb_elite_mutate = " + str(self.nb_elite_mutate) + "\n" ) flux.write( "nb_weak_mutate = " + str(self.nb_weak_mutate) + "\n" ) flux.write( "nb_rd_generated = " + str(self.nb_rd_generated) + "\n" ) # Annonce if debug : print("|") print("Protocole enregistré.")