Take Home Message:
本文是“利用ChatGPT和MAKE法实现新知识快速学习及变现”的方法,该方法将学习新知识学习和开发成本由数周降低到半小时,即:
-->问原理和便于理解的案例【算法核心,不轻易变,需仔细学习】(25mins)
-->问行业使用现状、最新技术【易变】(2mins)
--->问用最新技术解决某客户实际问题的具体代码【易变】(2mins)
以下内容全部来自chatgpt,而不来自于任何第三方网站、书籍等。
一、问:能帮我写一段遗传算法的代码,优化A、B、C三个值吗?
Chatgpt答:原始给出代码如下:
在下面这个代码中,我们定义了一个目标函数 `fitness_function`,用于计算个体的适应度。我们还定义了一个个体类 `Individual`,包含三个基因 `a`、`b`、`c` 和一个适应度 `fitness`。我们还定义了一个遗传算法类 `GeneticAlgorithm`,包含初始化种群、选择、交叉、变异和进化等方法。在 `evolve` 方法中,我们初始化种群,然后进行若干代的进化,每一代都进行选择、交叉和变异操作,并输出最优个体。 你可以根据自己的需求修改代码中的参数和函数,以达到优化 A、B、C 三个值的目的。
上述代码每段粘给chatgpt来解释:
import random
# 定义目标函数,用于评估适应度
def fitness_function(a, b, c):
return a**2 + b**2 + c**2
# 定义了一个个体类 `Individual`,包含三个基因 `a`、`b`、`c` 和一个适应度 `fitness`
class Individual:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
self.fitness = fitness_function(a, b, c)
def __repr__(self):
return f"({self.a}, {self.b}, {self.c}) - Fitness: {self.fitness}"
# 定义遗传算法类,包含初始化种群(定义种群个体数量population_size、突变率mutation_rate、迭代次数generation),选择、交叉、变异和进化等方法。
class GeneticAlgorithm:
def __init__(self, population_size, mutation_rate, generations):
self.population_size = population_size
self.mutation_rate = mutation_rate
self.generations = generations
self.population = []
# 初始化种群:每个个体random其三个基因Individual(a,b,c) -->循环创造多个个体,并存在population列表中。
def initialize_population(self):
for i in range(self.population_size):
a = random.uniform(-10, 10)
b = random.uniform(-10, 10)
c = random.uniform(-10, 10)
individual = Individual(a, b, c)
self.population.append(individual)
# 选择:
'''这段代码是一个遗传算法中的选择操作。具体解释如下:
首先,定义了一个名为selection的方法,它接受一个self参数,意味着它是一个类的方法。
创建了一个名为parents的空列表,用于存储选出的父代个体。使用for循环两次,确保选出两个父代个体。
在每次循环中,代码进行了以下操作:
a. 使用random模块的sample方法,在当前种群(self.population)中随机选择3个个体。
b. 使用sort方法对选出的3个个体进行排序,关键字参数key指定了排序的依据是个体的适应度值(x.fitness)。
c. 将排序后的个体列表中的第一个个体(tournament[0])添加到parents列表中。
循环结束后,方法返回了一个包含两个选出的父代个体的列表parents。'''
def selection(self):
parents = []
for i in range(2):
# 锦标赛选择
tournament = random.sample(self.population, 3)
tournament.sort(key=lambda x: x.fitness)
parents.append(tournament[0])
return parents
# 交叉
'''这段代码是一个遗传算法中的交叉操作。具体解释如下:
首先,定义了一个名为crossover的方法,它接受一个参数parents,表示传递过来的两个父代个体。
通过对两个父代个体的对应基因进行平均值操作,得到了三个新的基因值a、b和c。具体计算方式是将父代个体的对应基因值相加,再除以2。
使用这三个新的基因值创建了一个名为child的新个体。这里假设在遗传算法的实现中,存在一个名为Individual的类,它具有根据给定的基因值
创建新个体的方法。
最后,方法返回了这个新的个体child。'''
def crossover(self, parents):
a = (parents[0].a + parents[1].a) / 2
b = (parents[0].b + parents[1].b) / 2
c = (parents[0].c + parents[1].c) / 2
child = Individual(a, b, c)
return child
# 变异
'''
这段代码是一个遗传算法中的突变操作。具体解释如下:
首先,定义了一个名为mutation的方法,它接受一个参数child,表示传递过来的需要突变的个体。
在突变操作中,首先使用random模块的random方法生成一个0到1之间的随机数。如果这个随机数小于突变率(self.mutation_rate),则进行突变操作。
在突变操作中,通过对个体的每个基因值进行随机增减,以引入一定的变异。具体操作如下:
a. 对child个体的基因a,使用random模块的uniform方法生成一个-1到1之间的随机数,然后将其加到原来的基因值上。
b. 对child个体的基因b和c,也进行类似的操作。
在完成基因的突变后,通过调用fitness_function方法,计算并更新child个体的适应度值。这里假设在遗传算法的实现中,
存在一个名为fitness_function的函数,它能够根据给定的基因值计算个体的适应度值。
最后,方法返回经过突变处理后的个体child。
'''
def mutation(self, child):
if random.random() < self.mutation_rate:
child.a += random.uniform(-1, 1)
child.b += random.uniform(-1, 1)
child.c += random.uniform(-1, 1)
child.fitness = fitness_function(child.a, child.b, child.c)
return child
# 在 `evolve` 方法中,我们初始化种群,然后进行若干代的进化,每一代都进行选择、交叉和变异操作,并输出最优个体。
'''这段代码是一个遗传算法中的进化过程。具体解释如下:
首先,定义了一个名为evolve的方法,该方法用于执行进化过程。该方法不接受任何参数。
首先调用initialize_population方法,用于初始化种群。
使用for循环,对代数进行迭代,依次进行进化操作。
在每一代中,通过for循环依次生成新的个体。具体操作如下:
a. 使用selection方法选择两个父代个体。
b. 使用crossover方法对选出的父代个体进行交叉操作,生成一个子代个体。
c. 使用mutation方法对子代个体进行突变操作。
d. 将新生成的子代个体添加到new_population列表中。
e. 使用crossover方法对反转后的父代个体进行交叉操作,生成另一个子代个体。注意:parents[::-1]是Python中的切片操作,它可以用于将一个列表
或序列反转,得到原来序列的逆序版本。如my_list = [1, 2, 3, 4, 5],my_list[::-1]=[5, 4, 3, 2, 1]
f. 使用mutation方法对另一个子代个体进行突变操作。
g. 将新生成的子代个体添加到new_population列表中。
更新种群为新生成的个体new_population。
使用sort方法对种群进行排序,关键字参数key指定排序的依据是个体的适应度值(x.fitness)。
打印出当前代数以及种群中最优个体的信息。
注意:在上述代码中,self.population_size表示种群数量,self.generations表示进化的代数。
initialize_population、selection、crossover和mutation方法的具体实现不在这段代码中,但可以假设它们在遗传算法的实现中有相应的功能。
同时,打印信息的语句可以根据需要进行调整或删除。'''
def evolve(self):
self.initialize_population()#随机初始化第一代种群的每个个体
for i in range(self.generations): #开始按照generation次数进化
new_population = [] #生成子代暂存器
for j in range(self.population_size // 2):#1/2种群数量次数操作,每次生成两个子代
parents = self.selection() #选两个父代个体
child = self.crossover(parents) #两父代个体交叉-->第一个子代
child = self.mutation(child) #子代自己基因突变
new_population.append(child) #子代添加到新种群
child = self.crossover(parents[::-1])#父代反转,同样过程,再生成第二个子代
child = self.mutation(child)
new_population.append(child)
self.population = new_population #子代,替换父代
self.population.sort(key=lambda x: x.fitness) #新一代排序
print(f"Generation {i+1}: {self.population[0]}")#输出“代数编号”及“最优个体”
# 运行遗传算法一个实例
'''首先,通过GeneticAlgorithm(population_size=10, mutation_rate=0.1, generations=10)创建了一个名为ga的遗传算法实例。
population_size=10表示种群的大小为10,即初始种群中包含10个个体。
mutation_rate=0.1表示突变率为0.1,即在交叉操作后,每个基因在进行突变的概率为0.1。
generations=10表示进化的代数为10,即遗传算法将进行10代的迭代优化。
接下来,调用ga.evolve()方法来执行遗传算法的进化过程。
这个方法将执行遗传算法中的初始化种群、选择操作、交叉操作、突变操作、更新种群等一系列步骤,使种群逐代进化,
并在每一代结束后输出当前最优解或适应度最高的个体。
通过执行ga.evolve()方法,遗传算法将按照给定的参数进行10代的优化,并输出每一代中种群中最优解的信息。'''
ga = GeneticAlgorithm(population_size=10, mutation_rate=0.1, generations=100)
ga.evolve()
二、问:帮我详细解释下遗传算法的思想和步骤
ChatGPT答:
遗传算法是一种模拟生物进化过程进行优化的一种算法。其基本思想是通过模拟遗传和进化的过程,通过一代一代的迭代优化,逐渐逼近问题的最优解。
遗传算法的基本步骤如下:
-
初始化种群:根据问题的特征,初始化一个初始种群,种群中包含若干个个体,每个个体表示问题的一种解决方案,并且具有一定的随机性。种群的大小和个体的编码方式需要根据问题的特性进行设置。
-
适应度评估:为种群中的每个个体计算适应度值,这个值用于评估个体解决问题的优劣程度。适应度值的计算方式根据问题的不同而有所变化,可以是一个函数值、一个目标函数值、一个评分等。
-
选择操作:通过某种选择策略选出一部分适应度高的个体作为父代,使其有更高的概率能够被选中用于繁殖下一代。一般的选择策略有轮盘赌选择、锦标赛选择等。
-
交叉操作:通过交叉操作,将选出的父代个体的基因进行交换或重组,生成新的子代个体。交叉操作的目的是将不同父代个体的优良基因结合起来,提高种群的遗传多样性。
-
突变操作:对子代个体进行随机变异操作,引入一定的随机性,以避免种群陷入局部最优解。变异操作可以是对个体基因值的随机增减、交换位置、插入或删除等。
-
更新种群:用新生成的子代个体替代旧的父代个体,更新种群,进入下一代迭代。
-
终止条件判断:判断是否满足终止条件,如果满足则停止迭代,输出结果;否则,返回步骤2进行下一代迭代。
-
输出结果:当迭代结束后,输出最优解或者适应度最高的个体作为问题的解。
需要注意的是,遗传算法是一种启发式的优化算法,不保证一定能够找到全局最优解,但通常在搜索空间较大且复杂的优化问题中具有较好的搜索能力。算法的性能和结果质量取决于参数的设置、选择操作、交叉操作、突变操作等的设计和调优。因此,对于不同的问题,需要根据具体情况进行适当调整和优化。
问chatgpt:什么是启发式算法?
ChatGPT: 启发式算法是一种基于经验和直觉的问题求解方法,用于解决复杂的、难以找到最优解的问题。与传统的精确算法不同,启发式算法不追求找到问题的精确解,而是通过近似解或者近似最优解来解决问题。
启发式算法通常通过模仿自然界的进化、群体智能等过程,利用一种搜索策略来指导问题的求解过程。其主要思想是从可能的解空间中逐步搜索,通过评估当前解的好坏程度来导向搜索方向,从而逐渐接近问题的最优解或者较优解。
启发式算法通常具有以下特点:
- 基于迭代的优化过程:启发式算法通过多次迭代来不断改进当前的解,逐步接近最优解。
- 高度并行和随机化:启发式算法通常使用并行计算的方法来加速搜索过程,并引入一定的随机性以避免陷入局部最优解。
- 不保证找到全局最优解:由于问题的复杂性和搜索空间的庞大,启发式算法无法保证找到全局最优解,但通常能找到较好的近似解。
- 可应用于大规模问题和复杂优化问题:相比于精确算法,启发式算法具有较好的可扩展性和适应性,在处理大规模问题和复杂优化问题时具有一定优势。
常见的启发式算法包括遗传算法、粒子群优化算法、模拟退火算法、蚁群算法等。这些算法在不同的问题领域具有广泛的应用,如组合优化问题、路径规划问题、机器学习等。
问chatgpt:最好的遗传算法库有哪些?
答:DEAP
DEAP库简介与笔记
DEAP是一个进化计算框架,能够帮助我们快速实现和测试进化算法。
DEAP的特性:
- 各类遗传算法
- 遗传规划
- 进化策略
- 多目标优化
- 多种群之间的协作与竞争
- 并行计算
- 计算过程中设定检查点
- 设置基准模块,检验算法能力
- 支持粒子群算法、差分进化算法等
- DEAP下载:GitHub - DEAP/deap: Distributed Evolutionary Algorithms in Python
- (强烈建议,一篇足够从安装到使用,不用看其他)DEAP Document(用户手册):DEAP documentation — DEAP 1.4.1 documentation
中文某博主简介(较为专业的6讲,相对逻辑和应用案例都不错,至少比我写的好多了,建议看。ps:下面我写的,我都不想看,完全不知所云地记笔记DEAP Document,只见树木,无森林。。。。标黑了。直接看别人写的链接从1~8,从少许理论到各种案例齐全。):基于DEAP库的Python进化算法从入门到入土--(一)进化算法的基本操作与实现 - 简书
一般来说,进化算法的流程图大致如下:
DEAP进行进化算法设计有四大顺序模块:
一、Type(类型):用DEAP工具把你的问题用一行到两行就能设计成合适的类型。类型设计是指确定“个体”Individual和适应函数“FitnessFuction”
二、Initialization(初始化):利用DEAP进行随机值或者猜测值对Individual进行初始化。
三、Operators(操作符):利用DEAP工具,设定你需要的“选择”、“交叉”、“编译”等操作符。DEAP内置多种操作符,比如“选择“”操作符就涵盖13种(锦标赛、轮盘赌等)。
四、Algorithms(算法):这是任使用者自由发挥的阶段,可以编写自己的算法。
下面 ,我们可以让ChatGPT举个例子,如何使用DEAP来写一段上述同样问题。
三、问chatgpt:“能帮我用python写一段遗传算法的代码,利用DEAP库来优化A、B、C三个值吗?”
回答:在这段代码中,我们首先定义了一个三元组作为个体的基本单元,然后使用DEAP库的`initCycle`函数初始化了一个三元组的个体。接着,我们定义了一个评价函数,用于计算个体的适应度值。在遗传算法操作中,我们使用了标准的交叉和变异操作,以及锦标赛选择算子。最后,在主函数中,我们使用了50个个体进行了50代的进化,并输出了每一代中的最优解。 你可以根据自己的需求修改代码中的参数和函数,以实现更加复杂的遗传算法优化问题。
import random
from deap import base, creator, tools
# 定义问题
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)
toolbox = base.Toolbox()
toolbox.register("attr_float", random.uniform, -10, 10)
toolbox.register("individual", tools.initCycle, creator.Individual,
(toolbox.attr_float, toolbox.attr_float, toolbox.attr_float), n=1)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
# 定义评估函数
def evaluate(individual):
a, b, c = individual
# 这里是你要优化的函数,可以根据实际情况进行修改
result = a**2 + b**2 + c**2
return result,
toolbox.register("evaluate", evaluate)
# 定义遗传算法参数
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("map", map)
# 运行遗传算法
def main():
pop = toolbox.population(n=50)
CXPB, MUTPB, NGEN = 0.5, 0.2, 50
# 评估初始种群
fitnesses = list(map(toolbox.evaluate, pop))
for ind, fit in zip(pop, fitnesses):
ind.fitness.values = fit
# 进化
for g in range(NGEN):
offspring = toolbox.select(pop, len(pop))
offspring = list(map(toolbox.clone, 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
# 重新评估
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
# 更新种群
pop[:] = offspring
# 输出结果
fits = [ind.fitness.values[0] for ind in pop]
best_ind = tools.selBest(pop, 1)[0]
print("Generation %i: Best Fitness = %f, Best Individual = %s" % (g, max(fits), best_ind))
if __name__ == "__main__":
main()
一次生成的程序拷贝到电脑里,Run一次,Bingo~
Take Home message:
以下为初次探索,摸索并学习一个新算法的步骤。中间有弯路但终总结一套方法。
一、首先让chatgpt对遗传算法及其内部各组成部分(种群、适应度、选择、交叉、突变等)的基本设计哲学进行讲解,并给出了一个简单且非常易于初学者学习理解的例子。
二、然后让chatgpt推荐一些现成的遗传算法库(快速敏捷开发),得到DEAP。
三、研究DEAP库的原始Document。(低效,不符合MAKE原理,该部分已删除)
三、再针对一个具体问题,让chatgpt利用DEAP库再给出针对具体问题进行编程的开发代码。
以下内容,虽花了两个小时研究原始DEAP用户手册,但不满意。Do over。从正文中舍弃掉。用户手册有时是经典,有时是字典。
以下将对每个模块进行简单剖析:
一、二、Type(类型)和Initialization(初始化)
类型包含:Fitness、Individual和Pupulation设定。
创建Fitness :
creator.create("FitnessMulti", base.Fitness, weights=(-1.0, 1.0))
提供的Fitness类是一个抽象类,它需要一个weights属性,且必须是元组,元组内元素个数与我们所求的目标个数一直。若欲采用最小化适应度写负数(常写-1,与符号相关与数值无关),而想让适应度最大化就写正数(常写1)。此代码生成一个适应度,使第一个目标最小化,并使第二个目标最大化。
创建Individual:
(需逐步定义 List、Permutaion、Arithmetic Expression、Evolution Strategy、Paticle等)
根据不同算法(GA、GP、ES、PSO、DE、...),个体的设置将会多样。所以DEAP不提供预设的Individual格式,而是给用户方便的creator工具和Toolbox工具来生成自己的Individual。
定义List:创建包含浮点数的list型、array型或ndarray型的Individual。并且定义一个工具包。
import random
from deap import base
from deap import creator
from deap import tools
#创建一个Fitness属性
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
#创建Individual类,继承list,并具备刚创建的Fitness属性
creator.create("Individual", list, fitness=creator.FitnessMax)
#creator.create("Individual", array.array, typecode="d", fitness=creator.FitnessMax)#如果数据是array.array类型
#creator.create("Individual", numpy.ndarray, fitness=creator.FitnessMax)#如果数据是numpy.ndarray类型
IND_SIZE=10
toolbox = base.Toolbox()
#新创造attr_float别名,并将其重定向到random.random()函数。
toolbox.register("attr_float", random.random)
#新创建individual别名,并固定其container是继承creator.Individual类,其func是
#toolbox.attr_float()函数,重复次数参数IND_SIZE. 其有益结果是:运行toolbox.individual()后,
#会同时调用initRepeat(),并返回完整的creator.Individual,包含IND_SIZE个元素。
toolbox.register("individual", tools.initRepeat, creator.Individual,
toolbox.attr_float, n=IND_SIZE)
register()方法至少接受两个参数:别名、分配给此别名的函数。
或想定义另一种List?:排列(Permutaion)
toolbox.register("indices", random.sample, range(IND_SIZE), IND_SIZE)
toolbox.register("individual", tools.initIterate, creator.Individual,
toolbox.indices)
所有代码和List一样,只是最后两行改成如上。就可以得到一个permutation型。(
在Python中,List和Permutation都是序列类型,但它们之间有一些区别。
List是Python中的一种基本数据类型,它可以包含任何类型的数据,包括数字、字符串、列表等。List中的元素是有序的,并且可以通过索引进行访问。
Permutation是一个Python库itertools中的函数,用于计算给定集合中所有可能的排列方式。它可以通过Python的标准库中的itertools模块来调用。Permutation函数接受一个可迭代对象作为参数,并返回一个迭代器,该迭代器按照字典序排列给定集合的所有排列方式。
)
定义Arithmetic Expression(基本运算)包
import operator
from deap import base
from deap import creator
from deap import gp
from deap import tools
pset = gp.PrimitiveSet("MAIN", arity=1)
pset.addPrimitive(operator.add, 2)
pset.addPrimitive(operator.sub, 2)
pset.addPrimitive(operator.mul, 2)
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", gp.PrimitiveTree, fitness=creator.FitnessMin,
pset=pset)
toolbox = base.Toolbox()
toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=2)
toolbox.register("individual", tools.initIterate, creator.Individual,
toolbox.expr)
chatgpt解释:这段代码使用了Python的DEAP库来定义一个遗传算法的基本元素。具体来说,它定义了一个函数集合pset,包含了加、减、乘三种基本运算。然后,它定义了一个Individual类,用于表示一个个体,包含了一个PrimitiveTree和一个FitnessMin对象。最后,它定义了一个toolbox对象,用于注册一些工具函数,例如生成随机个体的函数。
设定Evolution Strategy
import array
import random
from deap import base
from deap import creator
from deap import tools
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", array.array, typecode="d",
fitness=creator.FitnessMin, strategy=None)
creator.create("Strategy", array.array, typecode="d")
def initES(icls, scls, size, imin, imax, smin, smax):
ind = icls(random.uniform(imin, imax) for _ in range(size))
ind.strategy = scls(random.uniform(smin, smax) for _ in range(size))
return ind
IND_SIZE = 10
MIN_VALUE, MAX_VALUE = -5., 5.
MIN_STRAT, MAX_STRAT = -1., 1.
toolbox = base.Toolbox()
toolbox.register("individual", initES, creator.Individual,
creator.Strategy, IND_SIZE, MIN_VALUE, MAX_VALUE, MIN_STRAT,
MAX_STRAT)
newbing解释:这段代码使用了Python的DEAP库来定义一个进化策略算法的基本元素。具体来说,它定义了一个Individual类,用于表示一个个体,包含了一个array和一个FitnessMin对象。然后,它定义了一个Strategy类,用于表示进化策略算法中的策略参数。最后,它定义了一个toolbox对象,用于注册一些工具函数,例如生成随机个体的函数。
此处省略Particle等部分。
设定Population(种群)
种群虽然很像个人。它不是用属性初始化的,而是用Individual、Evolution Strategy或Particle填充的。
Bag填充法:
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
Bag填充是最常用的类型。它没有特定的顺序,尽管它通常使用列表实现。由于包没有特定的属性,所以它不需要任何特殊的类。这段代码使用了Python的DEAP库来注册一个名为population的工具函数,用于生成一个随机个体列表。具体来说,它使用了initRepeat函数,将toolbox.individual作为参数,生成一个长度为N的个体列表。
toolbox.population(n=100)
上面的示例生成了一个包含100个个体的群体。
Grid填充法:
toolbox.register("row", tools.initRepeat, list, toolbox.individual, n=N_COL)
toolbox.register("population", tools.initRepeat, list, toolbox.row, n=N_ROW)
首先,我们使用了initRepeat函数,将toolbox.individual作为参数,生成一个长度为N_COL的个体列表。然后,我们再次使用initRepeat函数,将toolbox.row作为参数,生成一个长度为N_ROW的个体列表。
Swarm和Demes等种群填充法和seeding a population因为不符合MAKE原则,此处略。
三、四、Operators(操作符)和Algorithms(算法)
在开始使用复杂算法之前,我们将了解DEAP的一些基础知识。首先,我们将从创建简单的个体开始(如创建类型教程),并使它们使用不同的运算符相互交互。之后,我们将学习如何使用算法和其他工具。
第一步:创建个体 Individual
首先导入所需的模块,并注册创建具有最小化两个目标适应度的浮动列表所需的不同函数。
import random
from deap import base
from deap import creator
from deap import tools
IND_SIZE = 5
creator.create("FitnessMin", base.Fitness, weights=(-1.0, -1.0))
creator.create("Individual", list, fitness=creator.FitnessMin)
toolbox = base.Toolbox()
toolbox.register("attr_float", random.random)
toolbox.register("individual", tools.initRepeat, creator.Individual,
toolbox.attr_float, n=IND_SIZE)
现在,可以通过向脚本中添加适当的行来构建第一个个体。
ind1 = toolbox.individual()
打印个人ind1
检查它的适用性是否有效会给出类似的结果
print(ind1) # [0.86..., 0.27..., 0.70..., 0.03..., 0.87...]
print(ind1.fitness.valid) # False
个体被打印为其基类表示(这里是列表),并且适应度无效,因为它不包含值。
评估函数evaluate()
评估是进化算法中最个人化的部分,它是库中唯一必须自己编写的部分。典型的求值函数将一个个体作为参数,并将其适合度返回为tuple.如创建类型节,适应度是浮点值的列表,并具有属性valid了解是否应重新评估此人。通过设置values到相关的tuple例如,以下评估先前创建的个人ind1
并将其适合度分配给相应的值。
def evaluate(individual):
# Do some hard computing on the individual
a = sum(individual)
b = len(individual)
return a, 1. / b
ind1.fitness.values = evaluate(ind1)
print(ind1.fitness.valid) # True
print(ind1.fitness) # (2.73, 0.2)
处理单一目标适应度没有什么不同,评估函数必须返回元组,因为单目标被视为多目标的特殊情况。
突变mutation
我们将介绍的第一种算子是突变算子。deap.tools每个突变都有自己的特征,可以应用于不同类型的个体,请小心阅读文档。突变运算符的一般规则是只是突变,这意味着,突变前的个体如果还有员工,需要手动备份。为了在个体上应用突变(这里是高斯突变)ind1
,只需应用所需的函数。
mutant = toolbox.clone(ind1)
ind2, = tools.mutGaussian(mutant, mu=0.0, sigma=0.2, indpb=0.2)
del mutant.fitness.values
上述第一行代码是使用toolbox
模块中的clone()
函数创建了一个名为mutant
的个体副本。第二行代码使用了tools
模块中的mutGaussian()
函数对这个副本进行了变异。这个函数会以概率indpb
对输入个体的每个属性进行高斯变异。变异是属性值的高斯变化,其均值等于mu
,标准差等于sigma
。变异后的个体作为包含一个个体的元组返回。最后一行代码删除了变异后个体的适应度值。
交叉
我们将介绍的第二种算子是交叉运算符。deap.tools每个交叉都有自己的特点,可以应用于不同类型的个人。请小心阅读文档,挑选最合适的交叉方法。交叉运算符的一般规则是只是交配个体。
child1, child2 = [toolbox.clone(ind) for ind in (ind1, ind2)]
tools.cxBlend(child1, child2, 0.5)
del child1.fitness.values
del child2.fitness.values
上述代码中,第一行代码使用了列表推导式,将两个个体ind1
和ind2
的副本存储在名为child1
和child2
的列表中。这里使用了toolbox.clone()
函数来创建个体副本。第二行代码使用了tools.cxBlend()
函数对这两个个体进行了交叉。这个函数将两个个体的属性进行混合,生成两个新的个体。最后两行代码分别删除了新生成的两个个体的适应度值。
选择
由选择运算符在总体中进行选择,这些运算符在deap.tools模块。选择运算符通常将个人和要选择的个人数量的可迭代容器作为第一个参数。它返回一个列表,其中包含对选定个人的引用。选择如下:
selected = tools.selBest([child1, child2], 2)
print(child1 in selected) # True
是的非常这里需要注意的是,在选择过程中,选择运算符不会复制任何个体。如果一个个体被选择两次,并且其中一个对象被修改,另一个对象也将被修改。仅复制对个人的引用。就像它选择的其他运算符一样,它只选择。
通常,整个群体的复制将在选择后或变异前进行。
selected = toolbox.select(population, LAMBDA)
offspring = [toolbox.clone(ind) for ind in selected]
第一行代码使用了toolbox.select()
函数从种群中选择一些个体,并将它们存储在名为selected
的列表中。这里的population
是一个包含多个个体的列表,LAMBDA
是一个整数,表示要选择的个体数量。第二行代码使用了列表推导式,将selected
列表中的每个个体的副本存储在名为offspring
的列表中。