This is a memo on how to use deap. Here, the memo is described using deap \ examples \ onemax_numpy.py as an example.
deap https://deap.readthedocs.io/en/master/
deap github https://github.com/DEAP/deap
OneMax? This is a problem that maximizes the sum of a sequence of 0s and 1s, such as [1, 1, 1, 1, 0, 0, 0, 1, 1, 0]. ⇒ The solution to be obtained is [1, 1, 1, 1, 1, 1, 1, 1, 1, 1].
In the code below, the problem is a sequence of length 100.
Paste the code with notes.
my_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 #Number of genes per individual
n_individuals = 300 #Number of individuals per generation
n_generations = 1000 #Number of generations
p_cxpb = 0.5 #Crossover rate (number of crossing individuals)
p_mutpb = 0.2 #Mutation rate (number of individuals to mutate)
p_mutate = 0.05 #Mutation probability (gene mutation rate)
n_tournsize = 3 #Tournament size
def evalOneMax(individual):
"""Evaluation function onemax"""
return sum(individual),
def init_creator():
"""Set the direction of the objective function"""
#One objective function to evaluate, maximizing individual fitness
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
# numpy.Inherit the ndarray class
# fitness=creator.Create an Individual class with a member variable called FitnessMax
creator.create("Individual", numpy.ndarray, fitness=creator.FitnessMax)
return creator
def my_gene_generator(min, max):
"""Gene generation function"""
return random.randint(min, max)
def init_generator(creator):
"""Setting of gene, individual, and generation generation methods"""
toolbox = base.Toolbox()
#Definition of the function that produces the gene
toolbox.register("attr_bool", my_gene_generator, 0, 1)
#Definition of a function to generate an individual
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, n_gene)
#Definition of the function that generates the generation
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
return toolbox
def operator_registration(toolbox):
"""Evaluation function / strategy setting"""
toolbox.register("evaluate", evalOneMax) # evaluate =Evaluation function
toolbox.register("mate", tools.cxTwoPoint) # mate =Two-point crossing
toolbox.register("mutate", tools.mutFlipBit, indpb=p_mutate) # mutate =bit inversion
toolbox.register("select", tools.selTournament, tournsize=n_tournsize) # select = tournament(3)
def stats_register():
"""State definition settings"""
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):
"""2 point setting for 2 point crossing"""
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):
"""2-point crossover for 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()
#Generation of early generation
pop = toolbox.population(n=n_individuals)
#elite for numpy=1 Strategy
hof = tools.HallOfFame(1, similar=numpy.array_equal)
#stats definition
stats = stats_register()
# main loop
algorithms.eaSimple(pop, toolbox, cxpb=p_cxpb, mutpb=p_mutpb, ngen=n_generations, stats=stats,
halloffame=hof)
#Display of best individuals
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__":
#Set the direction of the objective function
creator = init_creator()
#Setting of gene, individual, and generation generation methods
toolbox = init_generator(creator)
#Evolution method setting
operator_registration(toolbox)
#Main routine
main(toolbox)
Execution result
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]
① I don't know how to determine the direction (maximization / minimization) of the evaluation function. -A negative weight is given when minimizing fitness, and a positive weight is given when maximizing fitness (any value is acceptable). ・ Weight must be tuple
creator.py
#One objective function to evaluate, maximizing individual fitness
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
#There are two objective functions to evaluate, the first is to minimize fitness and the second is to maximize.
creator.create("FitnessMulti", base.Fitness, weights=(-1.0, 1.0))
② How do you generate and evaluate genes? -Register the generated function in the toolbox Here, a function called my_gene_generator that randomly generates 0 or 1 is used. Register with the name "attr_bool" in the toolbox
gene_generator.py
def my_gene_generator(min, max):
"""Gene generation function"""
return random.randint(min, max)
def init_generator(creator):
"""Setting of gene, individual, and generation generation methods"""
toolbox = base.Toolbox()
#Definition of the function that produces the gene
toolbox.register("attr_bool", my_gene_generator, 0, 1)
・ Register the evaluation function in the toolbox Here, a function called evalOneMax Register with the name "evaluate" in the toolbox
gene_eval.py
def evalOneMax(individual):
"""Evaluation function onemax"""
return sum(individual),
def operator_registration(toolbox):
"""Evaluation function / strategy setting"""
toolbox.register("evaluate", evalOneMax) # evaluate =Evaluation function
③ Where is the main loop? ・ Here
algorithms.eaSimple(pop, toolbox, cxpb=p_cxpb, mutpb=p_mutpb, ngen=n_generations, stats=stats, halloffame=hof)