白话遗传算法(以长颈鹿的进化为例)

首先来看看遗传算法的本质,遗传算法是模拟生物进化的一种全局优化搜索算法,是一种数值求解方法。说几个大家熟悉的搜索的算法吧:
1. 枚举遍历(这也可以算吧- -)
2. 二分查找法(在有序数组中查找某一特定元素的搜索算法)
3. DFS(深度优先搜索,沿着树的深度遍历树的节点)
4. Dijkstra算法(用广度优先搜索解决非负权有向图的单源最短路径问题,算法最终得到一个最短路径树)
5. 等等等等
怎么样?搜索算法咱们也是见的不少了,这个遗传算法又是怎么回事呢?我们先看一下遗传算法的“官话”:

遗传算法将问题的可行解作为种群,每个种群是由一定数目的个体组成,每个个体都由多个基因编码的组合即染色体表示。将种群中个个体进行配对,产生下一代,根据一种评价函数衡量一个个体的最优程度,即适应度。适应度高的个体更有希望生存下来,参与种群的繁衍,进行交叉变异操作

是不是很晕呢
白话遗传算法(以长颈鹿的进化为例)
让我们以长颈鹿进化的例子来对应一下上述名词。

基本概念

例子:长颈鹿种群的进化算法。目的是为了进化出一个长脖子的种群,每个种群是由一些个体(一些鹿)组成,每只长颈鹿个体都由染色体表示,每个染色体是由多个基因编码的组合表示。
白话遗传算法(以长颈鹿的进化为例)
种群中的个体进行交配,产生下一代,根据脖子的长度衡量一头长颈鹿吃饱饭的程度,脖子太短吃不到树叶子,脖子太长会抬不起头,只有脖子长度适中才能吃的最饱。这个根据脖子的长短而决定的吃饱饭的程度就叫适应度函数。即适应度值是由脖子长度决定的函数值。

脖子长的个体更有希望生存下来,参与种群的繁衍,进行交配、变异。

算法的流程

遗传算法的流程是这样的:

使用遗传算法搜索最优解,首先要找出要求解的问题,在对可行方案进行编码操作,产生初始种群,找出评价函数,最后进行选择交叉变异

我们再做进一步的解释:
问题:找到更容易吃饱的长颈鹿。
可行方案:例如一头脖子长度刚刚适合的一头鹿。将它编码就是把决定脖子长度的基因表达即染色体信息写成2进制(也可以是其他进制,我们先用最简单的)。我们可以这样编码,一头64cm长脖子的长颈鹿,编码为:100000(64的二进制)
初始种群:上帝之手制造20头一样的初始小鹿,初始染色体100000,也就是脖子64cm长
评价函数:假设评价函数是这样的:f(x)=x2+2x,x为脖子长度,f(x)为吃饱饭的程度,最高为1。这个函数图像是这样的:
白话遗传算法(以长颈鹿的进化为例)
在这里,脖子长度为1米的时候,能吃10成饱!(当然只是一个有趣的假设)
选择交叉变异:根据适应度函数,能活到成年的概率与适应度成正比。选择活到成年的长颈鹿两两交叉(交配)产生下一代的染色体,再根据概率进行基因变异。
最后,在到达最大进化代数后停止。
以下图片引用自参考文献[1]:
流程图
白话遗传算法(以长颈鹿的进化为例)
交叉(两只长颈鹿交配,染色体交叉产生下一代)图示
白话遗传算法(以长颈鹿的进化为例)
变异(某只长颈鹿基因突变)图示
白话遗传算法(以长颈鹿的进化为例)

一个简单的应用

下面来看一个遗传算法寻找函数最大值的应用~
给定一个函数:
f(x)=xsin(10πx)+2
白话遗传算法(以长颈鹿的进化为例)
要找到在区间[-1,2]上的最大值,我们既可以采用遗传算法。
下图中,generation1即第一代初始种群,全部是随机生成的点,到了generation97的时候,种群就全部聚集在最高点处了。这个实现来自文献2,语言为R。
白话遗传算法(以长颈鹿的进化为例)
这里是我的一个Python程序GitHub地址,大家可以更改一下里面的适应度函数来求一些自己创造的函数极大极小点。结果如下(取前10进化代数和145-149代):
白话遗传算法(以长颈鹿的进化为例)
输出参数每行为:进化代数i,最大适应度值,种群平均适应度值,种群最低适应度值。

参考文献

[1] 一文读懂遗传算法工作原理(附 Python 实现)
[2] 算法理解-遗传算法(Genetic Algorithm)(一个带计算过程的例子)