赞
踩
在CNN分类器模型的构建中,涉及到特别多的超参数,比如:学习率、训练次数、batchsize、各个卷积层的卷积核大小与卷积核数量(feature map数),全连接层的节点数等。直接选择的话,很难选到一组满意的参数,因此可以用优化算法进行超参数优化,虽然过程比较慢,但是总比自己无脑试的效果好。
基于此思想,本文采用麻雀优化算法,对CNN上述9个超参数进行优化。
1,麻雀优化算法原理
麻雀优化是2020年提出来得,具体原理:原理点这里
2、麻雀优化CNN的原理
一般情况下进行参数的优化的时候,就是给CNN网络设一组超参数,然后训练并验证,取验证集精度最高的那个模型(这个模型就可以认为具有最优超参数)。其实优化算法也是这样,它们都是不断地产生新的超参数组合,然后用这组超参数建立CNN网络,训练并验证。只不过,优化算法是有自己的学习规律。我们对CNN超参数进行优化,也就是让SSA一直有去找能够让验证集满足精度最大化的那一组超参数。
3、代码实现:
数据是10分类,每个样本的特征维度是864,。共1000个样本,按照7:2:1划分训练集,验证集与测试集,标签是类比即可,不用转换为onehot编码。
3.1 CNN分类模型
- clc;clear;close all
- %% read data
- load('result/data_process.mat');
- method=@mapstd;
- % method=@mapminmax;
- [xs,mapping]=method(train_X');train_X=xs';
- xs=method('apply',test_X',mapping);test_X=xs';
- xs=method('apply',valid_X',mapping);valid_X=xs';
- N_train=size(train_X,1);
- N_feature=size(train_X,2);
- for i=1:N_train
- trainD(:,:,:,i)=reshape(train_X(i,:),[N_feature 1 1]);
- end
- N_valid=size(valid_X,1);
- for i=1:N_valid
- XValidation(:,:,:,i)=reshape(valid_X(i,:),[N_feature 1 1]);
- end
- N_test=size(test_X,1);
- for i=1:N_test
- testD(:,:,:,i)=reshape(test_X(i,:),[N_feature 1 1]);
- end
- targetD=categorical(train_Y);
-
- YValidation=categorical(valid_Y);
-
- target_testD=categorical(test_Y);
- %% define network
- layers = [
- imageInputLayer([size(trainD,1) ,size(trainD,2), size(trainD,3)]) %
- convolution2dLayer(5,8,'Padding','same') % 5x5 filtr ,8 kernel padding=‘same’,stride=1(default)
- % batchNormalizationLayer% batch Normalization
- reluLayer % relu activation function
- maxPooling2dLayer(2,'Stride',2,'Padding','same')% 2x2 kernel stride=2,padding=1
-
- convolution2dLayer(5,16,'Padding','same') % 5x5 filtr ,16 kernel padding=‘same’,stride=1(default)
- % batchNormalizationLayer
- reluLayer % relu activation function
- maxPooling2dLayer(2,'Stride',2,'Padding','same')% 2x2 kernel stride=2
-
- fullyConnectedLayer(128) %fc 128
- reluLayer
- fullyConnectedLayer(10) % classes
- softmaxLayer
- classificationLayer];
-
- options = trainingOptions('adam',...
- 'ExecutionEnvironment','cpu', ...
- 'MaxEpochs',10, ...
- 'InitialLearnRate',1e-3, ...
- 'MiniBatchSize',16, ...
- 'shuffle','every-epoch',...
- 'Verbose',false);
- % analyzeNetwork(layers)
- %% train
- 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;
- yyaxis left; % 激活左边的轴
- plot(traininfo.TrainingLoss);
- title('CNN');
- xlabel('训练次数');
- ylabel('损失值'); % 给左y轴添加轴标签
- yyaxis right; % 激活右边的轴
- plot(traininfo.TrainingAccuracy);
- ylabel('正确率'); % 给右y轴添加轴标签
- %% test
- predictedLabels = classify(net,testD);
- save result/cnn_result target_testD predictedLabels
-
- disp('测试集分类正确率为:')
- acc=sum(target_testD==predictedLabels)/length(target_testD)
-
-
上面是CNN的损失曲线与正确率曲线,下面是测试集输入训练好的网络得到的正确率,为85%。
3.2 SSA优化CNN分类模型
- clc;clear;close all;format compact;rng(0)
- %% 数据处理
- load('result/data_process.mat');
- method=@mapstd;
- % method=@mapminmax;
- [xs,mapping]=method(train_X');train_X=xs';
- xs=method('apply',test_X',mapping);test_X=xs';
- xs=method('apply',valid_X',mapping);valid_X=xs';
- N_train=size(train_X,1);
- N_feature=size(train_X,2);
- for i=1:N_train
- trainD(:,:,:,i)=reshape(train_X(i,:),[N_feature 1 1]);
- end
- N_valid=size(valid_X,1);
- for i=1:N_valid
- XValidation(:,:,:,i)=reshape(valid_X(i,:),[N_feature 1 1]);
- end
- N_test=size(test_X,1);
- for i=1:N_test
- testD(:,:,:,i)=reshape(test_X(i,:),[N_feature 1 1]);
- end
-
- targetD=categorical(train_Y);
-
- YValidation=categorical(valid_Y);
-
- target_testD=categorical(test_Y);
-
- %% SSA优化CNN的超参数
- %一共有9个参数需要优化,分别是学习率、迭代次数、batchsize、第一层卷积层的核大小、和数量、第2层卷积层的核大小、和数量,以及两个全连接层的神经元数量
- optimize=1;%optimize为1就优化 不然就调用之前优化得到的参数直接训练测试
- if optimize==1
- [x,trace]=ssa_cnn(trainD,targetD,XValidation,YValidation);
- save result/ssa_result x trace
- else
- load result/ssa_result
- end
- figure
- plot(trace)
- title('适应度曲线')
- xlabel('优化次数')
- ylabel('适应度值')
-
- disp('优化后的各超参数')
- lr=x(1)%学习率
- iter=x(2)%迭代次数
- minibatch=x(3)%batchsize
- kernel1_size=x(4)
- kernel1_num=x(5)%第一层卷积层的核大小
- kernel2_size=x(6)
- kernel2_num=x(7)%第2层卷积层的核大小
- fc1_num=x(8)
- fc2_num=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')
- % batchNormalizationLayer
- reluLayer
- maxPooling2dLayer(2,'Stride',2,'Padding','same')% 2x2 kernel stride=2,padding=1
-
- convolution2dLayer(kernel2_size,kernel2_num,'Stride',1,'Padding','same')
- % batchNormalizationLayer
- reluLayer
- maxPooling2dLayer(2,'Stride',2,'Padding','same')% 2x2 kernel stride=2,padding=1
-
- fullyConnectedLayer(fc1_num)
- reluLayer
- fullyConnectedLayer(fc2_num)
- reluLayer
- fullyConnectedLayer(10)
- softmaxLayer
- classificationLayer];
- options = trainingOptions('adam', ...
- 'ExecutionEnvironment','cpu', ...
- 'MaxEpochs',iter, ...
- 'MiniBatchSize',minibatch, ...
- 'InitialLearnRate',lr, ...
- '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/ssacnn_net net traininfo
- else
-
- load result/ssacnn_net
- end
-
- figure;
- yyaxis left; % 激活左边的轴
- plot(traininfo.TrainingLoss);
- title('SSA-CNN');
- xlabel('训练次数');
- ylabel('损失值'); % 给左y轴添加轴标签
- yyaxis right; % 激活右边的轴
- plot(traininfo.TrainingAccuracy);
- ylabel('正确率'); % 给右y轴添加轴标签
- %%
- predictedLabels = classify(net,testD);
- save result/ssa_cnn_result target_testD predictedLabels
-
- disp('测试集分类正确率为:')
- acc=sum(target_testD==predictedLabels)/length(target_testD)
-
以最小化验证集分类错误率为适应度函数,目的就是找到一组超参数,使得网络错误率最低。所以适应度曲线是一条下降的曲线
利用上述最优参数,训练CNN,结果如下:
可以看到测试集正确率为94%,具有明显提升。
4.代码
代码见评论区,还有更多哦
1.MATLAB麻雀优化CNN超参数分类
2.MATLAB麻雀优化CNN超参数回归
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。