基于DEAP库的python进化算法--遗传算法实践--配词问题
文章目录
- 一.前言
- 二.配词问题
- 1.问题描述
- 2.评价方式一 - ASCII码差异
- 2.评价方式二 -- 与原文相同的字符个数
- 小结
一.前言
在非线性函数寻优中,我们看到了编码方式对问题求解的重要性,但是遗传算法的评价函数的设定也对求解有至关重要的作用。如果设定的评价函数不好,可能导致算法无法正确收敛。
二.配词问题
1.问题描述
配词问题(word matching problem)是给定某字符串,以生成同样字符串为目的的问题。
例如对目标短语’to be or not to be’,要求用遗传算法生成该短语。
这里最简单直接的个体编码方式是采用13个ASCII码进行编码(当然用字符编码也是可以的,这里因为探讨的主要问题在于评价函数的选择,因此,不对编码方式做过多探索)。
考虑评价函数时,有两种评价思路:
- 第一种思路:是将目标函数设定为与给定的字符串的ASCII码差异,此时,配词问题转化为一个目标函数最小化问题。
- 第二种思路:是将目标函数设定与原文相同的字符个数,此时,配图问题转化为一个目标函数最大化问题。
2.评价方式一 - ASCII码差异
遗传算法操作:
- 个体编码:使用ASCII码数字编码,长度为13
- 评价函数:与给定的字符串的ASCII码差异的绝对值之和
- 育种选择:锦标赛选择
- 变异算法:交叉-均匀交叉,变异-乱序突变
- 环境选择:精英保留策略
代码实现
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author: liujie
@software: PyCharm
@file: ASCII差异.py
@time: 2020/11/28 19:36
"""
import numpy as np
import random
import matplotlib.pyplot as plt
from deap import creator,tools,base,algorithms# 定义问题
creator.create('FitnessMin',base.Fitness,weights=(-1.0,))
creator.create('Individual',list,fitness = creator.FitnessMin)# 个体编码-ASCII编码
gen_size = 13
toolbox = base.Toolbox()
# 小写字母“a”到“z”的ASCII码值分别为97到到122
toolbox.register('genASCII',random.randint,97,122)
toolbox.register('Individual',tools.initRepeat,creator.Individual,toolbox.genASCII,n = gen_size)
# 注册种群
toolbox.register('Population',tools.initRepeat,list,toolbox.Individual)# 评价函数-与给定的字符串的ASCII码差异之和
def eval(ind):target = list('tobeornottobe')# ord返回对应ASCII字符串的ASCII数值target = [ord(item) for item in target]return np.sum(np.abs(np.array(ind) - np.array(target))),# 注册评价函数
toolbox.register('evaluate',eval)
# 注册遗传算法的操作:选择、交叉、突变
toolbox.register('select',tools.selTournament,tournsize = 2)
toolbox.register('mate',tools.cxUniform,indpb=0.5)
toolbox.register('mutate',tools.mutShuffleIndexes,indpb = 0.3)# 创建统计学对象
stats = tools.Statistics(key= lambda ind : ind.fitness.values)
stats.register('avg',np.mean)
stats.register('std',np.std)
stats.register('min',np.min)
stats.register('max',np.max)
# 创建日志对象
logbook = tools.Logbook()
logbook.header = 'gen','avg','std','min','max'# 遗传算法
pop_size = 100
N_GEN = 50
CXPB = 0.8
MUTPB = 0.2# 生成种群
pop = toolbox.Population(n = pop_size)# 评价初代种群
invalid_ind = [ind for ind in pop if not ind.fitness.valid]
fitnesses = list(map(toolbox.evaluate,invalid_ind))
for ind,fit in zip(pop,fitnesses):ind.fitness.values = fit
record = stats.compile(pop)
logbook.record(gen = 0,**record)# 遗传算法迭代
for gen in range(1+N_GEN):# 配重选择selectTour = toolbox.select(pop,pop_size)# 复制selectInd = list(map(toolbox.clone,selectTour))# selectInd = [toolbox.clone(_) for _ in selectTour]# 交叉for child1,child2 in zip(selectInd[::2],selectInd[1::2]):if random.random() < CXPB:toolbox.mate(child1,child2)del child1.fitness.valuesdel child2.fitness.values# 变异for ind in selectInd:if random.random() < MUTPB:toolbox.mutate(ind)del ind.fitness.values# 对于被改变的个体,更改其适应度invalid_ind = [ind for ind in selectInd if not ind.fitness.valid]fitnesses = list(map(toolbox.evaluate,invalid_ind))for ind,fit in zip(invalid_ind,fitnesses):ind.fitness.values = fit# 精英育种策略combinedPop = pop + selectIndpop = tools.selBest(combinedPop,pop_size)# 将统计对象应用于poprecord = stats.compile(pop)logbook.record(gen = gen,**record)# 打印迭代过程
print(logbook)
# 输出结果
bestInd = tools.selBest(pop,1)[0]
bestFit = bestInd.fitness.values[0]
print('最优解为:',str(bestInd))
print('对应的函数最小值为:',str(bestFit))# 可视化
gen = logbook.select('gen')
min = logbook.select('min')
avg = logbook.select('avg')
plt.plot(gen,min,'b-',label = 'MIN_FITNESS')
plt.plot(gen,avg,'r-',label = 'AVG_FITNESS')
plt.xlabel('gen')
plt.plot('fit')
plt.legend(loc = 'upper right')
plt.show()
运行结果
gen avg std min max
0 105.15 18.9644 52 143
0 86.53 11.1234 52 100
1 73.83 10.1154 43 87
2 63.96 7.74328 43 73
3 54.72 7.76155 24 64
4 46.73 7.13282 23 55
5 39.71 6.63369 21 48
6 32.72 5.20208 19 40
7 27.53 3.71606 19 32
8 23.44 3.0243 14 28
9 19.97 3.07394 11 24
10 16.56 2.63939 9 21
11 13.7 2.52784 5 17
12 10.89 2.61494 4 14
13 8.3 2.35584 3 11
14 5.68 1.55486 2 8
15 3.83 1.12299 1 5
16 2.71 0.919728 0 4
17 1.77 0.580603 0 3
18 1.27 0.690724 0 2
19 0.64 0.48 0 1
20 0.23 0.420833 0 1
21 0 0 0 0
22 0 0 0 0
23 0 0 0 0
24 0 0 0 0
25 0 0 0 0
26 0 0 0 0
27 0 0 0 0
...
194 0 0 0 0
195 0 0 0 0
196 0 0 0 0
197 0 0 0 0
198 0 0 0 0
199 0 0 0 0
200 0 0 0 0
最优解为: ['t', 'o', 'b', 'e', 'o', 'r', 'n', 'o', 't', 't', 'o', 'b', 'e']
对应的函数最小值为: 0.0
可视化
2.评价方式二 – 与原文相同的字符个数
遗传算法操作
- 个体编码:使用ASCII编码,长度为13
- 评价函数:与原文相同的字符个数
- 育种选择:锦标赛选择
- 变异算法:交叉-均匀交叉,变异-乱序突变
- 环境选择:精英保留策略
代码实现
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author: liujie
@software: PyCharm
@file: ASCII差异.py
@time: 2020/11/28 19:36
"""
import numpy as np
import random
import matplotlib.pyplot as plt
from deap import creator,tools,base,algorithms# 定义问题
creator.create('FitnessMax',base.Fitness,weights=(1.0,))
creator.create('Individual',list,fitness = creator.FitnessMax)# 个体编码-ASCII编码
gen_size = 13
toolbox = base.Toolbox()
# 小写字母“a”到“z”的ASCII码值分别为97到到122
toolbox.register('genASCII',random.randint,97,122)
toolbox.register('Individual',tools.initRepeat,creator.Individual,toolbox.genASCII,n = gen_size)
# 注册种群
toolbox.register('Population',tools.initRepeat,list,toolbox.Individual)# 评价函数-生成的字符串与目标字符串相同的个数
def eval(ind):target = list('tobeornottobe')# ord返回对应ASCII字符串的ASCII数值target = [ord(item) for item in target]return np.sum(np.array(ind) == np.array(target)),# 注册评价函数
toolbox.register('evaluate',eval)
# 注册遗传算法的操作:选择、交叉、突变
toolbox.register('select',tools.selTournament,tournsize = 2)
toolbox.register('mate',tools.cxUniform,indpb=0.5)
toolbox.register('mutate',tools.mutShuffleIndexes,indpb = 0.5)# 创建统计学对象
stats = tools.Statistics(key= lambda ind : ind.fitness.values)
stats.register('avg',np.mean)
stats.register('std',np.std)
stats.register('min',np.min)
stats.register('max',np.max)
# 创建日志对象
logbook = tools.Logbook()
logbook.header = 'gen','avg','std','min','max'# 遗传算法
pop_size = 100
N_GEN = 200
CXPB = 0.8
MUTPB = 0.2# 生成种群
pop = toolbox.Population(n = pop_size)# 评价初代种群
invalid_ind = [ind for ind in pop if not ind.fitness.valid]
fitnesses = list(map(toolbox.evaluate,invalid_ind))
for ind,fit in zip(pop,fitnesses):ind.fitness.values = fit
record = stats.compile(pop)
logbook.record(gen = 0,**record)# 遗传算法迭代
for gen in range(1+N_GEN):# 配重选择selectTour = toolbox.select(pop,pop_size)# 复制selectInd = list(map(toolbox.clone,selectTour))# selectInd = [toolbox.clone(_) for _ in selectTour]# 交叉for child1,child2 in zip(selectInd[::2],selectInd[1::2]):if random.random() < CXPB:toolbox.mate(child1,child2)del child1.fitness.valuesdel child2.fitness.values# 变异for ind in selectInd:if random.random() < MUTPB:toolbox.mutate(ind)del ind.fitness.values# 对于被改变的个体,更改其适应度invalid_ind = [ind for ind in selectInd if not ind.fitness.valid]fitnesses = list(map(toolbox.evaluate,invalid_ind))for ind,fit in zip(invalid_ind,fitnesses):ind.fitness.values = fit# 精英育种策略combinedPop = pop + selectIndpop = tools.selBest(combinedPop,pop_size)# 将统计对象应用于poprecord = stats.compile(pop)logbook.record(gen = gen,**record)# 打印迭代过程
print(logbook)
# 输出结果
bestInd = tools.selBest(pop,1)[0]
bestFit = bestInd.fitness.values[0]
bestIndII = []
for each in bestInd:bestI = chr(each)bestIndII.append(bestI)
print('最优解为:',str(bestIndII))
print('对应的函数最小值为:',str(bestFit))# 可视化
gen = logbook.select('gen')
min = logbook.select('min')
avg = logbook.select('avg')
plt.plot(gen,min,'b-',label = 'MIN_FITNESS')
plt.plot(gen,avg,'r-',label = 'AVG_FITNESS')
plt.xlabel('gen')
plt.plot('fit')
plt.legend(loc = 'upper right')
plt.show()
运行结果
gen avg std min max
0 0.51 0.699929 0 3
0 1.26 0.687314 0 3
1 1.94 0.71861 1 4
2 2.59 0.664756 2 5
3 3.4 0.565685 3 5
4 3.98 0.599667 3 6
5 4.58 0.750733 4 7
6 5.55 0.71239 5 8
7 6.36 0.793977 5 9
8 7.22 0.944246 6 10
9 8.15 0.84113 7 11
10 9.03 0.754387 8 12
11 9.77 0.810617 9 12
12 10.53 0.623779 10 12
13 11.2 0.489898 10 12
14 11.62 0.485386 11 12
15 12 0 12 12
16 12 0 12 12
17 12 0 12 12
18 12 0 12 12
19 12 0 12 12
...
194 12 0 12 12
195 12 0 12 12
196 12 0 12 12
197 12 0 12 12
198 12 0 12 12
199 12 0 12 12
200 12 0 12 12
最优解为: ['t', 'o', 'b', 'e', 'o', 'r', 'n', 'o', 't', 'f', 'o', 'b', 'e']
可视化
小结
- 这里给出的评价方法一的结果是多次运行后的一个较优解:[‘t’, ‘o’, ‘b’, ‘f’, ‘o’, ‘q’, ‘n’, ‘p’,
‘t’, ‘t’, ‘o’, ‘b’, ‘e’],它显然并非全局最优解 — 并没有能完全复现我们的目标; - 评价方法二的结果是多次运行中随便取了一次结果 — 它每次都能以很快的速度收敛到最优解。
- 两个程序的差别仅仅在于更换了评价函数,别的遗传算法操作完全相同,可以看到评价函数选择对于遗传算法设计的重要性。
基于DEAP库的python进化算法--遗传算法实践--配词问题相关推荐
- 遗传算法 python 简书_基于DEAP库的Python进化算法从入门到入土—(二)简单遗传算法实现...
前言 在上一篇中,我们已经介绍了如何在DEAP中实现进化算法的基本操作,在这一篇中我们试图将各个操作组装起来,用进化算法解决一个简单的一元函数寻优问题. 进化算法实例 - 一元函数寻优 问题描述与分析 ...
- python路线寻优_基于DEAP库的Python进化算法从入门到入土 --(四)遗传算法的改进...
前言 前面一节我们尝试了用GA求解TSP问题,简单遗传算法总是不能很好收敛到一个较优的解,在用时和求解精度上都被贪心算法吊打.在末尾我们总结了三个可能的改进方向,这次我们想要沿着这三个方向试着改进简单 ...
- 基于DEAP库的Python进化算法
https://www.jianshu.com/p/8fa044ed9267 http://geatpy.com/index.php/category/geatpy_tutorials/
- 基于Pyinstaller库将Python项目包括 图片打包exe方法,本人已经实践多次
基于Pyinstaller库将Python项目包括 图片打包exe方法,本人已经实践多次 文章目录 基于Pyinstaller库将Python项目包括 图片打包exe方法,本人已经实践多次 一.前言 ...
- IGD+-EMOA:基于IGD+的多目标进化算法
IGD±EMOA:基于IGD+的多目标进化算法 参考文献 <IGD±EMOA:A Multi-Objective Evolutionary Algorithm based on IGD+> ...
- MaOEA-IBP:带有边界保护的基于指标的多目标进化算法
MaOEA-IBP:带有边界保护的基于指标的多目标进化算法 参考文献 <An Indicator-Based Many-Objective Evolutionary Algorithm With ...
- 【图像压缩】基于matlab香农熵和差分进化算法多级图像阈值图像压缩【含Matlab源码 2035期】
一.差分进化算法简介 1 前言 在遗传.选择和变异的作用下,自然界生物体优胜劣汰,不断由低级向高级进化和发展.人们注意到,适者生存的进化规律可以模式化,从而构成一些优化算法:近年来发展的进化计算类算法 ...
- 进化算法--遗传算法
遗传算法 一.能解决的问题 如果你需要解决一个问题,这个问题的每一个可能的解均可以用位串来表示,那么遗传算法就能解决这个问题. 二.术语 个体:每一个可能的解: 种群:一群个体: 基因:个体中位的一个 ...
- 新手题库-《Python语言程序设计》实践6
选择题 1. 关于Python的分支结构,以下选项中描述错误的是 [ 正确答案: B] A Python中if-elif-else语句描述多分支结构 B 分支结构可以向已经执行过的语句部分跳转 C P ...
- Python遗传算法库和进化算法框架(二)Geatpy库函数和数据结构
(转载自https://blog.csdn.net/qq_33353186/article/details/82020507) 上一篇讲了Geatpy的快速入门:https://blog.csdn.n ...
最新文章
- win10连接计算机,如何在win10中连接计算机和打印机
- .net core 微服务_.NET 微服务实战之负载均衡(上)
- mvn -U clean eclipse:clean eclipse:eclipse
- 国外经典!架构师必备:《MongoDB实战》第2版
- SQL Server中的快照隔离
- 原生mysql启动_单实例MySQL的启动和关闭的方法
- 关于使用jacob出现的异常
- 21、OSPF配置实验之特殊区域totally stub
- 计算机科学自考本科的科目,自考本科计算机专业考哪些
- DSP中EALLOW,EDIS,EINT,DINT,ERTM,DRTM的作用
- python获取今日头条搜索信息_python 爬取今日头条关键词搜索
- 每天学命令deleteRow
- svchost.exe占网速解决方法
- php 图片印章_php版圆形印章生成器
- Soft-NMS – Improving Object Detection With One Line of Code
- 用户输入自己的【姓名 年龄 爱好】 + 加CP【姓名 年龄 爱好】,点击按钮,页面显示该用户的信息 点击提交按钮,JSON显示用户信息+副本信息(副本初始值是{})
- 罗马数字和阿拉伯数字之间的转换
- 微信小程序自定义底部弹窗
- 国产芯片---带使能端、轨到轨的运算放大器MS8093
- nslookup type值_Nslookup命令及常见参数 - 里维斯社
热门文章
- 【COCOS2D-HTML5 开发之三】演示样例项目附源代码及执行的GIF效果图
- SharePoint 2013 中的新增功能(与开发有关)
- poj 1251 Jungle Roads
- Exchange 2003 和 Exchange 2007最大处理器数、内存支持比较
- 20190814 On Java8 第四章 运算符
- 第一章:Chrome 43 配置 java + selenium 环境
- 用Python自动发送邮件
- SharePoint 2007 在Windows Server 2008上列表Open with Windows Explorer失效 解决
- LC-779 语法中的第k个字符
- 五款app原型设计工具对比