遗传算法简介

遗传算法(Genetic Algorithm,GA)最早是由美国的 John holland于20世纪70年代提出,该算法是根据大自然中生物体进化规律而设计提出的。是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。该算法通过数学的方式,利用计算机仿真运算,将问题的求解过程转换成类似生物进化中的染色体基因的交叉、变异等过程。在求解较为复杂的组合优化问题时,相对一些常规的优化算法,通常能够较快地获得较好的优化结果

达尔文进化论的原理概括总结如下:

  1. 变异:种群中单个样本的特征(性状,属性)可能会有所不同,这导致了样本彼此之间有一定程度的差异
  2. 遗传:某些特征可以遗传给其后代。导致后代与双亲样本具有一定程度的相似性
  3. 选择:种群通常在给定的环境中争夺资源。更适应环境的个体在生存方面更具优势,因此会产生更多的后代

遗传算法的基本概念

由于遗传算法是由进化论和遗传学机理而产生的搜索算法,所以在这个算法中会用到一些生物遗传学知识,下面是我们将会用一些术语:

由于遗传算法是由进化论和遗传学机理而产生的搜索算法,所以在这个算法中会用到一些生物遗传学知识,下面是我们将会用一些术语:

  • 基因型 (Genotype) :在自然界中,通过基因型表征繁殖,繁殖和突变,基因型是组成染色体的一组基因的集合。
  • 种群 (Population): 可行解域,根据适应度函数选择的一组解
  • 染色体(Chromosome): 对每个可行解的编码
  • 变异(Mutation): 突变操作的目的是定期随机更新种群,将新模式引入染色体,并鼓励在解空间的未知区域中进行搜索。
  • 选择 (Selection): 保留适应度函数的函数值优的解
  • 交叉 (CrossOver): 将两个可行解内的组分随机交叉,产生新解
  • 适应性(Fitness): 适应度函数的函数值

算法流程图

python实践

