遗传算法
记录学习matlab的过程防止忘记。本文参考《智能优化算法及其matlab实例第二版》
遗传算法简介
遗传算法利用群体搜索技术,将种群代表一组问题解,对种群进行选择,交叉,变异,复制等生物学上的进化操作产生新一代的种群。
- 群体 :可行解集(一开始群体是随机生成的,然后通过自然选择,优胜略汰);
- 个体:可行解(组成群体的单个生物体);
- 染色体 :可行解的编码(包含生物体信息的遗传物质);
- 基因:可行解编码的分量(控制生物体的遗传信息的基本单位) ;
- 适应度:可行解在具体问题中跟最优解的差值(个体对当前环境的适应能力)
举个例子
我们创建一个数值在0~10的3行5列的矩阵
randi([0,10],3,5);
结果为
ans =
7 4 7 0 7
8 7 0 1 3
8 1 3 9 10
通常用一列作为一个个体即这个矩阵代表了5了个体
每一列中的三个实数编码代表了每个个体的遗传物质
比如说第一个个体的遗传信息是 7 8 8
遗传算法怎么解决问题
我觉得一个难点就是怎么把解转换为编码的个体,上面介绍过常用的编码方式有二进制编码跟实数编码,那么怎么编 ?
二进制编码
如果最优解是一个实数的话,像找函数的极大值极小值这些,就可以用到二进制编码,一列二进制编码代表的一个解就代表了一个实数。
实数编码
如果最优解是多个实数的话,像在一组数据中找出最合适的几个,就可以用实数编码。
遗传算法流程
1.初始化:设定最大进化次数,随机生成一个种群(一个矩阵,维数看实际问题)。
2.个体评价:计算种群中每个个体的适应度。
3.进化运算:对种群进行选择运算,交叉运算,变异运算。
4.终止条件判断:如果进化次数大于最大进化次数则终止。
遗传算法中关键参数
1.群体规模NP:NP太小时优化性能不太好,NP太大计算复杂度高。一般NP取10-200.
2.交叉概率Pc:Pc太小时可能会使遗传算法太过于迟钝,Pc较大时虽然可以扩大搜索区域,但稳定性不高。Pc一般取0.25-1.00
3.变异概率Pm:Pm在算法中起了一种辅助作用,不可以太高,太高会让算法变成随机的搜索。一般取0.001-0.1.
4.算法进化次数:一般100-1000之间。问题不大,能算不了就好。
简单的实例
用标准遗传算法求函数 f(x) = x+10sin(5x)+7cos(4x)的最大值
%遗传算法
clear ;
funcl =@(x) x+10*sin(5*x)+7*cos(4*x);
NP = 50; %种群数量
L = 20 ; %二进制编码长度
Pc = 0.8; %交叉率
Pm = 0.1 ;%变异率
G = 100 ;%最大迭代次数
Xs = 10; % X取值的上下限
Xx = 0;
f = randi([0,1],NP,L); %随机获得初始种群
fit =zeros(1,50);
x = zeros(1,50);
trace = zeros(1,100);
xtrace = zeros(1,100); %预先分配内存
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); %把二进制编码变成实数
fit(i) = funcl(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;
fitvalue = cumsum(fitvalue);
ms = sort(rand(NP,1));
fiti = 1;
newi = 1;
while newi <= 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(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;
xtrace(k) =xbest;
end
figure;
subplot(3,1,1);
plot(trace);
xlabel('迭代次数');
ylabel('进化曲线');
title("适应度进化曲线");
hold on;
subplot(3,1,2);
plot(xtrace);
xlabel('迭代次数');
ylabel('进化曲线');
title("适应度进化曲线");
subplot(3,1,3);
fplot(funcl,[0,10]);
xlabel('x');
ylabel('y');
title("函数曲线");
代码运行结果
可以看到算法收敛得很快。