incubateur.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. ## Fichier : incubateur.py
  2. # Auteur : Jovian Hersemeule
  3. # Classe python. Se charge d'entrainer un réseau de
  4. # neurones par algorithme génétique.
  5. from ReseauNeurones.cerveau import Cerveau
  6. from ReseauNeurones.generation import Generateur
  7. from Outils.IA_alphabeta import IA_minmax_alpha_beta
  8. from random import randint
  9. from os import system
  10. class Incubateur :
  11. def __init__(self): # Jovian 21 mars 2017
  12. """
  13. Construit l'incubateur.
  14. """
  15. self.population = None # Cerveau list
  16. self.iter = 0 # int
  17. self.nom_structure = None # int
  18. self.nom_session = None # string
  19. self.tournoi = None # fonction de tournoi
  20. self.nom_tournoi = "Pas de tournoi" # nom du tournoi
  21. self.save_rate = None # nombre de générations entre chaque sauvegarde
  22. #(None pas de sauvegarde avant la fin)
  23. self.nb_elite_kept = 1
  24. self.nb_elite_cross = 1
  25. self.nb_mixte_cross = 1
  26. self.nb_elite_mutate = 1
  27. self.nb_weak_mutate = 1
  28. self.nb_rd_generated = 1
  29. self.generator = Generateur()
  30. def start_session(self, nom_structure, nom_session = "BasicTraining", nb_gen_max = None, nb_pop = 20, debug = False ): # Jovian 21 mars 2017
  31. """
  32. Permet de démarrer une session d'entraînement.
  33. Attention cela est une fonction blocante.
  34. Arg nom_structure : le nom de la structure du réseau.
  35. Arg nom_session : permet de choisir le nom du dossier pour cette session.
  36. Arg nb_gen_max : le nombre maximal de générations avant l'arrêt. Si None pas de limite.
  37. Arg nb_pop : nombre d'individus par génération.
  38. Arg debug : affiche des informations si vaut True.
  39. """
  40. # Initialisation des attributs
  41. self.nom_structure = nom_structure
  42. self.nom_session = nom_session
  43. # Création des population
  44. self.population = []
  45. self.iter = 1
  46. for i in range(nb_pop):
  47. individual = Cerveau()
  48. individual.charger_structure( nom_structure, debug = debug )
  49. individual.generer_poids( inf = -1.0, sup = 1.0, debug = debug )
  50. individual.build_network( debug = debug )
  51. self.population.append( individual )
  52. # Sauvegarde des individus originaux
  53. self.save_population(debug = debug)
  54. # Ecriture du protocole
  55. self.write_protocole(debug = debug)
  56. # Entrainement
  57. self.train( nb_gen_max = nb_gen_max, debug = debug )
  58. # Sauvegarde de la population
  59. self.save_population(debug = debug)
  60. def save_population(self, debug = False): # Jovian 30 mai 2017
  61. """
  62. Sauvegarde la totalité de la population.
  63. """
  64. # Dossier
  65. chemin = "ReseauNeurones\\Base_Poids\\" + self.nom_session + "\\"
  66. chemin += "Generation" + str(self.iter)
  67. system("mkdir " + chemin)
  68. # Fichier
  69. chemin += "\\individu"
  70. chemin = chemin.replace("\\", "/")
  71. # Parcours
  72. for tp in enumerate(self.population) :
  73. k, individual = tp
  74. with open( chemin + str(k) + ".pds", "w" ) as flux :
  75. for v in individual.liste_poids :
  76. flux.write( str(v) + "\n" )
  77. # Annonce
  78. if debug :
  79. print("|")
  80. print("Population sauvegardée.")
  81. def sort(self, debug = False): # Jovian 6 juin 2017
  82. """
  83. Classe la population par un système de tournoi.
  84. """
  85. if debug :
  86. print("|\nClassement des individus.")
  87. # Création des intelligences à patir des cerveaux
  88. liste_IA = [ IA_minmax_alpha_beta(self.nom_session, brain.fct_eval, 1) for brain in self.population ]
  89. #liste_IA = [ IA_minmax_alpha_beta(self.nom_session, lambda x,y : 0, 1) for brain in self.population ]
  90. # Classement par tournoi
  91. tab_scores = self.tournoi( liste_IA )
  92. if debug :
  93. print("Tableau des scores : ", tab_scores )
  94. # Etablissement d'un classement à partir des scores :
  95. n = len(self.population)
  96. tab = [(tab_scores[i],i) for i in range(n)]
  97. tab.sort()
  98. tab_classement = [0] * n # Tableaux de rangs
  99. for i in range(n) :
  100. tab_classement[tab[i][1]] = n - 1 - i
  101. if debug :
  102. print("Rang des joueurs : ", tab_classement )
  103. # Ordonnancement de la population en conséquence :
  104. nouveau = n*[None]
  105. for i in range(n) :
  106. nouveau[tab_classement[i]] = self.population[i]
  107. self.population = nouveau
  108. def generate(self, debug = False): # Jovian 2 juin 2017
  109. """
  110. Génère la génération suivante d'individus.
  111. """
  112. # Annonce
  113. if debug :
  114. print("|\nGénération en cours de création : ", self.iter)
  115. # Liste des nouvaux chromosomes
  116. chrom_list = []
  117. # Séparation faibles / forts
  118. mid = len(self.population) // 2 + 1
  119. # Garder les meilleurs
  120. if debug and self.nb_elite_kept > 0 :
  121. print("On garde les ", self.nb_elite_kept, " meilleurs.")
  122. for k in range( self.nb_elite_kept ):
  123. chrom_list.append( self.population[k].liste_poids )
  124. # Croiser les meilleurs
  125. if debug and self.nb_elite_cross > 0 :
  126. print("On croise les ", self.nb_elite_cross, " meilleurs.")
  127. for k in range( self.nb_elite_cross ):
  128. # Choisir deux individus à reproduire
  129. indA = randint(0, mid)
  130. indB = randint(0, mid)
  131. # Opérations génétiques
  132. chromA = self.population[indA].liste_poids
  133. chromB = self.population[indB].liste_poids
  134. chromCross = self.generator.cross_random( chromA, chromB )
  135. # Ecriture du résultat
  136. chrom_list.append( chromCross )
  137. # Croiser des individus aléatoirement
  138. if debug and self.nb_mixte_cross > 0 :
  139. print("On croise aléatoirement ", self.nb_mixte_cross, " individus.")
  140. for k in range( self.nb_mixte_cross ):
  141. # Choisir deux individus à reproduire
  142. indA = randint(0, len( self.population ) )
  143. indB = randint(0, len( self.population ) )
  144. # Opérations génétiques
  145. chromA = self.population[indA].liste_poids
  146. chromB = self.population[indB].liste_poids
  147. chromCross = self.generator.cross_random( chromA, chromB )
  148. # Ecriture du résultat
  149. chrom_list.append( chromCross )
  150. # Mutation des élites
  151. if debug and self.nb_elite_mutate > 0 :
  152. print("On mute les ", self.nb_elite_mutate, " meilleurs.")
  153. for k in range( self.nb_elite_mutate ):
  154. # Choisir
  155. indA = randint(0, mid)
  156. # Opérations génétique
  157. chromA = self.population[indA].liste_poids
  158. chromMuted = self.generator.mutate_total( chromA, nb = 1 )
  159. # Ecriture du résultat
  160. chrom_list.append( chromMuted )
  161. # Mutation des faibles
  162. if debug and self.nb_weak_mutate > 0 :
  163. print("On mute les ", self.nb_weak_mutate, " plus faibles.")
  164. for k in range( self.nb_weak_mutate ):
  165. # Choisir
  166. indA = randint(mid, len( self.population ) )
  167. # Opérations génétique
  168. chromA = self.population[indA].liste_poids
  169. chromMuted = self.generator.mutate_total( chromA, nb = 1 )
  170. # Ecriture du résultat
  171. chrom_list.append( chromMuted )
  172. # Mise à jour des réseaux
  173. for k in range( self.nb_elite_kept, len(chrom_list) ) :
  174. self.population[k].donner_poids( chrom_list[k] )
  175. self.population[k].build_network()
  176. # On complète la population en générant des membres aléatoirement
  177. if debug and len(self.population) - len(chrom_list) > 0 :
  178. print("On rajoute ", len(self.population) - len(chrom_list), " générés au hasard.")
  179. for k in range( len(chrom_list), len(self.population) ) :
  180. self.population[k].generer_poids()
  181. self.population[k].build_network()
  182. def train(self, nb_gen_max = None, debug = False): # Jovian 31 mai 2017
  183. """
  184. Entraîne le réseau.
  185. int nb_gen_max : Le nombre de générations avant l'arrêt (None pour boucle infinie)
  186. bool debug : Affichage d'informations de suivi
  187. """
  188. last_save = self.iter
  189. if debug :
  190. print("Démarrage de l'entraînement à partir de la génération ", self.iter )
  191. # Itération
  192. while self.iter < nb_gen_max :
  193. self.iter += 1
  194. print("\n> Génération ", self.iter, " pour la session ", self.nom_session,".")
  195. # Classement
  196. self.sort(debug = debug)
  197. # Génération suivante
  198. self.generate(debug = debug)
  199. # Sauvegarde
  200. if self.save_rate != None and self.iter - last_save >= self.save_rate :
  201. last_save = self.iter
  202. self.save_population(debug = debug)
  203. # Fin de l'entraînement
  204. return None
  205. def write_protocole(self, debug = False): # Jovian 6 juin 2017
  206. """
  207. Sauvegarde les paramètres utilisés dans le dossier
  208. qui contient les résultats de l'entraînement.
  209. bool debug : Affichage d'informations de suivi
  210. """
  211. # Chemin
  212. chemin = "ReseauNeurones/Base_Poids/" + self.nom_session
  213. chemin += "/Protocole.txt"
  214. # Ecriture
  215. with open( chemin, "w" ) as flux :
  216. flux.write( "Nom du tournoi : " + str(self.nom_tournoi) + "\n" )
  217. flux.write( "Nombre de générations maximal : " + "inconnu" + "\n" )
  218. flux.write( "Taille de population : " + str(len(self.population)) + "\n" )
  219. flux.write( "\n\n" )
  220. flux.write( "nb_elite_kept = " + str(self.nb_elite_kept) + "\n" )
  221. flux.write( "nb_elite_cross = " + str(self.nb_elite_cross) + "\n" )
  222. flux.write( "nb_elite_kept = " + str(self.nb_mixte_cross) + "\n" )
  223. flux.write( "nb_elite_mutate = " + str(self.nb_elite_mutate) + "\n" )
  224. flux.write( "nb_weak_mutate = " + str(self.nb_weak_mutate) + "\n" )
  225. flux.write( "nb_rd_generated = " + str(self.nb_rd_generated) + "\n" )
  226. # Annonce
  227. if debug :
  228. print("|")
  229. print("Protocole enregistré.")