matlab实现卷积神经网络CNN(二)——代码实现与解析

        基于上一篇文章对于CNN网络结构的整理,我们将用matlab实现一维数据的CNN网络单\多输入和单\多输出。

        文中字母含义详情可见上一篇文章。

一、加载数据与数据集划分

clc;clear;close all;
data=load('data.csv')'; %总数据
label=load('label.csv')'; %总标签

[train_x,train_y,test_x,test_y,val_x,val_y]=spilt(data,label,0.8,0.1,0.1); 
%划分训练集、测试集和验证集

        data数据格式应为M×SN;M为一维数据的长度(即一个样本有多少个点),由于是一维数据,所以宽度N为1;SN则为样本个数。

        label数据格式应为P×SN;P代表输出特征个数(也就是单输出和多输出),SN为样本个数。

        spilt是个自定义函数,用来随机划分训练集、测试集和验证集,当然你也可以自行划分好后分别导入。

function [trainData,trainLabel,testData,testLabel,valData,valLabel]=spilt(data,label,trainRatio,testRatio,validationRatio)

% 生成随机分组索引
c = cvpartition(size(data,2), 'HoldOut', testRatio);
trainIdx = c.training;
testIdx = c.test;

% 对剩余数据再次进行随机分组
c = cvpartition(sum(trainIdx), 'HoldOut', validationRatio/(1-testRatio));
true_trainIdx=c.training;
valIdx = c.test;

% 将训练集、验证集和测试集分别保存到不同的变量中
trainData = data(:,trainIdx);
trainLabel = label(trainIdx);
valData = trainData(:,valIdx);
valLabel = trainLabel(valIdx);
testData = data(:,testIdx);
testLabel = label(testIdx);
trainData = trainData(:,true_trainIdx);
trainLabel = trainLabel(true_trainIdx);

总之,train_x、test_x和val_x数据格式应该分别为M×样本个数

           train_y、test_y和val_y数据格式应该分别为P×样本个数

二、数据预处理

%method=@mapminmax; %归一化
method=@mapstd; %标准化

[train_x,train_ps]=method(train_x,0,1);
test_x=method('apply',test_x,train_ps);
val_x=method('apply',val_x,train_ps);

[train_y,output_ps]=method(train_y,0,1);
test_y=method('apply',test_y,output_ps);
val_y=method('apply',val_y,output_ps);

选择对数据进行归一化或者标准化。

三、数据输入格式转换

trainD=reshape(train_x,[M,N,D,SN]);
%训练集输入,[单个样本长度,单个样本宽度,输入特征个数,样本数]
testD=reshape(test_x,[M,N,D,SN]);
%测试集输入,[单个样本长度,单个样本宽度,输入特征个数,样本数]
valD=reshape(val_x,[M,N,D,SN]);
%验证集输入,[单个样本长度,单个样本宽度,输入特征个数,样本数]

其中,因为是一维数据,所以N=1,下文同。

CNN的输入数据格式应为【单个样本长度,单个样本宽度,输入特征个数,样本数】;

【M,N,D,SN】。

D=1则代表单输入。

四、CNN网络结构建立

layers = [
    imageInputLayer([M N D]) %输入层参数设置,[M,N,D]
%第一层卷积层和池化层
    convolution2dLayer([64,1],128,'Padding','same')
    %[64,1]是卷积核大小,128是个数
    %对于一维数据,卷积核第二个参数为1就行了,这样就是一维卷积
    reluLayer %relu激活函数
    maxPooling2dLayer([32 1],'Stride',10)

%第二层卷积层和池化层
    convolution2dLayer([32,1],128,'Padding','same')
    reluLayer %relu激活函数
    maxPooling2dLayer([16 1],'Stride',20)

%两层全连接层
    fullyConnectedLayer(20) % 20个全连接层神经元
    reluLayer %relu激活函数
    fullyConnectedLayer(10) % 10个全连接层神经元
    fullyConnectedLayer(P) % 输出层神经元个数P
    regressionLayer];%添加回归层,用于计算损失值

        上述代码中的卷积核大小、个数等参数不具备参考意义,应当根据自身数据结构自行调整。

        convolution2dLayer代表卷积层;【64,1】是卷积核的大小,由于是一维数据,所以第二个参数为1;128是卷积核个数;'Padding','same'代表填充使得该层的神经元输入和输出个数相同。我们也可以自定义其他填充方式或者步幅大小。

详情可见官方文档:https://ww2.mathworks.cn/help/deeplearning/ref/nnet.cnn.layer.convolution2dlayer.html

        maxPooling2dLayer代表最大池化层;【32,1】是池化层大小;'Stride',10代表池化步幅。

        fullyConnectedLayer代表全连接层,最后一层全连接层需决定输出特征个数P;reluLayer代表激活函数的选择。

        regressionLayer代表回归层,也可以换成分类层softmaxLayer和classificationLayer

analyzeNetwork(net);

我们可以采用该指令来查看网络结构,包括层结构和每一层的输入输出大小。 

        有时候你的卷积核大小、个数、步幅以及池化层大小和步幅设置的不合理,导致网络出错,我们就可以通过该命令检查每一层的输入输出。比如,某一池化层的大小不能大于上一层的输出个数。

        具体可见下一篇文章,CNN结合灰狼优化算法进行超参数优化。

五、模型设置