我们来考虑下面这个优化问题,求解
f(x)=x2∗sin(5πx)+2f(x) = x^2 * sin(5 \pi x) + 2f(x)=x2∗sin(5πx)+2
在区间[-2, 2]上的最大值。很多单点优化的方法(梯度下降等)就不适合,可能会陷入局部最优的情况,这种情况下就可以用遗传算法(Genetic Algorithm。

问题定义

import numpy as np
import pandas as pd
import matplotlib.pyplot as pltdef f(x):return x**2 * np.sin(5*np.pi*x) + 2x = np.linspace(-2, 2, 100)
plt.plot(x, f(x))

初始化原始种群

遗传算法可以同时优化一批解 (种群), 我们在[-2, 2]的区间内随机生成10个点作为我们的初始种群

np.random.seed(0)def init_population(size):return np.random.uniform(low=-2, high=2, size=size) population = init_population(10)plt.plot(x, f(x))
plt.plot(population, f(population), '*')
plt.show()

染色体编码和解码

解空间中的解在遗传算法中的表示形式。从问题的解(solution)到基因型的映射称为编码,即把一个问题的可行解从其解空间转换到遗传算法的搜索空间的转换方法。遗传算法在进行搜索之前先将解空间的解表示成遗传算法的基因型串(也就是染色体)结构数据,这些串结构数据的不同组合就构成了不同的点。

常见的编码方法有二进制编码、格雷码编码、 浮点数编码、各参数级联编码、多参数交叉编码等。

简单起见,我们使用二进制编码。为了能编码浮点数,需要扩大倍数转成整数。

def encode(population, scale=1e4, _min=-2, bin_len=15):  _scaled_population = (population - _min) * scalechroms = np.array([np.binary_repr(x, width=bin_len) for x in _scaled_population.astype(int)])return chromsdef decode(chroms, _min=-2, scale=1e4):res = np.array([(int(x, base=2)/scale) for x in chroms])res += _minreturn resfitness = f(population)
chroms = encode(population)
print(population)
print(decode(encode(population)))
print(fitness)>>>
[ 0.1953  0.8608  0.4111  0.1795 -0.3054  0.5836 -0.2497  1.5671  1.8547  -0.4662]
[ 0.1953  0.8608  0.4111  0.1795 -0.3054  0.5836 -0.2497  1.5671  1.8547  -0.4662]
[ 2.00281338  2.60488832  2.02931805  2.01019697  2.09293383  2.0867721
2.04387992  0.78660371 -0.60517298  1.81257758]

选择

选择操作从旧群体中以一定概率选择优良个体组成新的种群,以繁殖得到下一代个体。个体被选中的概率跟适应度值有关,个体适应度值越高,被选中的概率越大,常用的选择算法为轮盘赌算法。若种群数位MMM, 个体iii的适应度为fif_ifi​,则个体iii被选中的概率为:
pi=fi∑k=1Mfkp_i = \frac{f_i}{\sum_{k=1}^Mf_k}pi​=∑k=1M​fk​fi​​
当个体选择的概率给定后,产生[0,1]之间均匀随机数来决定哪个个体参加交配。若个体的选择概率大,则有机会被多次选中,那么它的遗传基因就会在种群中扩大;若个体的选择概率小,则被淘汰的可能性会大。

def selection(chroms):probs = fitness/np.sum(fitness)  probs_cum = np.cumsum(probs)    each_rand = np.random.uniform(size=len(fitness))selected_chroms = np.array([chroms[np.where(probs_cum > rand)[0][0]] for rand in each_rand])return selected_chromsselected_chroms = selection(chroms, fitness)
print(f(decode(selected_chroms)))
>>>
[2.04387992 2.00281338 2.04387992 2.0806576  2.00281338 2.048604422.00281338 2.04387992 2.09053176 2.0806576 ]

交叉

交叉操作是指从种群中随机选择两个个体,通过两个染色体的交换组合,把父串的优秀特征遗传给子串,从而产生新的优秀个体。
这里在染色体中间进行交叉。

def crossover(selected_chroms, prob=0.6):# cross overpairs = np.random.permutation(int(len(selected_chroms)*prob//2*2)).reshape(-1, 2)center = len(selected_chroms[0])//2for i, j in pairs:# 在中间位置交叉x, y = selected_chroms[i], selected_chroms[j]selected_chroms[i] = x[:center] + y[center:]selected_chroms[j] = y[:center] + x[center:]return selected_chromscross_chroms = crossover(selected_chroms)
print(f(decode(cross_chroms)))
>>>
[2.03375504 2.00776988 2.04387992 2.09293383 2.00281338 2.029645222.00281338 2.04387992 2.09053176 2.0806576 ]

变异

为了防止遗传算法在优化过程中陷入局部最优解,在搜索过程中,需要对个体进行变异,在实际应用中,主要采用单点变异,也叫位变异,即只需要对基因序列中某一个位进行变异,以二进制编码为例,即0变为1,而1变为0。群体GtG_tGt​经过选择、交叉、变异运算后得到下一代群体Gt+1G_{t+1}Gt+1​。

def mutate(chroms, prob=0.1):clen = len(chroms[0])m = {'0':'1', '1':'0'}newchroms = []each_prob = np.random.uniform(size=len(chroms))for i, chrom in enumerate(chroms):if each_prob[i] < prob:pos = np.random.randint(clen)    chrom = chrom[:pos] + m[chrom[pos]] + chrom[pos+1:]newchroms.append(chrom)return np.array(newchroms)muatate_chroms = mutate(cross_chroms)
print(f(decode(muatate_chroms)))>>>
[2.03375504 2.00776988 2.04555749 2.09293383 2.00281338 2.029645222.00281338 2.04387992 2.09053176 2.0806576 ]

主程序

def PltTwoChroms(chroms1, chroms2, fitfun):Xs = np.linspace(-2, 2, 100)fig, (axs1, axs2) = plt.subplots(1, 2, figsize=(14, 5))dechroms = decode(chroms1)fitness = fitfun(dechroms)axs1.plot(Xs, fitfun(Xs))axs1.plot(dechroms, fitness, 'o')dechroms = decode(chroms2)fitness = fitfun(dechroms)axs2.plot(Xs, fitfun(Xs))axs2.plot(dechroms, fitness, '*')plt.show()np.random.seed(0)
population = init_population(10)
chroms = encode(population)
init_chroms = chroms.copy()
best_population = None
best_finess = -np.inffor i in range(1000):fitness = f(decode(chroms))# for fitness to be positivefitness = fitness - fitness.min() + 0.000001 if np.max(fitness) > np.max(best_finess):best_finess = fitnessbest_population = decode(chroms)selected_chroms = selection(chroms, fitness)crossed_chroms = crossover(selected_chroms)mutated_chroms = mutate(cross_chroms, 0.5)chroms = mutated_chromsPltTwoChroms(init_chroms, encode(best_population), f)


从图中可以看出,迭代1000次后,找到了最优解。

关于遗传算法的一些思考

关于遗传算法的应用需要具体问题具体分析。算法的每个步骤(染色体编解码,选择,交叉,变异),以及每个步骤的超参数,都需要根据实际情况来调整, 通过反复的试验找到最优解。

附录

完整代码如下:

import numpy as npclass GeneticTool:def __init__(self, _min=-2, _max=2, _scale=1e4, _width=10, population_size=10):self._min = _minself._max = _maxself._scale = _scaleself._width = _widthself.population_size = population_sizeself.init_population = np.random.uniform(low=_min, high=_max, size=population_size)@staticmethoddef fitness_function(x):return x**2 * np.sin(5*np.pi*x) + 2def encode(self, population):_scaled_population = (population - self._min) * self._scalechroms = np.array([np.binary_repr(x, width=self._width) for x in _scaled_population.astype(int)])return chromsdef decode(self, chroms):res = np.array([(int(x, base=2)/self._scale) for x in chroms])res += self._minreturn res@staticmethoddef selection(chroms, fitness):fitness = fitness - np.min(fitness) + 1e-5probs = fitness/np.sum(fitness)probs_cum = np.cumsum(probs)each_rand = np.random.uniform(size=len(fitness))selected_chroms = np.array([chroms[np.where(probs_cum > rand)[0][0]] for rand in each_rand])return selected_chroms@staticmethoddef crossover(chroms, prob):pairs = np.random.permutation(int(len(chroms)*prob//2*2)).reshape(-1, 2)center = len(chroms[0])//2for i, j in pairs:# cross over in centerx, y = chroms[i], chroms[j]chroms[i] = x[:center] + y[center:]chroms[j] = y[:center] + x[center:]return chroms@staticmethoddef mutate(chroms, prob):m = {'0':'1', '1':'0'}mutate_chroms = []each_prob = np.random.uniform(size=len(chroms))for i, chrom in enumerate(chroms):if each_prob[i] < prob:# mutate in a random bitclen = len(chrom)ind = np.random.randint(clen)chrom = chrom[:ind] + m[chrom[ind]] + chrom[ind+1:]mutate_chroms.append(chrom)return np.array(mutate_chroms)def run(self, num_epoch):# select best populationbest_population = Nonebest_finess = -np.infpopulation = self.init_populationchroms = self.encode(population)for i in range(num_epoch):population = self.decode(chroms)fitness = self.fitness_function(population)fitness = fitness - fitness.min() + 1e-4if np.max(fitness) > np.max(best_finess):best_finess = fitnessbest_population = populationchroms = self.encode(self.init_population)selected_chroms = self.selection(chroms, fitness)crossed_chroms = self.crossover(selected_chroms, 0.6)mutated_chroms = self.mutate(crossed_chroms, 0.5)chroms = mutated_chroms# select best individualreturn best_population[np.argmax(best_finess)]if __name__ == '__main__':np.random.seed(0)gt = GeneticTool(_min=-2, _max=2, _scale=1e10, _width=10, population_size=10)res = gt.run(1000)print(res)

遗传算法原理及其python实现相关推荐

  1. 量子遗传算法原理与MATLAB仿真程序

    写在前面: 1.其实这些智能算法的思想都差不多,只不过是各自搜寻方式.编码方式.种群更新方式等不一样而已. 量子遗传算法是在遗传算法的基础上使用了一种新的编码方式. 2.直接看前面介绍可能会觉得较难, ...

  2. java寻优算法_模拟退火算法SA原理及python、java、php、c++语言代码实现TSP旅行商问题,智能优化算法,随机寻优算法,全局最短路径...

    模拟退火算法SA原理及python.java.php.c++语言代码实现TSP旅行商问题,智能优化算法,随机寻优算法,全局最短路径 模拟退火算法(Simulated Annealing,SA)最早的思 ...

  3. python gdbt+fm_GBDT回归的原理及Python实现

    提到GBDT回归相信大家应该都不会觉得陌生(不陌生你点进来干嘛[捂脸]),本文就GBDT回归的基本原理进行讲解,并手把手.肩并肩地带您实现这一算法. 完整实现代码请参考本人的p...哦不是...git ...

  4. 手把手教你EMD算法原理与Python实现(更新)

    Rose今天主要介绍一下EMD算法原理与Python实现.关于EMD算法之前介绍过<EMD算法之Hilbert-Huang Transform原理详解和案例分析>, SSVEP信号中含有自 ...

  5. 信号处理之频谱原理与python实现

    目录 频谱分析 FFT频谱分析原理 下面就用python案例进行说明 案例1 案例2 短时傅里叶变换STFT 本分享为脑机学习者Rose整理发表于公众号:脑机接口社区.QQ交流群:941473018 ...

  6. 倒频谱原理与python实现

    目录 倒频谱定义 倒频谱python案例 本教程为脑机学习者Rose发表于公众号:脑机接口社区 .QQ交流群:903290195 倒频谱定义 倒频谱可以分析复杂频谱图上的周期结构,分离和提取在密集调频 ...

  7. 冲量(momentum)的原理与Python实现

    冲量(momentum)的原理与Python实现 前言 参考:https://www.jianshu.com/p/58b3fe300ecb 梯度下降法(Gradient Descent)是机器学习中最 ...

  8. python实现逻辑回归的流程_逻辑回归原理及其python实现

    September 28, 2018 7 min to read 逻辑回归原理及其python实现 原理 逻辑回归模型: $h_{\theta}(x)=\frac{1}{1+e^{-{\theta}^ ...

  9. 数学建模——智能优化之遗传算法详解Python代码

    数学建模--智能优化之遗传算法详解Python代码 import numpy as np import matplotlib.pyplot as plt from matplotlib import ...

  10. 典型相关分析(cca)原理_CCA典型关联分析原理与Python案例

    文章来源于"脑机接口社区" CCA典型关联分析原理与Python案例​mp.weixin.qq.com Rose今天分享一下CCA的相关原理以及Python应用,CCA在EEG等脑 ...

最新文章

  1. 新书上市 | 人类程序员,你能不能比三体人更懂量子纠缠?
  2. blob转file对象_C++核心准则C.41:构造函数生成的对象应该被完全初始化
  3. 为什么使用 Vuetify?
  4. 【项目实战课】基于Pytorch的DCGAN人脸嘴部表情图像生成实战
  5. sed是linux命令吗,Linux命令 sed
  6. SpringBoot 上传限制
  7. 一次MySQL线上慢查询分析及索引使用
  8. OpenSSL 宣布将开源许可证更改为 Apache 2.0
  9. 读《编程之美》读后感3
  10. 十动然鱼!《闲鱼年会经济数据》来了:卖得最快的奖品还是它
  11. 赛锐信息:SAP 程序优化
  12. C# 解析 Json数据
  13. [Hive]Hive常用的优化方法
  14. win2003实现单用户远程登录
  15. http长连接、长轮询的理解
  16. 互联网公司干不好上门维修?
  17. js pug 代码_前端开发nodejs+pug——注册登录
  18. 推荐必读:测试人员如何快速熟悉新业务?
  19. AndroidHttpCapture---手机轻松抓包工具
  20. 无线AP的Fat模式和Fit模式有什么区别?

热门文章

  1. android 浏览器抓包工具下载,WebSee app下载-WebSee抓包工具v1.2.1 安卓版-腾牛安卓网...
  2. winpe修复计算机无法启动,pe系统windows启动修复工具怎么使用
  3. 用Python合并文件夹下所有pdf文件(包括多级子目录下的pdf文件)
  4. modelsim编译c语言,Modelsim协同SystemC仿真
  5. 笔记本更新网卡驱动后,出现:上网图标消失、网络连接为空、设备管理器中网络适配器全部为叹号、有线无线均无法链接的情况
  6. sqlplus / as sysdba ORA-01017
  7. 黑客入侵手机的四种方法
  8. 宇宙最强下载器:IDM 俄罗斯大神版
  9. j2ee建立在线聊天室详细教程(第一天登陆页面)
  10. Bz1621.lzh二进制编辑器下载