介绍
数据处理见上篇博文,这里用遗传算法优化神经网络的参数,使其得到更好的训练效果。
实验步骤
流程图
初始化参数
%样本数据就是前面问题描述中列出的数据
[x,y]=date_inscet();
randIndex=randperm(size(x,1));%打乱顺序
x=x(randIndex,:);y=y(randIndex,:);
x1=x(1:1000,:);y1=y(1:1000,:);x2=x(1001:end,:);y2=y(1001:end,:);
% 初始隐层神经元个数
hiddennum1=15;hiddennum2=5;
% 输入向量的最大值和最小值
threshold=[0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1];
inputnum=size(x,2); % 输入层神经元个数
outputnum=size(y,2); % 输出层神经元个数
w1num=inputnum*hiddennum1; % 输入层到隐层1的权值个数
w2num=hiddennum2*hiddennum1;% 隐层1到隐层2的权值个数
w3num=outputnum*hiddennum2;% 隐层2到输出层的权值个数
N=w1num+hiddennum1+w2num+hiddennum2+w3num+outputnum; %待优化的变量的个数
%% 定义遗传算法参数
NIND=40; %个体数目
MAXGEN=50; %最大遗传代数
PRECI=10; %变量的二进制位数
%GGAP=0.95; %代沟
px=0.7; %交叉概率
pm=0.01; %变异概率
trace=zeros(N+1,MAXGEN); %寻优结果的初始值
初始化种群
二进制编码,通过自变量的范围与精度来确定染色体编码长度。
bounds=repmat([-1;1],1,N);%所有变量范围都为【-1,1】
precision=ones([1,N])*0.01;%由求解精度确定二进制编码长度
bits=ceil(log2((bounds(2,:)-bounds(1,:)) ./ precision));%由设定精度划分区间,ceil取上整
[Pop]=InitPopGray(NIND,bits);%初始化种群
bestpop=zeros([1,size(Pop,2)]);bestac=0;
%初始化种群
function [initpop]=InitPopGray(popsize,bits)
len=sum(bits);
initpop=zeros(popsize,len);%The whole zero encoding individual
for i=1:popsize
pop=round(rand(1,len));
initpop(i,:)=pop(:);
end
计算适应度函数
神经网络的测试集准确率作为适应度函数。
function [value] = fitness_funNew(Pop,bounds,precision,bits,x1,y1,x2,y2,hiddennum1,hiddennum2)
[m,n]=size(Pop);
value=zeros([m,2]);
for j=1:m
aa=b2f(Pop(j,:),bounds,precision,bits);%二进制->十进制
[err,ac]=Bpfun(aa,x1',y1',hiddennum1,hiddennum2,x2',y2');
value(j,:)=[err,ac];
end
用matlab自带的神经网络函数搭建
function [err,ac]=Bpfun(x,P,T,hiddennum1,hiddennum2,P_test,T_test)
%% 训练&测试BP网络
%% 输入
% x:一个个体的初始权值和阈值
% P:训练样本输入
% T:训练样本输出
% hiddennum:隐含层神经元数
% P_test:测试样本输入
% T_test:测试样本期望输出
%% 输出
% err:预测样本的预测误差的范数
inputnum=size(P,1); % 输入层神经元个数
outputnum=size(T,1); % 输出层神经元个数
%% 新建BP网络
net=newff(minmax(P),[hiddennum1,hiddennum2,outputnum],{'tansig','satlins','logsig'},'trainlm');
%% 设置网络参数:训练次数为1000,训练目标为0.01,学习速率为0.1
net.trainParam.epochs=10;
net.trainParam.goal=0.01;
LP.lr=0.1;
net.trainParam.show=NaN;
%net.trainParam.showwindow=false; %高版MATLAB
%% BP神经网络初始权值和阈值
w1num=inputnum*hiddennum1; % 输入层到隐层1的权值个数
w2num=hiddennum1*hiddennum2;% 隐层1到隐层2的权值个数
w3num=outputnum*hiddennum2;% 隐层2到输出层的权值个数
w1=x(1:w1num); %初始输入层到隐层的权值
B1=x(w1num+1:w1num+hiddennum1); %初始隐层阈值
w2=x(w1num+hiddennum1+1:w1num+hiddennum1+w2num); %初始隐层到输出层的阈值
B2=x(w1num+hiddennum1+w2num+1:w1num+hiddennum1+w2num+hiddennum2); %输出层阈值
w3=x(w1num+hiddennum1+w2num+hiddennum2+1:w1num+hiddennum1+w2num+hiddennum2+w3num); %初始隐层到输出层的阈值
B3=x(w1num+hiddennum1+w2num+hiddennum2+w3num+1:w1num+hiddennum1+w2num+hiddennum2+w3num+outputnum); %输出层阈值
net.iw{1,1}=reshape(w1,hiddennum1,inputnum);
net.lw{2,1}=reshape(w2,hiddennum2,hiddennum1);
net.lw{3,2}=reshape(w3,outputnum,hiddennum2);
net.b{1}=reshape(B1,hiddennum1,1);
net.b{2}=reshape(B2,hiddennum2,1);
net.b{3}=reshape(B3,outputnum,1);
%% 训练网络以
net=train(net,P,T);
%% 测试网络
Y=sim(net,P_test);
err=norm(Y-T_test);
for i=1:length(Y)
if Y(i)<0.5
Y(i)=0;
else
Y(i)=1;
end
end
ac=1-sum(abs(Y-T_test))/length(Y);
选择
历代最优留下+最好的前20%-1直接留下+轮盘赌选择法
function [selectpop]=NonlinearRankSelect(fit,pop,bestpop)
[m,n]=size(pop);
selectpop=zeros(m,n);
%fit=max(fit)-fit;
selectprob1=fit/sum(fit);%计算各个体相对适应度(0,1)
newfit=cumsum(selectprob1);%计算各选择概率之和,轮盘图
mm=round(m*0.2);
rNums=sort(rand(m-mm,1));
%把最好的前20%直接留下
[a,b]=sort(fit);
for i=1:mm-1
selectpop(i,:)=pop(b(m-i+1),:);
end
selectpop(mm,:)=bestpop;
%随机选
fitIn=1;newIn=mm+1;
while newIn<=m%选择,不用改
if rNums(newIn-mm)<=newfit(fitIn)
selectpop(newIn,:)=pop(fitIn,:);
newIn=newIn+1;
else
fitIn=fitIn+1;
end
end
交叉
全交叉
%交叉操作
function [NewPop]=CrossOver(OldPop,pCross)
%OldPop为父代种群,pcross为交叉概率
[m,n]=size(OldPop);
NewPop=zeros([m,n]);
r=rand(1,m);
y1=find(r<pCross);
y2=find(r>=pCross);
len=length(y1);
if len>2 && mod(len,2)==1%如果用来进行交叉的染色体的条数为奇数,将其调整为偶数
y2(length(y2)+1)=y1(len);
y1(len)=[];
end
if length(y1)>=2
for i=0:2:length(y1)-2
[NewPop(y1(i+1),:),NewPop(y1(i+2),:)]=EqualCrossOver(OldPop(y1(i+1),:),OldPop(y1(i+2),:));
end
end
NewPop(y2,:)=OldPop(y2,:);
end
function [children1,children2]=EqualCrossOver(parent1,parent2)%采用均匀交叉
n=length(parent1);
hidecode=round(rand(1,n));%随机生成掩码
crossposition=find(hidecode==1);
holdposition=find(hidecode==0);
children1(crossposition)=parent1(crossposition);%掩码为1,父1为子1提供基因
children1(holdposition)=parent2(holdposition);%掩码为0,父2为子1提供基因
children2(crossposition)=parent2(crossposition);%掩码为1,父2为子2提供基因
children2(holdposition)=parent1(holdposition);%掩码为0,父1为子2提供基因
end
变异
五点变异
function [NewPop]=Mutation(OldPop,pMutation,VarNum)%变异操作,VarNum变异点个数
[m,n]=size(OldPop);
r=rand(1,m);%m是种群个数
position=find(r<=pMutation);
len=length(position);
if len>=1
for i=1:len
k=unidrnd(n,1,VarNum); %设置变异点数,一般设置1点
for j=1:length(k)
if OldPop(position(i),k(j))==1
OldPop(position(i),k(j))=0;
else
OldPop(position(i),k(j))=1;
end
end
end
end
NewPop=OldPop;
实验结果
进化曲线:
最优初始权值和阈值:
X=-0.4 -0.77 1.04 0.11 1 0.68 -0.44 1.15 -0.3 1.02 0.91 1.11 -0.74 -0.28 0.3 -0.33 0.42 0.63 0.61 -0.22 1.27 -0.92 1.32 0.36 0.74 1.07 -0.94 -0.35 -0.57 0.32 0.87 0 -0.33 -0.07 0.93 0.79 1.33 0.83 0.01 1.06 -0.29 -0.14 0.5 1.41 1.15 1.01 -0.62 -0.03 -0.69 0.02 -0.47 0.16 1.41 -0.06 -0.42 0.55 0.22 -0.68 -0.8 1.21 0.66 1.4 -0.51 -0.32 -0.97 1.28 -0.29 -0.62 -0.32 0.44 0.22 0.09 -0.84 0.14 1.48 0.19 0.89 -0.3 0.77 0.94 -0.22 0.1 -0.02 -0.31 -0.91 -0.56 0.17 0.16 -0.2 0.92 -0.69 0.24 0.71 1.01 -0.21 1.54 -0.49 -0.81 0.1 1.44 -0.24 0.7 1.52 -0.52 0.54 -0.43 0.47 -0.03 -0.03 0.17 1.43 0.13 -0.91 1.52 -0.56 -0.66 -0.57 0.06 -0.65 0.98 0.79 0.62 1.38 1.46 0.12 -0.79 -0.46 1.41 0.23 -0.24 -0.15 -0.83 0.89 -0.7 0.84 0.88 -0.32 -0.75 1.41 1.17 1.37 1.08 0.27 -0.14 1.55 -0.87 -0.72 -0.95 -0.44 1.37 1.55 0.36 1.36 -0.5 -0.16 -0.79 -0.53 0.81 0.74 0.18 1.21 -0.75 1.34 0.05 0.63 0.34 0.28 0.86 0.28 -0.49 0.67 -0.62 -0.62 0.48 0.68 0.06 -0.27 -0.31 0.56 -0.3 0.08 -0.06 0.56 -0.26 -0.02 0.94 -0.51 0.25 -0.26 -0.64 1.16 -0.99 0.92 0.5 1.2 -0.5 0.44 -0.38 0.75 0.89 0.76 0.01 -0.89 -0.97 1.44 -0.65
最大准确率ac=0.83819
总代码
clc
clear all
close all
%% 加载神经网络的训练样本 测试样本每列一个样本 输入P 输出T
%样本数据就是前面问题描述中列出的数据
[x,y]=date_inscet();
randIndex=randperm(size(x,1));%打乱顺序
x=x(randIndex,:);y=y(randIndex,:);
x1=x(1:1000,:);y1=y(1:1000,:);x2=x(1001:end,:);y2=y(1001:end,:);
% 初始隐层神经元个数
hiddennum1=15;hiddennum2=5;
% 输入向量的最大值和最小值
threshold=[0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1;0 1];
inputnum=size(x,2); % 输入层神经元个数
outputnum=size(y,2); % 输出层神经元个数
w1num=inputnum*hiddennum1; % 输入层到隐层1的权值个数
w2num=hiddennum2*hiddennum1;% 隐层1到隐层2的权值个数
w3num=outputnum*hiddennum2;% 隐层2到输出层的权值个数
N=w1num+hiddennum1+w2num+hiddennum2+w3num+outputnum; %待优化的变量的个数
%% 定义遗传算法参数
NIND=40; %个体数目
MAXGEN=50; %最大遗传代数
PRECI=10; %变量的二进制位数
GGAP=0.95; %代沟
px=0.7; %交叉概率
pm=0.01; %变异概率
trace=zeros(N+1,MAXGEN); %寻优结果的初始值
%FieldD=[repmat(PRECI,1,N);repmat([-0.5;0.5],1,N);repmat([1;0;1;1],1,N)]; %区域描述器
%Chrom=crtbp(NIND,PRECI*N); %初始种群
bounds=repmat([-1;1],1,N);%所有变量范围都为【-1,1】
precision=ones([1,N])*0.01;%由求解精度确定二进制编码长度
bits=ceil(log2((bounds(2,:)-bounds(1,:)) ./ precision));%由设定精度划分区间,ceil取上整
[Pop]=InitPopGray(NIND,bits);%初始化种群
bestpop=zeros([1,size(Pop,2)]);bestac=0;
%% 优化
gen=0; %代计数器
[value] = fitness_funNew(Pop,bounds,precision,bits,x1,y1,x2,y2,hiddennum1,hiddennum2);%计算适应度
while gen<MAXGEN
fprintf('%d\n',gen)
[selectpop]=NonlinearRankSelect(value(:,2),Pop,bestpop);%排名选择
[CrossOverPop]=CrossOver(selectpop,px);%采用多点交叉和均匀交叉,且逐步增大均匀交叉的概率
[MutationPop]=Mutation(CrossOverPop,pm,5);%变异
[value] = fitness_funNew(MutationPop,bounds,precision,bits,x1,y1,x2,y2,hiddennum1,hiddennum2);%计算适应度
gen=gen+1; %代计数器增加
%获取每代的最优解及其序号,Y为最优解,I为个体的序号
[Y,I]=max(value(:,2));
trace(1:N,gen)=b2f(MutationPop(I,:),bounds,precision,bits); %记下每代的最优值
trace(end,gen)=Y; %记下每代的最优值
if Y>bestac
bestac=Y;
bestpop=MutationPop(I,:);
end
Pop=MutationPop;
end
%% 画进化图
figure(1);
plot(1:MAXGEN,trace(end,:));
grid on
xlabel('遗传代数')
ylabel('准确率的变化')
title('进化过程')
[a,b]=max(trace(end,:));
bestX=trace(1:end-1,b);
bestErr=trace(end,b);
fprintf(['最优初始权值和阈值:\nX=',num2str(bestX'),'\n最大准确率ac=',num2str(bestErr),'\n'])