1.算法描述
遗传算法GA把问题的解表示成“染色体”,在算法中也即是以二进制编码的串。并且,在执行遗传算法之前,给出一群“染色体”,也即是假设解。然后,把这些假设解置于问题的“环境”中,并按适者生存的原则,从中选择出较适应环境的“染色体”进行复制,再通过交叉,变异过程产生更适应环境的新一代“染色体”群。这样,一代一代地进化,最后就会收敛到最适应环境的一个“染色体”上,它就是问题的最优解。
其主要步骤如下:
1.初始化
选择一个群体,即选择一个串或个体的集合bi,i=1,2,...n。这个初始的群体也就是问题假设解的集合。一般取n=30-160。
通常以随机方法产生串或个体的集合bi,i=1,2,...n。问题的最优解将通过这些初始假设解进化而求出。
2.选择
根据适者生存原则选择下一代的个体。在选择时,以适应度为选择原则。适应度准则体现了适者生存,不适应者淘汰的自然法则。
给出目标函数f,则f(bi)称为个体bi的适应度。以
为选中bi为下一代个体的次数。
显然.从式(3—86)可知:
(1)适应度较高的个体,繁殖下一代的数目较多。
(2)适应度较小的个体,繁殖下一代的数目较少;甚至被淘汰。
这样,就产生了对环境适应能力较强的后代。对于问题求解角度来讲,就是选择出和最优解较接近的中间解。
3.交叉
对于选中用于繁殖下一代的个体,随机地选择两个个体的相同位置,按交叉概率P。在选中的位置实行交换。这个过程反映了随机信息交换;目的在于产生新的基因组合,也即产生新的个体。交叉时,可实行单点交叉或多点交叉。
在BP神经网络中,隐含层数量对神经网络的性能有着至关重要的影响,如果隐含层数量过多,会大大增加BP神经网络的内部结构的复杂度,从而降低学习效率,增加训练时间;如果隐含层数量过少,则无法精确获得训练输入数据和输出结果之间的内在规律,增加预测误差。因此,选择合适的隐含层个数具有十分重要的意义。由于隐含层个数的设置没有明确的理论可以计算,通常情况下,采用逐次分析的方法获得,即通过对不同隐含层所对应的神经网络进行预测误差的仿真分析,选择误差最小情况下所对应的隐含层个数。
学习率,即网络权值得更新速度,当学习率较大的时候,网络权值的更新速度快,当网络稳定性会下降;当学习率较小的时候,网络权值的更新速度慢,网络较为稳定。这里选择BP神经网络的学习率方式参考上一章节隐含层的选择方式,即通过对比不同学习率的网络训练误差,选择性能较优的学习率。
BP神经网络的初始网络权值对网络训练的效率以及预测性能有着较大的影响,通常情况下,采用随机生成[-1,1]之间的随机数作为BP神经网络的初始权值。
利用遗传算法来优化 BP 神经网络,利用它来学习神经网络 的权值,并在自适应遗传算法的基础上改进遗传算 子,根据适应度变化调节交叉率和变异率,并利用遗 传算法的全局搜索能力对BP 神经网络的初始权重进 行自适应调整,最终得到一个优化的 BP 神经网络.
2.仿真效果预览
matlab2022a仿真结果如下:
3.MATLAB核心程序
Max_G = 20;
Pop_Size = 10;
%交叉概率
P1 = 0.8;
%变异概率
P2 = 0.2;
%节点总数
Num_All = Num_In*Num_Hidden + Num_Hidden + Num_Hidden*Num_Out + Num_Out;
Lroms = ones(1,Num_All);
bound =[-0.5*ones(Num_All,1) 0.5*ones(Num_All,1)];
%初始化
gts = struct('fitness',zeros(1,Pop_Size),'chrom',[]);
%初始化种群
for i=1:Pop_Size
%随机种群
gts.chrom(i,:) = func_ga_code(Lroms,bound);
Xx = gts.chrom(i,:);
%计算适应度
gts.fitness(i) = func_fitness2(Xx,Num_In,Num_Hidden,Num_Out,net,train_data,train_aim);
end
fit_mean = [];
fit_best = [];
fit_chrom = [];
%最好染色体
[fit_best,ind_best] = min(gts.fitness);
fit_chrom = gts.chrom(ind_best,:);
fit_mean = sum(gts.fitness)/Pop_Size;
Fitness_line = zeros(1,Max_G);
for i=1:Max_G
i
if i == 1
P1s = P1;
P2s = 1 - P1s;
else
P1s = 1/(1 + exp(-1*fit_mean));
P2s = 1 - P1s;
end
%遗传选择
gts = func_select(gts,Pop_Size);
fit_mean = sum(gts.fitness)/Pop_Size;
%遗传交叉
gts.chrom = func_cross(P1s,Lroms,gts.chrom,Pop_Size,bound);
%变异
gts.chrom = func_mutation(P2s,Lroms,gts.chrom,Pop_Size,i,Max_G,bound);
%计算适应度
for j=1:Pop_Size
Xx = gts.chrom(j,:);
gts.fitness(j) = func_fitness2(Xx,Num_In,Num_Hidden,Num_Out,net,train_data,train_aim);
end
[fit_best2,ind_best2] = min(gts.fitness);
[fit_worst,ind_worst] = max(gts.fitness);
if fit_best > fit_best2
fit_best = fit_best2;
fit_chrom = gts.chrom(ind_best2,:);
end
gts.chrom(ind_worst,:) = fit_chrom;
gts.fitness(ind_worst) = fit_best;
fit_mean = sum(gts.fitness)/Pop_Size;
Fitness_line(i) = fit_best;
end
Xx=fit_chrom;
%把最优初始阀值权值赋予网络预测
L1 = 1;
L2 = Num_In*Num_Hidden;
w1 = Xx(L1:L2);
L1 = Num_In*Num_Hidden+1;
L2 = Num_In*Num_Hidden+Num_Hidden;
B1 = Xx(L1:L2);
L1 = Num_In*Num_Hidden+Num_Hidden+1;
L2 = Num_In*Num_Hidden+Num_Hidden+Num_Hidden*Num_Out;
w2 = Xx(L1:L2);
L1 = Num_In*Num_Hidden+Num_Hidden+Num_Hidden*Num_Out+1;
L2 = Num_In*Num_Hidden+Num_Hidden+Num_Hidden*Num_Out+Num_Out;
B2 = Xx(L1:L2);
net.iw{1,1}=reshape(w1,Num_Hidden,Num_In);
net.lw{2,1}=reshape(w2,Num_Out,Num_Hidden);
net.b{1}=reshape(B1,Num_Hidden,1);
net.b{2}=B2;
%样本的划分
for i = 1:length(C)-LEN
Price1(:,i) = C(i:i+LEN-1);
Price2(i) = C(i+LEN);
end
%训练样本
L1 = floor(0.6*length(Price2));
for i = 1:L1
train_data(:,i) = Price1(:,i);
train_aim(i) = Price2(i);
end
%测试样本
L2 = length(Price2) - L1;
for i = 1:L2
test_data(:,i) = Price1(:,i+L1);
test_aim(i) = Price2(i+L1);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%如下的是改进BP网络算法
%定义神经网络的各个层的个数
Num_In = LEN;
Num_Hidden = 60;
Num_Out = 1;
%构建BP网络
net = newff(train_data,train_aim,Num_Hidden);
ERR1 = [];
ERR2 = [];
ERR3 = [];
for j = 1:5
j
%通过改进遗传算法优化BP参数
net = func_newGA(net,Num_In,Num_Hidden,Num_Out,train_data,train_aim);
%网络训练
net.trainParam.showWindow = 0;
net = train(net,train_data,train_aim);
outputs = sim(net,test_data);
d1 = test_aim*(Maxs-Mins) + Mins;
d2 = outputs*(Maxs-Mins) + Mins;
ERR1 = [ERR1,mean(abs(d1-d2)./d2) ];
ERR2 = [ERR2,mean((abs(d1-d2)./d2).^2) ];
ERR3 = [ERR3,std((abs(d1-d2)./d2).^2) ];
end