源自一次大一下学期的数模比赛
遗传算法
演化思想
遗传算法的本质
遗传算法的本质=模拟生物演化。具体来说,模拟对象是生物演化中的种种自然现象(如变异,交叉互换,交配,淘汰)。因此,一个优秀的遗传算法首先应该做到生物演化的模拟。但是并非仅仅对生物演化进行简单复现,生物演化中有种种细节可以忽略不计,如DNA非编码段变异,等等
那演化中最重要的部分是什么?
对下一代种群的定向选择。这句话有三个要点,一个是下一代,另一个是定向,最后一个是选择。先说后两者,所谓定向就是人为设定衡量不同个体的可计算指标;而选择则是保留满足指标的个体;最后一点,下一代怎么产生呢?就是遗传,变异和交叉互换。
生物学有关名词这里就不解释了,假设高中生物老师都讲过。
Ras函数
Ras函数(Rastrigin’s Function)是一个典型的非线性==多峰==函数,具有多个局部的极大值点和极小值点,常规算法很容易陷入局部最优解中。
在n维空间中,Ras函数表达式为:
$$ f(x)=An+\sum_{i=1}^{n}\ [x^{2}{i}-Acos(2\pi x{i})] $$
其中,$A$是可以人为定义的常量,$n$是Ras函数的维数
当$n=2$时,Ras函数为二维形式,这个函数在$(0,0)$有全局最小值。
下图是$A=10,n=2$时,Ras函数在$x,y\in[-5,5]$上的三维图象
遗传算法
==目标函数== objective function
1 | %% |
目标函数是Ras函数。计算这个函数需要三个参数,分别是$A$,$x$,$y$。其中$A$是我们自行设定的常数,而$x,y$则对应二维平面上的点
补充:
function
------->matlab官方文档-function
fsurf
------->matlab官方文档-fsurf
==初始化种群== initialization population
1 | % initialization population - binary form |
- 初始种群要足够随机且多样:目的是尽可能扩大搜索范围,找到最优解
- 染色体长度等于初始种群中每个个体的二进制编码长度
==解码== decoding:from binary to decimal
1 | % coding - binary to decimal floating point |
每个个体由32位二进制数字组成。32位数字从中间划分成两组,前16位表示x,后16位表示y,组合起来代表二维平面上的点。
- mat2cell的时候注意元胞数组的索引方式
每个个体与向量$vector$相乘,可以将16位二进制数转化成十进制数$$vector=[2^{15} ,2^{14},…,2,1]$$
得到的乘积是一个范围落在在$(0,65535)$内的整数。为了将这个范围缩小到10附近,再将结果除以6553。
函数最后输出一个50*2的矩阵,储存50个个体的二维坐标值
补充:
mat2cell
函数------->matlab官方文档-mat2cell
ones
函数------->matlab官方文档-ones
==计算目标函数== calculate the real value
1 | % calculate the real value |
==计算适应度== calculate the fittness value
1 | % calculate the fittness value; range in 0 and 1 |
衡量适应度采用常见归一化方法
$$ X = \frac{x-x_{min}}{x_{max}-x_{min}}$$
如果求解最大值,则$X$越大,个体适应度越高;
如果求解最小值时,则$(1-X)$的结果越大,个体适应度越高。
==选择最优个体== choose the best individual
1 | % best |
==选择复制== selection copy
1 | % evolution |
选择复制的思想是每次都保留种群中的优秀个体,逐代提高下一代种群适应度。特别要注意的是,种群适应度的提高的过程一定要 “==逐步==” ,提高速度太快,种群容易过早陷入局部最优解;提高速度过慢,则迭代次数过多,计算速度慢。
那么,怎样才能体现 ==逐步== 这二字?
答案是,在每一代种群中选择优秀个体的同时,保留一些不那么优秀的个体,为种群提供多样性和可能性。
或者降低交叉互换,基因变异的概率
补充:
轮盘赌-------->轮盘赌算法
cumsum
-------->matlab帮助文档-cumsum
进行到这一步,结合计算适应度、计算目标函数、选择最优个体和选择复制,已经可以得到多次演化大致的图象
图象在前10次迭代里快速向高适应度方向演化,但是在演化10次左右后最小值不再改变,呈现为一条平滑的直线,陷入局部最优解。
用这种不进行交叉互换,不产生基因突变,仅仅依靠选择复制的算法,计算得最优个体为$(3.3357 ,3.5710)$。
==交叉互换== crossover
1 | function popNew = crossover(pop,pc,fitvalue) |
从任意位置开始随机选择两个个体交换染色体,进行交叉互换
交叉互换后得到的解更加逼近于全局最优解,得到的最优个体为$( 2.5010 ,1.5626
)$
==随机变异== mutation
1 | % mutation |
随机选择染色体中某位1变成0,0变成1,得到的最优个体为$( 0.0012 ,0.9962)$,更加逼近全局最优解。
==总代码==
1 | clear all; |
==未回答的问题==
算法虽好,仍有遗憾
- 陷入局部最优无法跳出窘境
上图是迭代一千次的结果,每一个细小尖微的波动都是突变在演化中产生的影响,但是仍没有跳出局部最优的窘境。