如果你对遗传算法感兴趣或者正在做有关GA的研究,不妨关注博客右侧专栏 → 智能计算-深入遗传算法 ,一步一步深入算法,分享算法每一个流程模块(如选择策略,交叉机制等等)的众多参考观点。代码和Demo咱从来不缺。
遗传算法入门系列文章:
(上篇)遗传算法入门(上)代码中的进化学说与遗传学说
(下篇)遗传算法入门(下)C++求解TSP问题
说明: 本文用一个实际的二进制编码求解一元函数最值的代码例子阐明基本遗传算法的运行机理 。 本文会用Matlab代码写明关键之处的算子,源码的下载 请带好大挪移令和灵石进传送阵
目标函数如下:
max:F(x)=x+10sin(5x)+7cos(4x), x∈[0,10] m a x : F ( x ) = x + 10 s i n ( 5 x ) + 7 c o s ( 4 x ) , x ∈ [ 0 , 10 ]
该函数图形如下:
从图像中很容易看出函数在 x∈[0,10] x ∈ [ 0 , 10 ] 上的最值 Fmax≈24.8 F m a x ≈ 24.8 , Fmin≈−12 F m i n ≈ − 12 ,并且在 x≈3.2 x ≈ 3.2 附近,有一个局部极大值。
本文列在入门篇,所以求解函数选用最为简单的一元函数,并且定义域无负值。而所采用的遗传算法也采用最传统的算法思想与最传统的算子:二进制编码,赌轮(轮盘赌)选择算子,多基因交叉,多基因变异。
算法流程:
初始参数,种群的规模,也是个体的数量 NP=80 N P = 80 , 迭代次数 G=100 G = 100 。
因为是一元函数,变量只有一个,所以采用二进制编码,精度(个体基因位数)设置为 L=20 L = 20 。也就是说,初始种群实际上就是一个随机生成的由0和1组成的 NP∗L N P ∗ L 的二维矩阵 。MATLAB代码如下:
f=randi([0,1],NP,L); %随机获得初始种群矩阵
这样,每个个体都是由20位的0和1基因组成,我们知道,其实每个个体就是函数的一个变量,在进行求解适应度时,需要将该变量带入函数运算,这时,就需要将二进制编码的个体解码成在定义域内的十进制,解码的原理和对应法则大家可以看如下的MATLAB代码:
for i=1:NP
U =f(i,:);
m=0;
for j=1:L
m=U(j)*2^(j-1)+m;
end
x(i)=Xx+m*(Xs-Xx)/(2^L-1); %x(i)为[0,10]内的实数
end
适应度函数是为了更好的编写代码,更好的参与选择、交叉和变异算子而在目标函数的基础上做的一系列改进,本文要求解的目标函数非常普通,而且本文求解的是最大值,即,个体的目标函数值越大,说明该个体越好,适应度就越好,所以就直接把目标函数当做适应度函数,本文提到的适应度函数就是目标函数。
需要提一下的是,源码中对适应度值做了归一化的处理。大家可不用理会 。
思考:若本文求的是最小值呢?目标函数能不能直接当适应度函数用?
回答: 不可以。我们所说的目标函数的概念是待优化的函数,而适应度函数是适应度的变化函数。如果求解目标函数的最小值,则目标函数值越小的,适应度越高,所以适应度函数的设计就应该考虑把目标函数做取反,或者取倒数操作 。
关于 适应度函数的设计我们放到深入遗传算法系列时再说。
在遗传算法中,选择策略用的最多的就是轮盘赌选择,也叫赌轮选择或者适应度比例选择法 。轮盘赌选择的原理并不难理解,我们这里给出一个简单的理解,详细的探讨将留在”深入遗传算法系列“中 。
假设我们有4个个体个体:A
个体:B
个体:C
个体:D
,其适应度、选择概率、累计概率如下表所示 :
个体 | 适应度 | 选择概率 | 累计概率 |
---|---|---|---|
A | 10 | 0.1 | 0.1 |
B | 40 | 0.4 | 0.5 |
C | 30 | 0.3 | 0.8 |
D | 20 | 0.2 | 1 |
我们用累计概率画出一个饼图(赌博的轮盘):
画好图后,就开始选择了。首先我们准备一个骰(tou)子,随机抛入轮盘中,落入0.0~0.1区域就选中个体A,落入0.1~0.5区域就选中个体B,落入0.5~0.8区域就选中个体C,落入0.8~1.0区域就选中个体D。 一共抛种群规模NP次,选出NP个个体组成新的种群。
以上的思想就是轮盘赌的思想,其实还有另一个方式玩这个游戏,就是把骰子固定不动,我们转NP次轮盘,骰子指向哪个区域,就选中对应区域的个体。貌似这种方式只是变换了一下参考系而已。
用代码实现上述的思想,也就会有两种方式,希望大家在看别的代码实现的时候能够搞清楚是哪两种方式。下面是MATLAB代码实现: (用的是轮盘转,骰子不动的思维方式)
sum_Fit = sum(Fit) ;
fitvalue = Fit ./sum_Fit ; %选择概率,将Fit的每个元素除以sum_Fit
fitvalue = cumsum(fitvalue) ; %累积概率
ms = sort (rand(NP,1)) ; %产生NP个0~1之间的随机数,并且升序排序
fiti =1;
newi=1;
while newi<=NP %轮盘开始转,一共转NP次
if(ms(newi)%如果骰子落在轮盘的这个区域
nf(newi,:) = f(fiti , :) ; % 把个体给新的种群
newi = newi + 1;
else
fiti=fiti +1;
end
end
交叉,选出两个个体,通过交叉概率Pc确定是否需要交叉,如果交叉,则两个个体某些对应基因位上的基因进行交换即可。
变异,每个个体通过变异概率Pm确定是否需要变异,如果变异,则某些基因位取反即可。
附上交叉代码:
for i = 1:2:NP % 从1到NP ,每隔两个
p = rand ;
if p[0,1],1,L);
for j =1:L
if q(j) == 1
temp=nf(i+1,j);
nf(i+1,j) = nf(i,j);
nf(i,j) = temp;
end
end
end
end
附上变异代码:
i = 1;
while i<=round(NP*Pc) % 四舍五入
h=randi([1,NP],1,1) ; %随机选取一个需要变异的染色体
for j = 1:round(L*Pc)
g = randi([1,20],1,1);%随机选取需要变异的基因数
%g=rand;
nf(h,g) = ~ nf(h,g);
end
i=i+1;
end
所谓的精英策略是指: 上一代最好的个体不经过选择、交叉、变异,直接复制到下一代中。不要小看精英策略,实践证明,经营策略是增强算法收敛的最主要,最强大的手段,是经过理论证实。如果算法中缺乏精英策略,会严重影响收敛速度。
什么 ?你还不会用MATLAB画图,太out了!赶紧带好大挪移令进传送阵-三个实例搞定MATLAB二维绘图闭关修炼去吧,恕不远送!!
首先,我们要清楚要绘制怎样的结果图。你可以绘制一幅种群平均适应度随迭代次数的变化,也可以绘制一幅当前代种群的最大适应度,而本次我们绘制的是一幅迄今为止种群中最大适应度随迭代次数的变化,如下图:
至于是怎么绘制的 ?其实很简单,定义一个G(代数)维数组,盛放每一代中迄今为止的最大值,然后用plot绘图函数绘制即可。