本博客来源于CSDN机器鱼,未同意任何人转载。
更多内容,欢迎点击本专栏目录,查看更多内容。
目录
0.引言
在博客【ROA优化LSTM超参数回归】中,我们采用ROA对LSTM的学习率、迭代次数、batchsize、两个lstmlayer的节点数进行寻优,在优化过程中我们不必知道ROA的具体优化原理,只需要修改lb、ub、维度D、边界判断、适应度函数即可。今天这边篇博客,我们依旧采用此前提到的步骤对CNN的超参数进行优化,话不多说,首先我们定义一个超级简单的CNN网络进行回归预测,代码如下:
clc;clear;close all;rng(0)
%% 数据的提取
load data%数据是4输入1输出的简单数据
train_x;%4*98
train_y;%1*98
test_x;%4*42
test_y;%1*98
%转成CNN的输入格式
feature=size(train_x,1);
num_train=size(train_x,2);
num_test=size(test_x,2);
trainD=reshape(train_x,[feature,1,1,num_train]);
testD=reshape(test_x,[feature,1,1,num_test]);
targetD = train_y';
targetD_test = test_y';
%% 网络构建
layers = [
imageInputLayer([size(trainD,1) size(trainD,2) size(trainD,3)]) % 输入
convolution2dLayer(3,4,'Stride',1,'Padding','same')%核3*1 数量4 步长1 填充为same
reluLayer%relu激活
convolution2dLayer(3,8,'Stride',1,'Padding','same')%核3*1 数量8 步长1 填充为same
reluLayer%relu激活
fullyConnectedLayer(20) % 全连接层1 20个神经元
reluLayer
fullyConnectedLayer(20) % 全连接层2 20个神经元
reluLayer
fullyConnectedLayer(size(targetD,2)) %输出层
regressionLayer];
%% 网络训练
options = trainingOptions('adam', ...
'ExecutionEnvironment','cpu', ...
'MaxEpochs',30, ...
'MiniBatchSize',16, ...
'InitialLearnRate',0.01, ...
'GradientThreshold',1, ...
'shuffle','every-epoch',...
'Verbose',false);
train_again=1;% 为1就代码重新训练模型,为0就是调用训练好的网络
if train_again==1
[net,traininfo] = trainNetwork(trainD,targetD,layers,options);
save result/cnn_net net traininfo
else
load result/cnn_net
end
figure;
plot(traininfo.TrainingLoss,'b')
hold on;grid on
ylabel('损失')
xlabel('训练次数')
title('CNN')
%% 结果评价
YPred = predict(net,testD);YPred=double(YPred);
观察网络构建与训练部分的代码,我们发现至少有9个参数需要优化,分别是:迭代次数MaxEpochs、MiniBatchSize、第一层卷积层的核大小和数量、第2层卷积层的核大小和数量,以及两个全连接层的神经元数量,还有学习率InitialLearnRate(学习率放最后是因为其他的都是整数,只有这个是小数,要么放最前要么放最后,方便我们写边界判断函数与初始化种群的程序,当然放其他位置也没得问题,这只是我们的编程习惯)。
1.ROA优化CNN
步骤1:知道要优化的参数与优化范围。显然就是上面提到的9个参数。代码如下,首先改写lb与ub,然后初始化的时候注意除了学习率,其他的都是整数。并将原来里面的边界判断,改成了Bounds函数,方便在计算适应度函数值的时候转化成整数与小数。如果学习率的位置不在最后,而是在其他位置,就需要改随机初始化位置和Bounds函数与fitness函数里对应的地方,具体怎么改就不说了,很简单。
function [Rbest,Convergence_curve,process]= roa_cnn(X1,y1,Xt,yt)
D=9;%一共有9个参数需要优化,分别是迭代次数、batchsize、第一层卷积层的核大小、和数量、第2层卷积层的核大小、和数量,以及两个全连接层的神经元数量,学习率
lb= [10 16 1 1 1 1 1 1 0.001]; % 下边界
ub= [50 256 3 20 3 20 50 50 0.01]; % 上边界
% 迭代次数的范围是10-50 batchsize的范围是16-256 核大小的范围是1-3 核数量的范围是1-20 全连接层的范围是1-50
% 学习率的范围是0.001-0.01
sizepop=5;
maxgen=10;% maxgen 为最大迭代次数,
% sizepop 为种群规模
%记D为维度,lb、 ub分别为搜索上、下限
R=ones(sizepop,D);%预设种群
for i=1:sizepop%随机初始化位置
for j=1:D
if j==D%除了学习率 其他的都是整数
R( i, j ) = (ub(j)-lb(j))*rand+lb(j);
else
R( i, j ) = round((ub(j)-lb(j))*rand+lb(j));
end
end
end
for k= 1:sizepop
Fitness(k)=fitness(R(k,:),X1,y1,Xt,yt);%个体适应度
end
[Fbest,elite]= min(Fitness);%Fbest为最优适应度值
Rbest= R(elite,:);%最优个体位置
H=zeros(1,sizepop);%控制因子
%主循环
for iter= 1:maxgen
Rpre= R;%记录上一代的位置
V=2*(1-iter/maxgen);
B= 2*V*rand-V;
a=-(1 + iter/maxgen);
alpha=rand*(a-1)+ 1;
for i= 1:sizepop
if H(i)==0
dis = abs(Rbest-R(i,:));
R(i,:)= R(i,:)+ dis* exp(alpha)*cos(2*pi* alpha);
else
RAND= ceil(rand*sizepop);%随机选择一个个体
R(i,:)= Rbest -(rand*0.5*(Rbest + R(RAND,:))- R(RAND,:));
end
Ratt= R(i,:)+ (R(i,:)- Rpre(i,:))*randn;%作出小幅度移动
%边界吸收
R(i, : ) = Bounds( R(i, : ), lb, ub );%对超过边界的变量进行去除
Ratt = Bounds( Ratt, lb, ub );%对超过边界的变量进行去除
Fitness(i)=fitness(R(i,:),X1,y1,Xt,yt);
Fitness_Ratt= fitness(Ratt,X1,y1,Xt,yt);
if Fitness_Ratt < Fitness(i)%改变寄主
if H(i)==1
H(i)=0;
else
H(i)=1;
end
else %不改变寄主
A= B*(R(i,:)-rand*0.3*Rbest);
R(i,:)=R(i,:)+A;
end
R(i, : ) = Bounds( R(i, : ), lb, ub );%对超过边界的变量进行去除
end
%更新适应度值、位置
[fbest,elite] = min(Fitness);
%更新最优个体
if fbest< Fbest
Fbest= fbest;
Rbest= R(elite,:);
end
process(iter,:)=Rbest;
Convergence_curve(iter)= Fbest;
iter,Fbest,Rbest
end
end
function s = Bounds( s, Lb, Ub)
temp = s;
dim=length(Lb);
for i=1:length(s)
if i==dim%除了学习率 其他的都是整数
temp(:,i) =temp(:,i);
else
temp(:,i) =round(temp(:,i));
end
end
% 判断参数是否超出设定的范围
for i=1:length(s)
if temp(:,i)>Ub(i) | temp(:,i)<Lb(i)
if i==dim%除了学习率 其他的都是整数
temp(:,i) =rand*(Ub(i)-Lb(i))+Lb(i);
else
temp(:,i) =round(rand*(Ub(i)-Lb(i))+Lb(i));
end
end
end
s = temp;
end
步骤2:知道优化的目标。优化的目标是提高的网络的准确率,而ROA代码我们这个代码是最小值优化的,所以我们的目标可以是最小化CNN的预测误差。预测误差具体是,测试集(或验证集)的预测值与真实值之间的均方差。
步骤3:构建适应度函数。通过步骤2我们已经知道目标,即采用ROA去找到9个值,用这9个值构建的CNN网络,误差最小化。观察下面的代码,首先我们将ROA的值传进来,然后转成需要的9个值,然后构建网络,训练集训练、测试集预测,计算预测值与真实值的mse,将mse作为结果传出去作为适应度值。
function y=fitness(x,trainD,targetD,testD,targetD_test)
rng(0)
%% 将传进来的值 转换为需要的超参数
iter=x(1);
minibatch=x(2);
kernel1_size=x(3);
kernel1_num=x(4);
kernel2_size=x(5);
kernel2_num=x(6);
fc1_num=x(7);
fc2_num=x(8);
lr=x(9);
feature=size(trainD,1);
%% 利用寻优得到参数重新训练CNN与预测
layers = [
imageInputLayer([size(trainD,1) size(trainD,2) size(trainD,3)])
convolution2dLayer(kernel1_size,kernel1_num,'Stride',1,'Padding','same')
reluLayer
convolution2dLayer(kernel2_size,kernel2_num,'Stride',1,'Padding','same')
reluLayer
fullyConnectedLayer(fc1_num)
reluLayer
fullyConnectedLayer(fc2_num)
reluLayer
fullyConnectedLayer(size(targetD,2))
regressionLayer];
options = trainingOptions('adam', ...
'ExecutionEnvironment','cpu', ...
'MaxEpochs',iter, ...
'MiniBatchSize',minibatch, ...
'InitialLearnRate',lr, ...
'GradientThreshold',1, ...
'shuffle','every-epoch',...
'Verbose',false);
net = trainNetwork(trainD,targetD,layers,options);
YPred = predict(net,testD);
%% 适应度值计算
YPred=double(YPred);
%以CNN的预测值与实际值的均方误差最小化作为适应度函数,SSA的目的就是找到一组超参数
%用这组超参数训练得到的CNN的误差能够最小化
[m,n]=size(YPred);
YPred=reshape(YPred,[1,m*n]);
targetD_test=reshape(targetD_test,[1,m*n]);
y=mse(YPred,targetD_test);
rng(sum(100*clock))
2.主程序调用
clc;clear;close all;format compact;rng(0)
%% 数据的提取
load data
load data%数据是4输入1输出的简单数据
train_x;%4*98
train_y;%1*98
test_x;%4*42
test_y;%1*98
feature=size(train_x,1);
num_train=size(train_x,2);
num_test=size(test_x,2);
trainD=reshape(train_x,[feature,1,1,num_train]);
testD=reshape(test_x,[feature,1,1,num_test]);
targetD = train_y';
targetD_test = test_y';
%% ROA优化CNN的超参数
%一共有9个参数需要优化,分别是学习率、迭代次数、batchsize、第一层卷积层的核大小、和数量、第2层卷积层的核大小、和数量,以及两个全连接层的神经元数量
optimaztion=1;
if optimaztion==1
[x,trace,process]=roa_cnn(trainD,targetD,testD,targetD_test);
save result/roa_result x trace process
else
load result/roa_result
end
%%
figure
plot(trace)
title('适应度曲线')
xlabel('优化次数')
ylabel('适应度值')
disp('优化后的各超参数')
iter=x(1)%迭代次数
minibatch=x(2)%batchsize
kernel1_size=x(3)
kernel1_num=x(4)%第一层卷积层的核大小与核数量
kernel2_size=x(5)
kernel2_num=x(6)%第2层卷积层的核大小与核数量
fc1_num=x(7)
fc2_num=x(8)%两个全连接层的神经元数量
lr=x(9)%学习率
%% 利用寻优得到参数重新训练CNN与预测
rng(0)
layers = [
imageInputLayer([size(trainD,1) size(trainD,2) size(trainD,3)])
convolution2dLayer(kernel1_size,kernel1_num,'Stride',1,'Padding','same')
reluLayer
convolution2dLayer(kernel2_size,kernel2_num,'Stride',1,'Padding','same')
reluLayer
fullyConnectedLayer(fc1_num)
reluLayer
fullyConnectedLayer(fc2_num)
reluLayer
fullyConnectedLayer(size(targetD,2))
regressionLayer];
options = trainingOptions('adam', ...
'ExecutionEnvironment','cpu', ...
'MaxEpochs',iter, ...
'MiniBatchSize',minibatch, ...
'InitialLearnRate',lr, ...
'GradientThreshold',1, ...
'Verbose',false);
train_again=1;% 为1就重新训练模型,为0就是调用训练好的网络
if train_again==1
[net,traininfo] = trainNetwork(trainD,targetD,layers,options);
save result/roacnn_net net traininfo
else
load result/roacnn_net
end
figure;
plot(traininfo.TrainingLoss,'b')
hold on;grid on
ylabel('损失')
xlabel('训练次数')
title('roa-CNN')
%% 结果评价
YPred = predict(net,testD);YPred=double(YPred);
3.结语
优化网络超参数的格式都是这样的!只要会改一种,那么随便拿一份能跑通的优化算法,在不管原理的情况下,都能用来优化网络的超参数。更多内容【点击专栏】目录。