概述

如果你习惯于其他进化算法框架,你会注意到我们在DEAP中做事的方式有所不同。我们没有用预定义的类型限制你,而是提供了创建适当类型的方法。我们没有提供封闭的初始化器,而是让你根据自己的意愿定制它们。我们没有建议不合适的操作符,而是明确要求你明智地选择它们。我们没有实现许多封闭的算法,而是允许你编写适合你所有需求的算法。本教程将简要概述DEAP的全部内容,以及每个DEAP程序的构成。

类型

首先要做的是为你的问题选择合适的类型。然后,与其在可用类型列表中寻找,DEAP 允许你构建自己的类型。这是通过 creator 模块完成的。创建一个合适的类型可能看起来很复杂,但创建者让它变得非常简单。事实上,这通常在一行代码中完成。例如,以下代码创建了一个用于最小化问题的 FitnessMin 类和一个从列表派生的 Individual 类,其适应度属性设置为刚刚创建的适应度。

from deap import base, creator
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)

就是这样。关于创建类型的更多信息可以在 创建类型 教程中找到。

初始化

一旦类型创建完毕,你需要用有时是随机值,有时是猜测的值来填充它们。同样,DEAP 提供了一个简单的机制来做到这一点。Toolbox 是一个包含各种工具的容器,包括可以完成所需任务的初始化器。以下代码继续了前面的代码,为包含随机浮点数的个体和包含这些个体的种群创建了初始化器。

import random
from deap import tools

IND_SIZE = 10

toolbox = base.Toolbox()
toolbox.register("attribute", random.random)
toolbox.register("individual", tools.initRepeat, creator.Individual,
                 toolbox.attribute, n=IND_SIZE)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

这创建了从个体初始化的函数,这些个体本身使用随机浮点数初始化。这些函数在工具箱中以其默认参数在给定名称下注册。例如,可以调用函数 toolbox.population() 来立即创建一个种群。更多初始化方法可以在 创建类型 教程和各种 示例 中找到。

运算符

操作符就像初始化器一样,只不过其中一些已经在 tools 模块中实现了。一旦你选择了完美的操作符,只需在工具箱中注册它们。此外,你必须创建你的评估函数。这就是在 DEAP 中实现的方式。

def evaluate(individual):
    return sum(individual),

toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.1)
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("evaluate", evaluate)

注册的函数由工具箱重命名,允许不依赖于操作符名称的通用算法。另请注意,适应度值必须是可迭代的,这就是为什么我们在评估函数中返回一个元组。更多关于这方面的内容,请参阅 运算符和算法 教程和 示例

算法

现在一切准备就绪,我们可以开始编写自己的算法了。通常这是在一个主函数中完成的。为了完整性,我们将开发完整的代际算法。

def main():
    pop = toolbox.population(n=50)
    CXPB, MUTPB, NGEN = 0.5, 0.2, 40

    # Evaluate the entire population
    fitnesses = map(toolbox.evaluate, pop)
    for ind, fit in zip(pop, fitnesses):
        ind.fitness.values = fit

    for g in range(NGEN):
        # Select the next generation individuals
        offspring = toolbox.select(pop, len(pop))
        # Clone the selected individuals
        offspring = map(toolbox.clone, offspring)

        # Apply crossover and mutation on the offspring
        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

        # Evaluate the individuals with an invalid fitness
        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

        # The population is entirely replaced by the offspring
        pop[:] = offspring

    return pop

也可以使用 algorithms 模块中现成的四种算法之一,或者使用该模块中称为变体的构建块来构建。