options = trainingOptions('adam', ...%优化方法:sgdm、adam等
    'MaxEpochs',30, ...
    'MiniBatchSize',20, ...
    'InitialLearnRate',0.001, ...
    'GradientThreshold',1, ...
    'Verbose',false,...
    'ExecutionEnvironment','multi-gpu',...% GPU训练
    'Plots','training-progress',...%'none'代表不显示训练过程
    'ValidationData',{valD,val_y'});%验证集

值得一提的是验证集的输入,在很多书籍中,验证集和测试集是同一个数据集。

六、模型训练与测试

net = trainNetwork(trainD,train_y',layers,options);

% 预测
YPred = predict(net,testD);

% 结果
YPred=double(YPred');%输出是n*1的single型数据,要转换为1*n的double是数据形式

% 反归一化
predict_value=method('reverse',YPred,output_ps);predict_value=double(predict_value);
true_value=method('reverse',test_y,output_ps);true_value=double(true_value);

七、结果评估

rmse=sqrt(mean((true_value-predict_value).^2));
disp(['根均方差:',num2str(rmse)])
mae=mean(abs(true_value-predict_value));
disp(['平均绝对误差:',num2str(mae)])
maxape=max(abs((true_value-predict_value)./true_value));
disp(['最大相对百分误差:',num2str(maxape*100),'%'])
mape=mean(abs((true_value-predict_value)./true_value));
disp(['平均相对百分误差:',num2str(mape*100),'%'])

  • 40
    点赞
  • 190
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
以下是使用MATLAB实现卷积神经网络CNN并用于Mnist数据集分类的步骤: 1. 导入Mnist数据集 Mnist数据集是一个手写数字的数据集,包含了60,000张训练图片和10,000张测试图片,每张图片大小为28x28。可以通过MATLAB内置函数 `digitDataset` 来导入Mnist数据集。 ``` % 导入Mnist数据集 digitDatasetPath = fullfile(matlabroot,'toolbox','nnet','nndemos', ... 'nndatasets','DigitDataset'); digitData = imageDatastore(digitDatasetPath, ... 'IncludeSubfolders',true,'LabelSource','foldernames'); ``` 2. 划分训练集和测试集 使用 `splitEachLabel` 函数来划分训练集和测试集,将60,000张训练图片划分为50,000张训练图片和10,000张验证图片。 ``` % 划分训练集和测试集 [trainDigitData,testDigitData] = splitEachLabel(digitData,0.8,'randomized'); ``` 3. 定义卷积神经网络 使用 `convolution2dLayer` 函数来定义卷积层,使用 `maxPooling2dLayer` 函数来定义池化层,使用 `fullyConnectedLayer` 函数来定义全连接层,使用 `softmaxLayer` 函数来定义输出层。然后将这些层堆叠起来,使用 `layerGraph` 函数来定义卷积神经网络。 ``` % 定义卷积神经网络 layers = [ imageInputLayer([28 28 1]) convolution2dLayer(5,20,'Padding',0) batchNormalizationLayer reluLayer maxPooling2dLayer(2,'Stride',2) convolution2dLayer(5,50,'Padding',0) batchNormalizationLayer reluLayer maxPooling2dLayer(2,'Stride',2) fullyConnectedLayer(500) reluLayer fullyConnectedLayer(10) softmaxLayer classificationLayer]; lgraph = layerGraph(layers); ``` 4. 训练卷积神经网络 使用 `trainingOptions` 函数来定义训练选项,包括学习率、最大训练轮数、每轮训练的批次大小等。然后使用 `trainNetwork` 函数来训练卷积神经网络。 ``` % 训练卷积神经网络 options = trainingOptions('adam', ... 'InitialLearnRate',0.0001, ... 'MaxEpochs',20, ... 'MiniBatchSize',128, ... 'ValidationData',testDigitData, ... 'ValidationFrequency',10, ... 'Verbose',false, ... 'Plots','training-progress'); net = trainNetwork(trainDigitData,lgraph,options); ``` 5. 测试卷积神经网络 使用 `classify` 函数来测试卷积神经网络,将测试图片输入卷积神经网络中,得到对应的输出结果。 ``` % 测试卷积神经网络 testLabels = classify(net,testDigitData); accuracy = sum(testLabels == testDigitData.Labels)/numel(testLabels); fprintf('准确率为%.2f%%。\n',accuracy*100); ``` 完整的代码如下: ``` % 导入Mnist数据集 digitDatasetPath = fullfile(matlabroot,'toolbox','nnet','nndemos', ... 'nndatasets','DigitDataset'); digitData = imageDatastore(digitDatasetPath, ... 'IncludeSubfolders',true,'LabelSource','foldernames'); % 划分训练集和测试集 [trainDigitData,testDigitData] = splitEachLabel(digitData,0.8,'randomized'); % 定义卷积神经网络 layers = [ imageInputLayer([28 28 1]) convolution2dLayer(5,20,'Padding',0) batchNormalizationLayer reluLayer maxPooling2dLayer(2,'Stride',2) convolution2dLayer(5,50,'Padding',0) batchNormalizationLayer reluLayer maxPooling2dLayer(2,'Stride',2) fullyConnectedLayer(500) reluLayer fullyConnectedLayer(10) softmaxLayer classificationLayer]; lgraph = layerGraph(layers); % 训练卷积神经网络 options = trainingOptions('adam', ... 'InitialLearnRate',0.0001, ... 'MaxEpochs',20, ... 'MiniBatchSize',128, ... 'ValidationData',testDigitData, ... 'ValidationFrequency',10, ... 'Verbose',false, ... 'Plots','training-progress'); net = trainNetwork(trainDigitData,lgraph,options); % 测试卷积神经网络 testLabels = classify(net,testDigitData); accuracy = sum(testLabels == testDigitData.Labels)/numel(testLabels); fprintf('准确率为%.2f%%。\n',accuracy*100); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值