I would like to introduce the genetic algorithm library Deap that can be used in Python. There is another Python genetic algorithm library called Pyevolve, but Deap seems to be more active in development, so I would like to use this. I will. Below are the main algorithms and features available in Deap.
Example This time I will explain the example of GA. First, import the module.
import random
from deap import base
from deap import creator
from deap import tools
creator inherits from the base class and creates a new class.
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)
The first line creates a goodness-of-fit class that is optimized by maximizing the goodness of fit. Although weights are an array, size 1 is fine for single-purpose optimization (although "," seems to be necessary), and multi-purpose optimization arranges the weights for each purpose. Set (-1.0,) to optimize by minimizing.
toolbox = base.Toolbox()
# Attribute generator
toolbox.register("attr_bool", random.randint, 0, 1)
# Structure initializers
toolbox.register("individual", tools.initRepeat, creator.Individual,
toolbox.attr_bool, 100)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox creates a function. In register on the 3rd line, a function called attr_bool is created by giving 0,1 arguments to random.randint. attr_bool is a function that randomly generates 0 or 1. initRepeat is a function that is prepared in Toolbox in advance. The first argument is the type of the container that stores the data, the second is the function that generates individual data, and the third is the size of the container. Here, a function called individual (individual) and a function called population (group) are created from initRepeat. Next, create evaluation functions, intersections, mutations, and selection functions. (Note that there is a "," in the return value of the evaluation function.)
def evalOneMax(individual):
return sum(individual),
toolbox.register("evaluate", evalOneMax)
toolbox.register("mate", tools.cxTwoPoints)
toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
toolbox.register("select", tools.selTournament, tournsize=3)
Now that the GA settings are complete, let's create the actual evolutionary computation routine.
def main():
random.seed(64)
#Generate an early population
pop = toolbox.population(n=300)
CXPB, MUTPB, NGEN = 0.5, 0.2, 40 #Crossing probability, mutation probability, evolutionary computation loop count
print("Start of evolution")
#Evaluation of early population
fitnesses = list(map(toolbox.evaluate, pop))
for ind, fit in zip(pop, fitnesses):
ind.fitness.values = fit
print(" Evaluated %i individuals" % len(pop))
#Evolutionary computation started
for g in range(NGEN):
print("-- Generation %i --" % g)
#Select the next generation population
offspring = toolbox.select(pop, len(pop))
#Clone the population
offspring = list(map(toolbox.clone, offspring))
#Adapt crossing and mutation to selected populations
#Take out even-numbered and odd-numbered individuals and intersect
for child1, child2 in zip(offspring[::2], offspring[1::2]):
if random.random() < CXPB:
toolbox.mate(child1, child2)
del child1.fitness.values
del child2.fitness.values
for mutant in offspring:
if random.random() < MUTPB:
toolbox.mutate(mutant)
del mutant.fitness.values
#Calculate the goodness of fit by collecting individuals for which the goodness of fit has not been calculated
invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
fitnesses = map(toolbox.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses):
ind.fitness.values = fit
print(" Evaluated %i individuals" % len(invalid_ind))
#Make the next generation offspring
pop[:] = offspring
#Array the goodness of fit of all individuals
fits = [ind.fitness.values[0] for ind in pop]
length = len(pop)
mean = sum(fits) / length
sum2 = sum(x*x for x in fits)
std = abs(sum2 / length - mean**2)**0.5
print(" Min %s" % min(fits))
print(" Max %s" % max(fits))
print(" Avg %s" % mean)
print(" Std %s" % std)
print("-- End of (successful) evolution --")
best_ind = tools.selBest(pop, 1)[0]
print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))
After that, you can call this main function like ```if name == "main": main () `` `.
Start of evolution
Evaluated 300 individuals
-- Generation 0 --
Evaluated 189 individuals
Min 40.0
Max 65.0
Avg 54.7433333333
Std 4.46289766358
-- Generation 1 --
Evaluated 171 individuals
Min 44.0
Max 70.0
Avg 58.48
Std 3.98533980149
...(Omitted on the way)...
-- Generation 38 --
Evaluated 180 individuals
Min 89.0
Max 100.0
Avg 97.7466666667
Std 2.32719191779
-- Generation 39 --
Evaluated 196 individuals
Min 88.0
Max 100.0
Avg 98.1833333333
Std 2.33589145486
-- End of (successful) evolution --
Best individual is [True, 1, 1, 1, 1, 1, True, 1, 1, 1, 1, True, 1, 1, 1, 1, True, 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, True, True, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, True, 1, 1, 1, 1, True, True, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], (100.0,)
1 and True are mixed in the array, probably because of the problem of the function of intersection or mutation, but you can see that the optimum solution is required.
Deap Example: http://deap.gel.ulaval.ca/doc/default/examples/ga_onemax.html
Recommended Posts