深圳幻海软件技术有限公司 欢迎您!

Matlab深度学习入门实例:从0搭建卷积神经网络CNN(附完整代码)

2023-02-28

网上已具有大量卷积神经网络的讲解,故本文不在对此赘述,这篇文章针对已了解CNN基础结构和原理者,以一个例子搭建一个简单的卷积神经网络,作为正式迈入深度学习的第一步。我们以深度学习最经典的案例——手写数字的识别,和一种经典的CNN——LeNet进行本次学习。Matlab的功能十分强大,其自带的深度学习

网上已具有大量卷积神经网络的讲解,故本文不在对此赘述,这篇文章针对已了解CNN基础结构和原理者,以一个例子搭建一个简单的卷积神经网络,作为正式迈入深度学习的第一步。

我们以深度学习最经典的案例——手写数字的识别,和一种经典的CNN——LeNet进行本次学习。

Matlab的功能十分强大,其自带的深度学习工具箱可以使我们免于编写底层算法,迅速地搭建出一个卷积神经网络,同时,其自带手写数字图片以供学习,地址如下,笔者使用的是Matlab2022a。

我们将DigitDataset拷贝到当前编写代码的文件夹下,并删除其中包含两个Excel即可得到下列图片。

 第一步,加载手写数字样本图片,代码如下:

  1. clear
  2. clc
  3. % 第一步:加载手写数字样本
  4. imds = imageDatastore( ...
  5. 'DigitDataset', ...
  6. 'IncludeSubfolders',true, ...
  7. 'LabelSource','foldernames');

'IncludeSubfolders',true:包含每个文件夹中的所有文件和子文件夹;

'LabelSource','foldernames':根据文件夹名称分配标签并储存在Labels属性中。

第二步,将样本划分为训练集和测试集,并统计分类数量,代码如下:

  1. % 第二步:
  2. % 将样本划分为训练集与测试集
  3. [imdsTrain,imdsValidation] = splitEachLabel(imds,0.7);
  4. % 统计训练集中分类标签的数量
  5. numClasses = numel(categories(imdsTrain.Labels));

imdsTrain为训练样本数据,imdsValidation为验证样本数据,0.7为训练样本的比例。

第三步,构建LeNet并进行可视化分析,代码如下:

  1. % 第三步:构建LeNET卷积网络并进行分析
  2. % 构建LeNET卷积网络
  3. LeNET= [
  4. imageInputLayer([60 20 1],'Name','input','Normalization','zscore')
  5. convolution2dLayer([5 5],6,'Padding','same','Name','Conv1')
  6. maxPooling2dLayer(2,'Stride',2,'Name','Pool1')
  7. convolution2dLayer([5 5],16,'Padding','same','Name','Conv2')
  8. maxPooling2dLayer(2,'Stride',2,'Name','Pool2')
  9. convolution2dLayer([5 5],120,'Padding','same','Name','Conv3')
  10. fullyConnectedLayer(84,'Name','fc1')
  11. fullyConnectedLayer(numClasses,'Name','fc2')
  12. softmaxLayer( 'Name','softmax')
  13. classificationLayer('Name','output')
  14. ];
  15. % 对构建的网络进行可视化分析
  16. lgraph = layerGraph(LeNET);
  17. analyzeNetwork(lgraph)

由于手写数字图片大小为60*20*1,故需调整输入层大小;

LeNet结构如下:

第一个卷积层:卷积核大小为5,数量为6,卷积方式为0填充;

第一个池化层:二维最大池化,区域为2,步长为2;

第二个卷积层:卷积核大小为5,数量为16,卷积方式为0填充;

第二个池化层:二维最大池化,区域为2,步长为2;

第三个卷积层:卷积核大小为5,数量为12,卷积方式为0填充;

第一个全连接层:输出大小为84;

第二个全连接层:输出大小为numClasses;

softmax层:得出全连接层每一个输出的概率;

classfication层:根据概率确定类别。

analyzeNetwork可以使我们对网络进行可视化分析,该代码运行结果如下图:

第四步,调整训练集和输入集的图像大小使其与LeNet输入层相同,代码如下:

  1. % 第四步:将训练集与验证集中图像的大小调整成与LeNet输入层的大小相同
  2. inputSize = [60 20 1];
  3. augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain);
  4. augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);

该步骤在此例中可以省略。

