这篇文章是我经过这两天学习遗传算法的小总结,参考了《智能优化算法及MATLAB实例》这本书,还有一大堆大佬的博客等。有一些概念是参考书上还有自己理解的部分,会更通俗易懂一点吧。主要介绍了遗传算法的原理,还有一道简单的例题用来方便理解,书上的代码不能直接用,而且注释有点少,我改了一些,然后加了一些注释。应该比较通俗易懂吧,哈哈哈。昨天刚看到这个代码真的是一头雾水,有一些变量想了半天不知道是啥。今天四处搜罗了一些资料以后基本可以比较完整的理解它了。可以给像我这样的初学者一点参考吧。我要是有精力下次还会更几道遗传算法的极值问题或者旅行商问题的习题及详解或者免疫算法吧,哈哈哈。希望我继续爱学习!!!
一、遗传算法基础
遗传算法借鉴了孟德尔遗传学说和达尔文的进化论,本质上是一种全局搜索方法。使用的‘适者生存’的原则。
1.1 生物学基础
跟我们高中学的生物很相似,适者生存就必须进行生存斗争。达尔文把这种生存斗争中的适者生存,优胜劣汰的过程叫做自然选择。
总结一下就是:
(1)遗传信息都包含在染色体中染色体决定生物的性状,染色体是由基因有规律的排列构成。
(2)同源染色体的交叉或者变异会产生新的性状甚至物种。
(3)对环境适应能力强的个体,比适应能力差个体的更有机会将自己的基因或染色体遗传到下一代。
这部分跟高中生物一模一样,理科生都懂。
1.2 理论基础
模式:模式是描述种群中在位串的某些确定位置上具有相似的位串子集的相似性模板。
模式阶:模式H中确定位置的个数称作该模式的模式阶。比如模式0111的阶数为4,而模式0****阶数为1。所以一个模式的阶数越高,确定性就越高。
定义距:在模式H中第一个确定位置和最后一个确定位置之间的距离称为该模式的定义距。
模式定理:在遗传算法选择,交叉,变异算子的作用下,具有低阶,短定义距,并且其平均适应度高于群体平均适应度的模式在子代中将成指数增长。
1.3 对应关系
群体(可行解集)、个体(可行解)、染色体(可行解的编码)、基因(可行解编码的分量)、适应度(评价函数值)。
1.4 遗传编码
二进制编码,实数编码(十进制编码),十进制编码的优势是计算精度高,但是只能用于连续变量问题。
1.5 适应度
用来评价个体优劣的函数叫做个体的适应度函数。
1.6 遗传算法特点
(1)遗传算法以决策变量的编码作为运算对象。
(2)遗传算法直接以目标函数值最为搜索信息。使用目标函数值变换来的适应度函数值,可以进一步确定搜索方向和搜索范围。
举个栗子,我在玩和平精英的时候跑毒想找车,我可能会先找车库,可能不太恰当,大概就是这个意思,比起原来无目的的寻找,我的方向变为了找车库,我就不会海景房或者教堂里面去找车了。
(3)遗传算法同时使用多个搜索点的搜索信息。
(4)遗传算法是一种基于概率的搜索技术。
(5)遗传算法具有自组织、自适应和自学习的特性。
二、遗传算法操作
2.1 遗传操作
(1)选择算子:根据适应度,选择优良个体遗传到下一代群体中。其中‘轮盘赌’选择法是比较常用的方法。它是一种基于比例的选择,利用个体适应度所占比例的大小来决定其子孙保留的可能性。
举个栗子:假设我们有四个个体A、B、C、D,它们的适应度,选择概率,累计概率如图所示。
A 20 0.2 0.2
B 10 0.1 0.3
C 50 0.5 0.8
D 20 0.2 1
我们选择一个骰子,如果落在0-0.2,就是选择个体A,如果落在0.2-0.3就选择B,如果落在0.3-0.8就算则个体C,如果落在0.8-1,就选择D。这大概就是轮盘赌的大概思想。
换个方式也可以假设骰子不动,转动轮盘也可以,只不过是参考系不同而已。
(2)交叉算子
类似生物学中的染色体交叉,假设交叉概率为Pc,从交配池中随机选择一对,根据位串长度L,对于交配的一对,随机选择[1,L-1]中的一个或者多个作为交叉位置,进行交叉操作。
(3)变异算子
假设变异概率为Pm,对进行变异的个体随机选择变异位进行变异。
三、遗传算法流程
3.1
3.2 关键参数说明
群体规模NP,太小性能不好,太多计算量大,一般取10~200。
交叉概率Pc,适当的交叉可以开辟新的搜索区域能力,太大模式可能遭到破坏一般取0.25~1.00。
变异概率Pm,主要目的是保持群体多样性,高频度可能式其变成纯粹的随机搜索。通常取0.001~0.1。
终止进化代数G,一般在100~1000之间。
四 MATLAB仿真实例及详解
用标准遗传算法求函数
的最大值。
解:首先我们先把函数图像画出来
clear all;
close all;
clc;
x=0:0.01:10;
y=x+10*sin(5*x)+7*cos(4*x);
plot(x,y)
xlabel('x')
ylabel('y')
title('x+10*sin(5*x)+7*cos(4*x)')
我们发现他是一个局部多极值函数。
接下来我们开始利用遗传算法进行仿真:
书上的代码敲完不能直接用,所以我搞懂以后更改了一些部分还加上了一些注释,希望可以更好地理解这个算法的原理。
初始化:种群数量NP=50,染色体二进制编码长度L=20,迭代次数G=100,交叉概率为Pc=0.8,变异概率Pm=0.1。
首先先开始初始化参数
clear all;
close all;
clc;
NP=50; %种群数量
L=20; %二进制位串长度
Pc=0.8; %交叉概率
Pm=0.1; %变异概率
G=100; %迭代次数
Xs=10; %上限
Xx=0; %下限
f=randi([0,1],NP,L); %随机获得初始种群
特意说一下这个randi函数,书上给的本来是 randint函数,但是一直报错,后来发现是2016a版本的MATLAB将randint函数删掉了,都用randi来代替,但是他们的语法略有不同,randint(m,n,[a,b]),randi([a,b],m,n)只有里面参数位置发生了变化。
接下来就是讲二进制解码为定义域内十进制
%遗传算法循环
for k=1:G
%二进制解码为定义域内十进制
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]内的实数
Fit(i)=func1(x(i));
end
maxFit=max(Fit); %最大值
minFit=min(Fit); %最小值
rr=find(Fit==maxFit);
fBest=f(rr(1,1),:); %历代最优个体
xBest=x(rr(1,1));
Fit=(Fit-minFit)/(maxFit-minFit); %归一化适应度值
接下来就是我们的基于轮盘赌的复制操作,我们这里采用的是骰子不动,转轮盘的思想
%轮盘赌复制操作
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))<fitvalue(fiti) %如果骰子落在轮盘的这个区域
nf(newi,:)=f(fiti,:); %把这个新个体给种群
newi=newi+1;
else
fiti=fiti+1;
end
end
接下来是交叉和变异操作,交叉就将对应基因位置的基因进行交换即可,变异就是将某些需要变异的基因取反即可。
%基于概率的交叉操作
for i=1:2:NP
p=rand;
if p<Pc
q=randi([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*Pm) %四舍五入
h=randi([1,NP],1,1); %随机选取需要变异的染色体
for j=1:round(L*Pm)
g=randi([1,L],1,1); %选择需要变异的基因数
nf(h,g)=~nf(h,g);
end
i=i+1;
end
f=nf;
f(1,:)=fBest;
trace(k)=maxFit;
end
xBest;
figure
plot(trace)
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进化曲线')
%适应度函数
function result=func1(x)
fit=x+10*sin(5*x)+7*cos(4*x);
result=fit;
end
书上代码中还有一个小问题,就是最后一段没有写end,这个地方大家要注意啦。刚开始我也没注意function这段最后要加end。
下面是仿真结果
发现这种方法其实在迭代30次左右,就可以得到最佳解,确实还是比较好用的。
五 遗传算法改进方向
标准算法存在局部搜搜能力差和‘早熟’等缺陷,不能保证算法收敛。很多文献提出使用编码机制、选择策略、交叉算子、变异算子、特殊算子和参数设计等来优化。
此外还有将遗传算法与差分进化算法,免疫算法,蚁群算法,粒子群算法,模拟退火算法,禁忌搜索法和量子计算等方法结合所构成的混合算法来解决标准遗传算法的缺陷。