遗传算法与深度学习实战——遗传算法框架DEAP
0. 前言
虽然可以使用纯 Python 编写所有遗传算法代码,但我们不必重新造轮子,相反,在之后的学习中,我们将使用成熟的 DEAP
(Distributed Evolutionary Algorithms in Python
) 进化计算框架,该框架能够实现包括遗传算法在内的各种进化计算方法。在本节中,我们将学习 DEAP
库中的重要数据结构和工具。
1. DEAP 框架介绍
DEAP
(Distributed Evolutionary Algorithms in Python
) 是一个用 Python
编写的开源框架,用于实现和运行各种进化算法 (Evolutionary Algorithms
, EA
)。它设计用于处理各种进化计算任务,包括遗传算法 (Genetic Algorithms
, GA
)、进化策略 (Evolution Strategies
, ES
)、遗传编程 (Genetic Programming
, GP
) 等。除了 DEAP
外,还有许多其它用于遗传算法的 Python
框架—— GAFT
,Pyevolve
和 PyGMO
等,相比之下,DEAP
具有以下优势:
DEAP
提供了一套灵活的工具和模块,可以轻松地定义和执行各种进化算法。它支持用户根据特定的问题需求定制算法的各个部分,如选择 (selection
)、交叉 (crossover
)、突变 (mutation
) 等DEAP
提供了大量的工具和算法组件,包括各种进化算法中常用的操作(如选择、交叉、突变)、适应度评估、种群管理等,可以帮助用户快速实现复杂的进化算法,并且方便地进行实验和比较不同的算法配置- 同时,
DEAP
易于使用,DEAP
设计上尽可能简化了进化算法的实现过程,使得即使是对进化算法不太熟悉的用户也能够快速上手,进行自己问题的求解
与其它 Python
库一样,可以使用 pip
命令安装 DEAP
库:
$ pip install deap
2. creator 模块
creator
模块可以作为元工厂,能够通过添加新属性来扩展现有类。例如,有一个名为 Employee
的类,使用 creator
工具,可以通过创建 Developer
类来扩展 Employee
类:
import deap import creator
creator.create("Developer", Employee, position="Developer", programmmingLanguage=set)
传递给create()
函数的第一个参数是新类的名称。第二个参数是要扩展的现有类,接下来是使用其他参数定义新类的属性。如果为参数分配了一个类(例如 dict
或 set
),它将作为构造函数中初始化的实例属性添加到新类中。如果参数不是类(例如字符串),则将其添加为静态 (static
) 属性。
因此,创建的 Developer
类将扩展 Employee
类,并将具有一个静态属性 position
,设置为 “Developer
”,以及一个实例属性,类型为 set
的 programmingLanguages
,该属性在构造函数中初始化。因此,以上代码实际上等效于:
class Developer(Employee):
position = "Developer"
def __init__(self):
self.programmmingLanguage = set()
这个新类存在于 creator
模块中,因此需要引用时使用 creator.Developer
。
使用 DEAP
时,creator
模块通常用于创建适应度类 Fitness
以及个体类 Individual
。
2.1 创建适应度类
使用 DEAP
时,适应度封装在 Fitness
类中。在 DEAP
框架中适应度可以有多个组成部分,每个组成部分都有自己的权重 (weights
)。这些权重的组合定义了适合给定问题的行为或策略。
2.1.1 定义适应度策略
为了快速定义适应度策略,DEAP
使用了抽象 base.Fitness
类,其中包含 weights
元组,以定义策略并使类可用。可以通过使用 creator
创建基础 Fitness
类的扩展来完成,类似于创建 Developer
类:
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
这将产生一个 creator.FitnessMax
类,该类扩展了 base.Fitness
类,并将 weights
类属性初始化为值 (1.0,
)。Note.
weights参数是一个元组。
FitnessMax
类的策略是在遗传算法过程中最大化单目标解的适应度值。相反,如果有一个单目标问题,需要使适应度值最小的解,则可以使用以下定义来创建最小化策略:
creator.create("FitnessMin", base.Fitness,weights=(-1.0,))
还可以定义具有优化多个目标且重要性不同的策略:
creator.create("FitnessCompound", base.Fitness, weights=(1.0,0.2,-0.5))
这将产生一个 creator.FitnessCompound
类,它拥有三个不同的适应度组成部分。第一部分权重为 1.0
,第二部分权重为 0.2
,第三部分权重为 -0.5
。这将倾向于使第一和第二部分(或目标)最大化,而使第三部分(或目标)最小化。
2.1.2 适应度存储方式
虽然权重元组定义了适应度策略,但是一个对应的元组(称为 values
)用于将适应度值存储在 base.Fitness
类中。这些值是从单独定义的函数(通常称为 evaluate()
) 获得的。就像 weights
元组一样,values
元组存储每个适应度组件(对象)值。
元组 wvalues
包含通过将 values
元组的每个分量与其 weights
元组的对应分量相乘而获得的加权值。只要得到了实例的适应度值,就会计算加权值并将其插入 wvalues
中,这些值用于个体之间的适应度的比较操作。
2.2 创建个体类
在 DEAP
中,creator
工具的第二个常见用途是定义构成遗传算法种群的个体。遗传算法中的个体使用可以由遗传算子操纵的染色体来表示,通过扩展表示染色体的基类来创建 “Individual
” 类。另外,DEAP
中的每个个体实例都需要包含其适应度函数作为属性。为了满足这两个要求,利用 creator
来创建 creator.Individual
类:
creator.create("Individual", list, fitness=creator.FitnessMax)
该代码片段具有以下两个效果:
- 创建的
Individual
类扩展了Python
的list
类,这意味着使用的染色体是列表类型 - 创建的
Individual
类的每个实例将具有之前创建的FitnessMax
属性
3. Toolbox 类
DEAP
框架提供的第二种高效创建遗传算法的机制是 base.Toolbox
类。Toolbox
用作函数(或操作)的容器,能够通过别名机制和自定义现有函数来创建新的运算符。假设有一个函数 sumOfTwo()
:
def sumOfTwo(a,b):
return a + b
使用 toolbox
,可以创建一个新的运算,incrementByFive()
,该运算符利用 sumOfTwo()
函数创建:
import base
toolbox = base.Toolbox()
toolbox.register("incrementByFive", sumOfTwo,b=5)
传递给register()
函数的第一个参数是新运算符所需的名称(或别名),第二个参数是被定制的现有函数。创建完成后,每当调用新运算符时,其他参数都会自动传递给创建的函数,如:
toolbox.incrementByFive(10)
等效于:
sumOfTwo(10, 5)
这是因为参数 b
已由 incrementByFive
运算符定义为 5
。
3.1 创建遗传算子
为了快速构建遗传流程,可以使用 Toolbox
类定制 tools
模块的现有函数。tools
模块包含许多便捷的函数,这些函数包括选择、交叉和变异的遗传算子以及程序的初始化等。例如,以下代码定义了三个别名函数,用作遗传算子:
from deap import tools
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutFlipBit, indpb=0.02)
这三个别名函数的详细说明:
select
注册为tools
函数selTournament()
的别名,且tournsize
参数设置为3
,这将创建一个toolbox.select
运算符,用于创建锦标赛规模为3
的锦标赛选择算子mate
注册为tools
函数cxTwoPoint()
的别名,这将创建执行两点交叉的toolbox.mate
算子mutate
注册为tools
函数mutFlipBit()
的别名,并将indpb
参数设置为0.02
,这将创建一个翻转每个特征的概率为0.02
的位翻转突变算子
tools
模块提供了各种遗传算子的实现,以下列示常用遗传算子的实现函数。
- 选择算子主要包括:
selRoulette() #轮盘选择
selStochasticUniversalSampling()#随机遍历采样(SUS)
selTournament()#锦标赛选择
- 交叉算子主要包括:
cxOnePoint() #单点交叉
cxUniform() #均匀交叉
cxOrdered() #有序交叉
cxPartialyMatched() #实现部分匹配交叉
- 突变算子主要包括:
mutFlipBit() #位翻转突变
mutGaussian() #正态分布突变
3.2 创建种群
工具模块的 init.py
文件包含用于创建和初始化遗传算法的函数,其中包括 initRepeat()
,它接受三个参数:
- 要放置结果对象的容器类型
- 用于生成将放入容器的对象的函数
- 要生成的对象数
如:
#产生含有30个随机数的列表,这些随机数介于0和1之间
randomList = tools.initRepeat(list, random.random, 30)
此示例中,list
是用作要填充的容器的类型,random.random
是生成器函数,而 30
是调用生成器函数以生成填充容器的值的次数。如果想用 0
或 1
的整数随机数填充列表,则可以创建一个使用 random.radint()
生成随机值 0
或 1
的函数,然后将其用作 initRepeat()
的生成器函数:
def zeroOrOne():
return random.randint(0,1)
randomList = tools.initRepeat(list, zeroOrOne, 30)
或者,可以利用 Toolbox
:
#创建zeroOrOne运算符,使用参数0、1调用random.radint()
toolbox.register("zeroOrOne", random.randint, 0, 1)
randomList = tools.initRepeat(list, tools.zeroOrOne,30)
3.3 计算适应度
虽然 Fitness
类定义了确定其策略(例如最大化或最小化)的适应度权重,但实际的适应度是从单独定义的函数中获得的。该适应度计算函数通常使用别名 evalidate
来注册到 Toolbox
模块中:
def someFitnessCalculationFunction(individual):
"""算给定个体的适应度"""
return _some_calculation_of_of_the_fitness(individual)
#将evaluate注册为someFitnessCalculationFunction()的别名
toolbox.register("evaluate",someFitnessCalculationFunction)
小结
DEAP
是一个基于 Python
的开源框架,专门用于实现和运行各种进化算法,旨在帮助用户轻松地构建和调整进化算法,用于解决各种优化和搜索问题。本节中,介绍了 DEAP
相较于其它进化计算框架的优势,以及 DEAP
中重要的工具 creator
和 Toolbox
。
系列链接
遗传算法与深度学习实战(1)——进化深度学习
遗传算法与深度学习实战(2)——生命模拟及其应用
遗传算法与深度学习实战(3)——生命模拟与进化论
遗传算法与深度学习实战(4)——遗传算法详解与实现
文章评论