第五步:配置训练选项并对网络进行训练,代码如下:

  1. % 第五步:配置训练选项并对网络进行训练
  2. % 配置训练选项
  3. options = trainingOptions('sgdm', ...
  4. 'InitialLearnRate',0.001, ...
  5. 'MaxEpochs',3, ...
  6. 'Shuffle','every-epoch', ...
  7. 'ValidationData',augimdsValidation, ...
  8. 'ValidationFrequency',30, ...
  9. 'Verbose',true, ...
  10. 'Plots','training-progress');
  11. % 对网络进行训练
  12. net = trainNetwork(augimdsTrain,LeNET,options);

训练选项如下:

训练方法为sgdm;

初始学习率为0.001;

最大轮数为3;

'Shuffle','every-epoch': 在每一轮训练前打乱数据;

训练期间所用数据为augimdsValidation;

验证频率为30次/轮;

设置打开命令窗口输出;

设置打开训练进度图。

我们可以看到训练进度如下图:

第六步:将训练好的网络用于对新的输入图像进行分类,并计算准确率

  1. % 第六步:将训练好的网络用于对新的输入图像进行分类,并计算准确率
  2. YPred = classify(net,augimdsValidation);
  3. YValidation = imdsValidation.Labels;
  4. accuracy = sum(YPred == YValidation)/numel(YValidation)
  5. figure
  6. confusionchart(YValidation,YPred)

confusionchart可以产生混淆矩阵,以便我们更直观的看出LeNet验证的结果。

可以看到预测结果准确度比较低,对此我们可以对LeNet进行改进,增加卷积,池化层或者使用更高级的AlexNet等神经网络进行训练,本例全部代码如下:

  1. clear
  2. clc
  3. % 第一步:加载手写数字样本
  4. imds = imageDatastore( ...
  5. 'DigitDataset', ...
  6. 'IncludeSubfolders',true, ...
  7. 'LabelSource','foldernames');
  8. % 第二步:
  9. % 将样本划分为训练集与测试集
  10. [imdsTrain,imdsValidation] = splitEachLabel(imds,0.7);
  11. % 统计训练集中分类标签的数量
  12. numClasses = numel(categories(imdsTrain.Labels));
  13. % 第三步:构建LeNET卷积网络并进行分析
  14. % 构建LeNET卷积网络
  15. LeNET= [
  16. imageInputLayer([60 20 1],'Name','input','Normalization','zscore')
  17. convolution2dLayer([5 5],6,'Padding','same','Name','Conv1')
  18. maxPooling2dLayer(2,'Stride',2,'Name','Pool1')
  19. convolution2dLayer([5 5],16,'Padding','same','Name','Conv2')
  20. maxPooling2dLayer(2,'Stride',2,'Name','Pool2')
  21. convolution2dLayer([5 5],120,'Padding','same','Name','Conv3')
  22. fullyConnectedLayer(84,'Name','fc1')
  23. fullyConnectedLayer(numClasses,'Name','fc2')
  24. softmaxLayer('Name','softmax')
  25. classificationLayer('Name','output')
  26. ];
  27. % 对构建的网络进行可视化分析
  28. lgraph = layerGraph(LeNET);
  29. analyzeNetwork(lgraph)
  30. % 第四步:将训练集与验证集中图像的大小调整成与LeNet输入层的大小相同
  31. inputSize = [60 20 1];
  32. augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain);
  33. augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);
  34. % 第五步:配置训练选项并对网络进行训练
  35. % 配置训练选项
  36. options = trainingOptions( ...
  37. 'sgdm', ...
  38. 'InitialLearnRate',0.001, ...
  39. 'MaxEpochs',3, ...
  40. 'Shuffle','every-epoch', ...
  41. 'ValidationData',augimdsValidation, ...
  42. 'ValidationFrequency',30, ...
  43. 'Verbose',true, ...
  44. 'Plots','training-progress');
  45. % 对网络进行训练
  46. net = trainNetwork(augimdsTrain,LeNET,options);
  47. % 第六步:将训练好的网络用于对新的输入图像进行分类,并计算准确率
  48. YPred = classify(net,augimdsValidation);
  49. YValidation = imdsValidation.Labels;
  50. accuracy = sum(YPred == YValidation)/numel(YValidation)
  51. figure
  52. confusionchart(YValidation,YPred)

文章知识点与官方知识档案匹配,可进一步学习相关知识
Python入门技能树首页概览237982 人正在系统学习中