Ceci est un mémo sur l'utilisation de deap. Ici, le mémo est décrit en utilisant deap \ examples \ onemax_numpy.py comme exemple.
deap https://deap.readthedocs.io/en/master/
deap github https://github.com/DEAP/deap
OneMax? C'est un problème de maximiser la somme d'une séquence de nombres composée de 0,1 comme [1, 1, 1, 1, 0, 0, 0, 1, 1, 0]. ⇒ La solution à obtenir est [1, 1, 1, 1, 1, 1, 1, 1, 1, 1].
Dans le code ci-dessous, le problème est une chaîne de longueur 100.
Collez le code avec des notes.
<détails> Résultat d'exécution <détails> ① Je ne sais pas comment déterminer la direction (maximisation / minimisation) de la fonction d'évaluation.
-Un poids négatif est donné lors de la minimisation de l'adaptabilité, et un poids positif est donné lors de sa maximisation (toute valeur est acceptable).
・ Le poids doit être tapple ② Comment générez-vous et évaluez-vous les gènes?
-Enregistrer la fonction générée dans la boîte à outils
Ici, une fonction appelée my_gene_generator qui génère au hasard 0 ou 1 est utilisée.
Inscrivez-vous avec le nom "attr_bool" dans la boîte à outils ・ Enregistrez la fonction d'évaluation dans la boîte à outils
Ici, une fonction appelée evalOneMax
Inscrivez-vous avec le nom «évaluer» dans la boîte à outils ③ Où est la boucle principale?
· Icimy_onemax_numpy.py
import random
import numpy
from deap import algorithms
from deap import base
from deap import creator
from deap import tools
# parameter
n_gene = 100 #Nombre de gènes par individu
n_individuals = 300 #Nombre d'individus par génération
n_generations = 1000 #Nombre de générations
p_cxpb = 0.5 #Taux de croisement (nombre d'individus traversant)
p_mutpb = 0.2 #Taux de mutation (nombre d'individus à muter)
p_mutate = 0.05 #Probabilité de mutation (taux de mutation génique)
n_tournsize = 3 #Taille du tournoi
def evalOneMax(individual):
"""Fonction d'évaluation onemax"""
return sum(individual),
def init_creator():
"""Définir la direction de la fonction objectif"""
#Une fonction objective pour évaluer, maximiser l'adaptabilité individuelle
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
# numpy.Hériter de la classe ndarray
# fitness=creator.Créer une classe individuelle avec une variable membre appelée FitnessMax
creator.create("Individual", numpy.ndarray, fitness=creator.FitnessMax)
return creator
def my_gene_generator(min, max):
"""Fonction de génération de gène"""
return random.randint(min, max)
def init_generator(creator):
"""Définition des méthodes de génération de gènes, d'individus et de générations"""
toolbox = base.Toolbox()
#Définition de la fonction qui produit le gène
toolbox.register("attr_bool", my_gene_generator, 0, 1)
#Définition de la fonction pour générer un individu
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, n_gene)
#Définition de la fonction qui génère la génération
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
return toolbox
def operator_registration(toolbox):
"""Fonction d'évaluation / définition de la stratégie"""
toolbox.register("evaluate", evalOneMax) # evaluate =Fonction d'évaluation
toolbox.register("mate", tools.cxTwoPoint) # mate =Traversée en deux points
toolbox.register("mutate", tools.mutFlipBit, indpb=p_mutate) # mutate =inversion de bits
toolbox.register("select", tools.selTournament, tournsize=n_tournsize) # select = tournament(3)
def stats_register():
"""Paramètres de définition d'état"""
stats = tools.Statistics(lambda ind: ind.fitness.values)
stats.register("avg", numpy.mean)
stats.register("std", numpy.std)
stats.register("min", numpy.min)
stats.register("max", numpy.max)
return stats
def get_cxpoint(size):
"""Réglage 2 points pour croisement à 2 points"""
cxpoint1 = random.randint(1, size)
cxpoint2 = random.randint(1, size - 1)
if cxpoint2 >= cxpoint1:
cxpoint2 += 1
else: # Swap the two cx points
cxpoint1, cxpoint2 = cxpoint2, cxpoint1
return cxpoint1, cxpoint2
def cxTwoPointCopy(ind1, ind2):
"""Crossover à 2 points pour numpy"""
size = min(len(ind1), len(ind2))
cxpoint1, cxpoint2 = get_cxpoint(size)
ind1[cxpoint1:cxpoint2], ind2[cxpoint1:cxpoint2] \
= ind2[cxpoint1:cxpoint2].copy(), ind1[cxpoint1:cxpoint2].copy()
return ind1, ind2
def set_seed(seed=42):
random.seed(seed)
def main(toolbox):
set_seed()
#Génération de la première génération
pop = toolbox.population(n=n_individuals)
#élite pour numpy=1 stratégie
hof = tools.HallOfFame(1, similar=numpy.array_equal)
#définition des statistiques
stats = stats_register()
# main loop
algorithms.eaSimple(pop, toolbox, cxpb=p_cxpb, mutpb=p_mutpb, ngen=n_generations, stats=stats,
halloffame=hof)
#Affichage des meilleurs individus
best_ind = tools.selBest(pop, 1)[0]
print("Best individual is \n Eval:\n %s, \n Gene:\n %s" % (best_ind.fitness.values, best_ind))
return pop, stats, hof
if __name__ == "__main__":
#Définir la direction de la fonction objectif
creator = init_creator()
#Définition des méthodes de génération de gènes, d'individus et de générations
toolbox = init_generator(creator)
#Réglage de la méthode d'évolution
operator_registration(toolbox)
#Routine principale
main(toolbox)
gen nevals avg std min max
0 300 49.88 4.82344 36 64
1 172 54.27 3.60792 45 68
2 181 57.24 3.32 47 68
・ ・ ・
987 183 98.9767 2.3642 89 100
988 171 99.1467 2.02941 89 100
989 192 99.0567 2.26424 90 100
990 176 99.1167 2.12047 88 100
991 183 99.2733 1.94901 90 100
992 164 98.97 2.30704 90 100
993 178 99.03 2.0581 90 100
994 188 98.9767 2.24264 89 100
995 174 98.95 2.3211 86 100
996 177 98.83 2.33833 90 100
997 186 99.0367 2.15453 89 100
998 177 98.9833 2.16095 91 100
999 175 98.9933 2.25683 90 100
1000 181 98.8967 2.23443 89 100
Best individual is
Eval:
(100.0,),
Gene:
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
Où rester coincé
creator.py
#Une fonction objective pour évaluer, maximiser l'adaptabilité individuelle
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
#Il y a deux fonctions objectives à évaluer, la première est de minimiser l'adaptabilité et la seconde est de maximiser.
creator.create("FitnessMulti", base.Fitness, weights=(-1.0, 1.0))
gene_generator.py
def my_gene_generator(min, max):
"""Fonction de génération de gène"""
return random.randint(min, max)
def init_generator(creator):
"""Définition des méthodes de génération de gènes, d'individus et de générations"""
toolbox = base.Toolbox()
#Définition de la fonction qui produit le gène
toolbox.register("attr_bool", my_gene_generator, 0, 1)
gene_eval.py
def evalOneMax(individual):
"""Fonction d'évaluation onemax"""
return sum(individual),
def operator_registration(toolbox):
"""Fonction d'évaluation / définition de la stratégie"""
toolbox.register("evaluate", evalOneMax) # evaluate =Fonction d'évaluation
algorithms.eaSimple(pop, toolbox, cxpb=p_cxpb, mutpb=p_mutpb, ngen=n_generations, stats=stats, halloffame=hof)