遗传算法(GA)的原理简介与应用【python实现】
遗传算法(GA)的原理简介与应用【python实现】
- 算法原理简介与实现
- 算法框架
- 关于GA求解过程中一些结果的讨论
- SA-GA总结与体会
算法原理简介与实现
遗传算法(Genetic Algorithm,GA)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。
遗传算法是从代表问题可能潜在的解集的一个种群(population)开始的,而一个种群则由经过基因(gene)编码的一定数目的个体组成。每个个体实际上是染色体(chromosome)带有特征的实体。染色体作为遗传物质的主要载体,即多个基因的集合,其内部表现(即基因型)是某种基因组合,它决定了个体的形状的外部表现,如黑头发的特征是由染色体中控制这一特征的某种基因组合决定的。因此,在一开始需要实现从表现型到基因型的映射即编码工作。由于仿照基因编码的工作很复杂,我们往往进行简化,如二进制编码,初代种群产生之后,按照适者生存和优胜劣汰的原理,逐代(generation)演化产生出越来越好的近似解,在每一代,根据问题域中个体的适应度(fitness)大小选择(selection)个体,并借助于自然遗传学的遗传算子(genetic operators)进行组合交叉(crossover)和变异(mutation),产生出代表新的解集的种群。这个过程将导致种群像自然进化一样的后生代种群比前代更加适应于环境,末代种群中的最优个体经过解码(decoding),可以作为问题近似最优解。
下面通过求解与上一篇文章(点击可跳转)相同的一个问题来进一步说明算法介绍和实现过程:
算法框架
- 确定编码与解码方式。常见的编码方式有二进制编码、整数编码、顺序编码等,具体的编码方式的选择需要根据需要解决的问题来选择。
采用顺序编码时,需要注意的是合法性问题,即编码是否符合实际,例如在TSP问题中,采用顺序编码在交叉变异时可能会出现重复走到一个城市的情形,这种情况即为不合法。针对这种情况在交叉方式上有相应的研究,在222中有说明。
在本题中,采用二进制编码的方式。为了保证编码后对应的数值在可行域范围内,采取了编码后再进行一步线性变换的操作。
编码方式 | 适用问题 |
---|---|
二进制编码 | 背包问题、函数优化问题、指派问题 |
整数编码 | 时间优化问题 |
顺序编码 | 指派、旅行商(TSP)问题,调度问题 |
交叉变异的方式交叉和变异能够保证种群的多样性。交叉是指一对父代个体之间染色体进行交叉,交叉率通常设为0.8-0.9,用pc表示。对于二进制及整数编码,交叉方式有单切点交叉、双切点交叉、均匀交叉;对于顺序编码,有部分映射交叉、顺序交叉和循环交叉,这些方式可保证交叉的合法性。
变异是指染色体上的基因发生突变,在生物群体中发生概率较小,因此变异率设定在0.05一下,用pm表示。对于二进制及整数编码,变异方式为位变异;对于顺序编码,变异方式有插入、交换、翻转。进行适应度的计算与标定。一般来说,适应度可以以所求目标函数值作为参考,对目标函数值域的某种映射变换称为适应度标定。适应度标定很重要,直接影响算法收敛速度以及是否可以找到最优解。下面介绍两种常用标定方法。
线性标定:F=af+bF=af+bF=af+b,FFF为适值函数,fff为目标函数。对于maxf(x)maxf(x)maxf(x),则F=f−fmin+ξF=f-f_{min}+\xiF=f−fmin+ξ;对于minf(x)minf(x)minf(x),则F=−f+fmax+ξF=-f+f_{max}+\xiF=−f+fmax+ξ。
动态线性标定:F=akf+bkF=a^kf+b^kF=akf+bk,kkk为迭代次数,FFF为适值函数,fff为目标函数。对于maxf(x)maxf(x)maxf(x),则F=f−fmink+ξkF=f-f_{min}^k+\xi^kF=f−fmink+ξk;对于minf(x)minf(x)minf(x),则F=−f+fmaxk+ξkF=-f+f_{max}^k+\xi^kF=−f+fmaxk+ξk。其中ξ0=0\xi^0=0ξ0=0,ξk=ξk−1∗r\xi^k=\xi^{k-1}*rξk=ξk−1∗r,r∈[0.9,0.999]r\in[0.9,0.999]r∈[0.9,0.999]。关于ξk\xi^kξk,可以认为ξk\xi^kξk的加入使得使最坏个体仍有繁殖的可能,它的值随kkk的增大而减小,更加符合自然界的规律。
- 确定选择策略,优胜劣汰。基本思想是:各个个体被选中的概率与其适应度大小成正比。常用的选择方法有轮盘赌选择法、随即遍历抽样法和精英保留策略。
轮盘赌和随机遍历抽样有相似的地方,这两种方法都需要将个体的适应度归一化到[0,1]区间内,在这里做一下区分:
轮盘赌,顾名思义是通过转盘,随机选取个体,即指针落到某一个个体对应的累积适应度区间内,即选择该个体。这可以通过生成[0,1)伪随机数,然后找到该伪随机数的对应区间,即可确定选择的个体。
随机遍历抽样是假定有nnn个需要选择的个体,那么选择个体的指针就有nnn个,指针之间的距离为1n\frac{1}{n}n1,第一个指针在[0,1n\frac{1}{n}n1]随机确定。本题采用了轮盘赌的选择策略。
- 开始进化。
关于GA求解过程中一些结果的讨论
在求解这个问题时发现,每一次的运行结果不同,但是发现有一次的结果比Matlab求解的结果更小,一度怀疑哪个地方出错了。在了解了Matlab求解方法后发现,其实Matlab的结果也并不是遍历可行域得出来的结果,而是以一定的步长求解,例如如果图像在某一点处有一个尖峰,但是Matlab遍历时并没有看到这一点,这就有可能会漏掉某些更小的解。所以Matlab的结果也不能百分百作为标准,只能当作一种参考。同时在求解时也应当有一定的“自信”:关于一个问题,如果目标函数和约束条件没有写错,利用GA,SA等优化算法,求出来的解肯定会在可行域内且在函数上,这些启发式算法并不会凭空产生一个不在函数上的解。
SA-GA总结与体会
求解方法 | 最优点 | 函数值 |
---|---|---|
Matlab求解 | (−1.62,3.04),(−1.62,−3.04)(-1.62,3.04),(-1.62,-3.04)(−1.62,3.04),(−1.62,−3.04) | 41.3205 |
模拟退火(SA) | (−1.5449,−3.1257)(-1.5449,-3.1257)(−1.5449,−3.1257) | 41.3472 |
遗传算法(GA) | (−1.569,−3.104)(-1.569,-3.104)(−1.569,−3.104) | 41.334 |
模拟退火中关键的地方有初温、末温、内层循环遍历次数以及温度变化控制参数,当然,那些产生新解的邻域操作也很重要。其中初温、末温、内层循环遍历次数、温度变化参控制数应该与要解答的问题的规模有关。要注意的是,\textbf{SA中温度并不用于产生新解,只是用于决定是否该接受较差的新解,而GA告诉我们的就是如何去产生新解。}而且GA的灵感都来自大自然,无论是交叉还是变异亦或是选择过程都充满了哲理,其实大部分现代优化算法的理念都是靠近自然。
python实现的GA代码如下:
import random
import math
import numpy as np
import matplotlib.pyplot as pltpopulation_size = 50 #种群大小
generation = 200 #代数
code_len = 10 #二进制编码长度
pc = 0.6 # 交配概率
pm = 0.01 # 变异概率
gene_population_1 = [] #种群的基因库
decode_value_1 = [] #解码后的变量
gene_population_2 = [] #种群的基因库
decode_value_2 = [] #解码后的变量
fitness = [] #函数值(原始适应值)
fitness_standard = [] #标定后适应值
select_possibility = []
sum_pob = []
random_selection = []
def encode(gene_population):for i in range(population_size):gene = []for j in range(code_len):gene.append(random.randint(0,1))gene_population.append(gene)#print(gene_population)def decode(gene_population,decode_value):decode_value.clear()for i in range(population_size):value = 0for j in range(code_len):value = value + gene_population[i][j] * (2 ** (code_len - 1 - j))value = value * 10 / (2 ** (code_len) - 1) - 5decode_value.append(value)
#适应值的处理可以再考虑一下
def fitness_process(decode_value_1,decode_value_2):fitness.clear()fitness_standard.clear()sum_fitness = 0for i in range(population_size):#function = - (decode_value_1[i] - 1)**2- (decode_value_2[i] - 1)**2 + 1 #测试function = -(6*decode_value_1[i]/(2 + decode_value_1[i] ** 2 + decode_value_2[i] ** 2) + 5*math.sin(decode_value_1[i]) +3*math.cos(decode_value_2[i]) + 50)fitness.append(function)fitness_standard.append(function)#找最小值min_fitness = fitness[0]#min_id = 0for k in range(population_size):if (min_fitness > fitness[k]):min_fitness = fitness[k]#min_id = k #适应值修正————线性标定zeta = 2#tao = 0.95for m in range(population_size):fitness_standard[m] = fitness[m] - min_fitness + zeta#zeta = zeta ** (tao)#找最大值max_fitness = fitness_standard[0]max_id = 0for j in range(population_size):sum_fitness = sum_fitness + fitness_standard[j]if (max_fitness < fitness_standard[j]):max_fitness = fitness_standard[j]max_id = jreturn (sum_fitness,max_id)def roulette_select(sum_fitness,gene_population):sum_pob.clear()random_selection.clear()for i in range (population_size):possibility = fitness_standard[i]/sum_fitnessselect_possibility.append(possibility)pob = 0for i in range(population_size):pob = pob + select_possibility[i]sum_pob.append(pob)sum_pob[-1]=1for i in range(population_size):random_selection.append(random.random())#random_selection.sort()gene_population_new = []#random_selection_id = 0
# for i in range(population_size):
# while(( random_selection_id < population_size) and (random_selection[random_selection_id] < sum_pob[i])):
# gene_population_new.append(gene_population[i])
# random_selection_id += 1#轮盘赌for i in range(population_size):for j in range(population_size):if((random_selection[i]>sum_pob[j])and(random_selection[i]<=sum_pob[j + 1])):gene_population_new.append(gene_population[j + 1]) gene_population = gene_population_new# 进行基因的变异
def mutation(gene_population):for i in range(population_size):if random.random() < pm:mutation_point = random.randint(0, code_len - 1)if gene_population[i][mutation_point] == 0:gene_population[i][mutation_point] = 1else:gene_population[i][mutation_point] = 0# 进行交配过程
def crossover(gene_population):for i in range(0, population_size - 1, 2):if random.random() < pc:# 随机选择交叉点change_point = random.randint(0, code_len - 1)temp1 = []temp2 = []temp1.extend(gene_population[i][0: change_point])temp1.extend(gene_population[i+1][change_point:])temp2.extend(gene_population[i+1][0: change_point])temp2.extend(gene_population[i][change_point:])gene_population[i] = temp1gene_population[i+1] = temp2#开始进化
best_fitness_all = []
best_fitness_all.append(0)encode(gene_population_1)
encode(gene_population_2)
for i in range(generation):decode(gene_population_1,decode_value_1)decode(gene_population_2,decode_value_2)sum_fitness,max_id = fitness_process(decode_value_1,decode_value_2)best_fitness_all.append(-fitness[max_id])roulette_select(sum_fitness,gene_population_1)roulette_select(sum_fitness,gene_population_2)crossover(gene_population_1)mutation(gene_population_1)crossover(gene_population_2)mutation(gene_population_2)
print('(x1,x2)为(%s,%s),最小值为%s'%(decode_value_1[max_id],decode_value_2[max_id],-fitness[max_id])) plt.plot(range(1, len(best_fitness_all)+1), best_fitness_all)
plt.xlabel('最优解更新次数',fontproperties='SimHei')
plt.ylabel('每一代的最优解', fontproperties='SimHei')
plt.show()
遗传算法(GA)的原理简介与应用【python实现】相关推荐
- 基于遗传算法GA算法优化BP神经网络(Python代码实现)
一. 概述 BP-GA算法的设计︰基于遗传算法的BP神经网络算法(以下简称BP-GA)就是在BP神经网络的学习过程中,将权重和阀值描述为染色体,并选取适宜的适应函数,然后进行GA迭代,直到某种意义上的 ...
- 【优化算法】 简述遗传算法(GA)原理
[优化算法]简述遗传算法(GA)原理 [优化算法]简述灰狼优化算法(GWO)原理 前言 遗传算法GA(Genetic algorithm)由美国密西根大学 J. Holland 教授于90年代提出来的 ...
- 【python】psnr原理简介及代码实现
写在前面 psnr作为图像质量评价指标,在很多图像领域如图像超分辨率.图像压缩.图像去噪等都有广泛的应用. PSNR(峰值信噪比) 简介 Peak signal-to-noise ratio(简称PS ...
- Pymoo:遗传算法原理简介及Pymoo中遗传算子的实现示例
Pymoo:遗传算法原理简介及Pymoo中遗传算子的实现示例 一.遗传算法原理简介 二.Pymoo中的遗传算子(Genetic Operators)及其实现 2.1 抽样算子(Sampling Ope ...
- 遗传算法与爬山算法简介_遗传算法简介
遗传算法与爬山算法简介 Genetic Algorithms (GAs) are a part of Evolutionary Computing (EC), which is a rapidly g ...
- DeepLearning tutorial(1)Softmax回归原理简介+代码详解
FROM: http://blog.csdn.net/u012162613/article/details/43157801 DeepLearning tutorial(1)Softmax回归原理简介 ...
- DeepLearning tutorial(3)MLP多层感知机原理简介+代码详解
FROM:http://blog.csdn.net/u012162613/article/details/43221829 @author:wepon @blog:http://blog.csdn.n ...
- DeepLearning tutorial(4)CNN卷积神经网络原理简介+代码详解
FROM: http://blog.csdn.net/u012162613/article/details/43225445 DeepLearning tutorial(4)CNN卷积神经网络原理简介 ...
- 【数据挖掘】遗传算法原理浅析:什么是遗传算法?遗传算法的工作原理是什么?
文章目录 1.基础知识 1.1 生物学背景 1.2 进化算法 1.2.1 概念 1.2.2 进化计算关键概念 1.2.3 进化计算的求解过程 1.2.4 应用举例 2.遗传算法是什么 2.1 定义 2 ...
最新文章
- Unity3D Mecanim 动画系统骨骼动画问题解决方法
- [LeetCode] Binary Tree Postorder Traversal 二叉树的后序遍历
- 读史以明志,把握好自己的明天
- 学习“用dlopen,dlsym加载动态链接库.so中函数”之摘录
- User Mode Driver Management介绍(一)
- LeetCode 486. 预测赢家(博弈DP)
- 反思 大班 快乐的机器人_幼儿园大班健康教案《有趣的椅子》含反思
- 【jmeter安装】jmeter下载安装超详细简单步骤
- java 生成er图标_设计数据库 ER 图太麻烦?不妨试试这两款工具,自动生成数据库 ER 图!!!...
- arcgis 经纬度转大地坐标_深入理解ArcGIS的地理坐标系、大地坐标系
- 个人信息安全规范----6、个人信息的委托处理、共享、转让、公开披露
- 【密码学/密码分析】基于TMTO的密码分析方法
- Heading/Pitch/Roll与Omega/Phi/Kappa简单介绍
- Vue中使用clipboard实现复制功能
- 服务器远程管理简介(ILO,BMC,RSA)
- 联发科八核芯片MT6599 起步赢高通,辉达NVIDIA
- android+video+自动播放源码,华为手机浏览器使用Video.js无法自动播放
- 中英文翻译功能 php,PHP微信开发之翻译功能
- 接口保护ESD防静电二极管选择ESDSRVLC05-4
- MySQL事务特性及实现原理