系列文章目录
深度学习实战——利用卷积神经网络对手写数字二值图像分类(附代码)
目录
前言
本案例利用MATLAB中的DL Toolbox构建了一个浅层的卷积神经网络,用于0-9二值数字图像分类并计算分类准确率。
一、案例需求
本案例的目标为构建一个卷积神经网络,可实现对输入的含有0-9数字的二值图像(像素数为28×28)进行分类,并计算分类准确率。(图像数据全部来自MATLAB根目录下的DigitDataset文件)
二、MATLAB算法实现
Step1:清除内存、清空命令行窗口
clear
clc
Step2:创建并加载图像样本数据
digitDatasetPath = fullfile(matlabroot,'toolbox','nnet','nndemos', ...
'nndatasets','DigitDataset');
%创建图像集,fullfile 函数作用是作用是利用文件各部分信息创建并合并成完整文件名,同时读取多个文件夹路径;matlabroot的位置表示大文件夹,这里指的是matlab根目录文件,后面引号中的指的是大文件夹中的子文件夹,DigitDataset文件夹中包含数字0-9的全部形态类型,每个数字有1000张图片,10个数字共有10000张图片
imds = imageDatastore(digitDatasetPath, ...
'IncludeSubfolders',true,'LabelSource','foldernames'); %imds为图像样本数据,
imageDatastore用于数据集读取;digitDatasetPath这里指从上一步整合的资料库中读取数据;IncludeSubfolders :是否继续读取子文件夹中的图像数据,为 true 表示继续读取。LabelSource :图像标签的来源是什么;'foldernames':子文件夹名称
![](https://i-blog.csdnimg.cn/blog_migrate/2d2b6a07aa36adf83afba894e8c7307f.png)
Step3:显示二值图像
figure; %建立空幕布
perm = randperm(10000,20); %随机打乱一个数字序列,表示从10000张图片中中随机选择20张图片
for i = 1:20 %开始循环取图并放置在幕布中
subplot(4,5,i); %subplot将当前图窗划分为4×5的网格,并在指定的位置i创建坐标区
imshow(imds.Files{perm(i)}); %imshow函数用于在窗口中显示二值图像
end
![](https://i-blog.csdnimg.cn/blog_migrate/583d64f1f10a78f3a852873c5a7680ae.png)
Step4:将加载的图像样本分为训练集和测试集
(注:在本例中,训练集的数量为750幅,剩余的为测试集,一张图中总像素数28*28=784,测试集的数量为34)
numTrainFiles = 750; %设置训练集像素个数
[imdsTrain,imdsValidation] = splitEachLabel(imds,numTrainFiles,'randomize'); %imdsTrain,imdsValidation为训练集和验证集,把imds拆分成训练集和验证集,splitEachLabel用于拆分数据集,randomize为随机拆分
Step5:构建卷积神经网络
这里构建了一个二维单通道的3卷积层神经网络,激活函数采用ReLU函数,加入批量归一化层加快网络收敛。
layers = [
imageInputLayer([28 28 1]) % 输入层,一张图片像素为28×28,1个通道
convolution2dLayer([3 3],8,'Padding','same')
% 二维卷积层1:卷积核大小为3×3,卷积核的个数为8(每个卷积核的通道数与输入图像的通道数相等,本层中每个卷积核1个通道)卷积的方式采用零填充方式(即设定为same方式)
batchNormalizationLayer % 批量归一化层1(加快网络收敛)
reluLayer % ReLu非线性激活函数1(relu函数的作用就是增加了神经网络各层之间的非线性关系)
maxPooling2dLayer(2,'Stride',2) % 二维池化层1:池化方式:最大池化;池化区域为2×2(第一个2),步长为2(第二个2)
convolution2dLayer([3 3],16,'Padding','same')
% 卷积层2:卷积核大小为3×3,卷积核的个数为16(每个卷积核的通道数与输入特征图的通道数相等,本层中每个卷积核1个通道)卷积的方式采用零填充方式(即设定为same方式)
batchNormalizationLayer % 批量归一化层2
reluLayer % ReLu非线性激活函数2
maxPooling2dLayer(2,'Stride',2) % 池化层2:池化方式:最大池化;池化区域为2×2,步长为2
convolution2dLayer([3 3],32,'Padding','same')
% 卷积层3:卷积核大小为3×3,卷积核的个数为32(每个卷积核的通道数与输入特征图的通道数相等,本层中每个卷积核1个通道)卷积的方式采用零填充方式(即设定为same方式)
batchNormalizationLayer % 批量归一化层3
reluLayer % ReLu非线性激活函数3
maxPooling2dLayer(2,'Stride',2) % 池化层3:池化方式:最大池化;池化区域为2×2,步长为2
fullyConnectedLayer(10) % 全连接层:将全连接层输出的个数设置为10个(全连接层用于将特征表示整合成一个值)
softmaxLayer % softmaxLayer层:将数值缩放到0-1之内,输出每个输出的概率
classificationLayer ]; % 分类层:根据上一层的输入的概率,进行分类并输出
Step6:配置训练选项并开始训练
options = trainingOptions('sgdm', ...
'InitialLearnRate',0.01, ...
'MaxEpochs',4, ...
'Shuffle','every-epoch', ...
'ValidationData',imdsValidation, ...
'ValidationFrequency',30, ...
'Verbose',false, ...
'Plots','training-progress');
% 配置训练选项
%'sgdm'表示使用具有动量Momentum的随机梯度下降方法来训练网络;
% 'InitialLearnRate'设置初始学习率为0.01;
% 'MaxEpochs'将最大训练轮数设置为4;
% 'Shuffle'表示打乱数据;
% 'every-epoch'则代表每一轮训练都打乱一次数据;
% 'ValidationData'用于设置验证数据集,'ValidationFrequency'设置验证频率为30;
% 'Verbose'设置为false则不显示进度信息;
% 'Plots'打开训练进度图。
net = trainNetwork(imdsTrain,layers,options); %对网络进行训练,imdsTrain为训练集数据,layers是构建的网络,options是训练选项
Step7:将训练好的网络用于对新的输入图像进行分类,并计算准确率
YPred = classify(net,imdsValidation); %输入验证集imdsValidation,classify调用网络中的分类器进行分类预测,将分类结果赋给YPred
YValidation = imdsValidation.Labels; %提取验证集的分类标签
accuracy = sum(YPred == YValidation)/numel(YValidation)
%准确率计算,YPred == YValidation表示判断预测值和实际值相等的个数,相等计1,不相等计0,求和,numel用于计数,相等总数/验证集总数=准确率
![](https://i-blog.csdnimg.cn/blog_migrate/fefe875b5cac818a78715014c14f3f83.png)
三、MATLAB源代码
%% 步骤1:清除内存、清空命令行窗口
clear
clc
%% 步骤2:创建并加载图像样本数据
digitDatasetPath = fullfile(matlabroot,'toolbox','nnet','nndemos', ...
'nndatasets','DigitDataset'); %创建图像集,fullfile 函数作用是作用是利用文件各部分信息创建并合并成完整文件名,同时读取多个文件夹路径;matlabroot的位置表示大文件夹,这里指的是matlab根目录文件,后面引号中的指的是大文件夹中的子文件夹,DigitDataset文件夹中包含数字0-9的全部形态类型,每个数字有1000张图片,10个数字共有10000张图片
imds = imageDatastore(digitDatasetPath, ...
'IncludeSubfolders',true,'LabelSource','foldernames'); %imds为图像样本数据,imageDatastore用于数据集读取;digitDatasetPath这里指从上一步整合的资料库中读取数据;IncludeSubfolders :是否继续读取子文件夹中的图像数据,为 true 表示继续读取。LabelSource :图像标签的来源是什么;'foldernames':子文件夹名称
%% 步骤3:显示二值图像
figure; %建立空幕布
perm = randperm(10000,20); %随机打乱一个数字序列,表示从10000张图片中中随机选择20张图片
for i = 1:20 %开始循环取图并放置在幕布中
subplot(4,5,i); %subplot将当前图窗划分为4×5的网格,并在指定的位置i创建坐标区
imshow(imds.Files{perm(i)}); %imshow函数用于在窗口中显示二值图像
end
%% 步骤4:将加载的图像样本分为训练集和测试集(注:在本例中,训练集的数量为750幅,剩余的为测试集,一张图中总像素数28*28=784,测试集的数量为34)
numTrainFiles = 750; %设置训练集像素个数
[imdsTrain,imdsValidation] = splitEachLabel(imds,numTrainFiles,'randomize'); %imdsTrain,imdsValidation为训练集和验证集,把imds拆分成训练集和验证集,splitEachLabel用于拆分数据集,randomize为随机拆分
%% 步骤5:构建卷积神经网络
layers = [
imageInputLayer([28 28 1]) % 输入层,一张图片像素为28×28,1个通道
convolution2dLayer([3 3],8,'Padding','same')% 二维卷积层1:卷积核大小为3×3,卷积核的个数为8(每个卷积核的通道数与输入图像的通道数相等,本层中每个卷积核1个通道)卷积的方式采用零填充方式(即设定为same方式)
batchNormalizationLayer % 批量归一化层1(加快网络收敛)
reluLayer % ReLu非线性激活函数1(relu函数的作用就是增加了神经网络各层之间的非线性关系)
maxPooling2dLayer(2,'Stride',2) % 二维池化层1:池化方式:最大池化;池化区域为2×2(第一个2),步长为2(第二个2)
convolution2dLayer([3 3],16,'Padding','same')% 卷积层2:卷积核大小为3×3,卷积核的个数为16(每个卷积核的通道数与输入特征图的通道数相等,本层中每个卷积核1个通道)卷积的方式采用零填充方式(即设定为same方式)
batchNormalizationLayer % 批量归一化层2
reluLayer % ReLu非线性激活函数2
maxPooling2dLayer(2,'Stride',2) % 池化层2:池化方式:最大池化;池化区域为2×2,步长为2
convolution2dLayer([3 3],32,'Padding','same')% 卷积层3:卷积核大小为3×3,卷积核的个数为32(每个卷积核的通道数与输入特征图的通道数相等,本层中每个卷积核1个通道)卷积的方式采用零填充方式(即设定为same方式)
batchNormalizationLayer % 批量归一化层3
reluLayer % ReLu非线性激活函数3
maxPooling2dLayer(2,'Stride',2) % 池化层3:池化方式:最大池化;池化区域为2×2,步长为2
fullyConnectedLayer(10) % 全连接层:将全连接层输出的个数设置为10个(全连接层用于将特征表示整合成一个值)
softmaxLayer % softmaxLayer层:将数值缩放到0-1之内,输出每个输出的概率
classificationLayer ]; % 分类层:根据上一层的输入的概率,进行分类并输出
%% 步骤6:配置训练选项并开始训练
options = trainingOptions('sgdm', ...
'InitialLearnRate',0.01, ...
'MaxEpochs',4, ...
'Shuffle','every-epoch', ...
'ValidationData',imdsValidation, ...
'ValidationFrequency',30, ...
'Verbose',false, ...
'Plots','training-progress');
% 配置训练选项
%'sgdm'表示使用具有动量Momentum的随机梯度下降方法来训练网络;
% 'InitialLearnRate'设置初始学习率为0.01;
% 'MaxEpochs'将最大训练轮数设置为4;
% 'Shuffle'表示打乱数据;
% 'every-epoch'则代表每一轮训练都打乱一次数据;
% 'ValidationData'用于设置验证数据集,'ValidationFrequency'设置验证频率为30;
% 'Verbose'设置为false则不显示进度信息;
% 'Plots'打开训练进度图。
net = trainNetwork(imdsTrain,layers,options); %对网络进行训练,imdsTrain为训练集数据,layers是构建的网络,options是训练选项
%% 步骤7:将训练好的网络用于对新的输入图像进行分类,并计算准确率
YPred = classify(net,imdsValidation); %输入验证集imdsValidation,classify调用网络中的分类器进行分类预测,将分类结果赋给YPred
YValidation = imdsValidation.Labels; %提取验证集的分类标签
accuracy = sum(YPred == YValidation)/numel(YValidation) %准确率计算,YPred == YValidation表示判断预测值和实际值相等的个数,相等计1,不相等计0,求和,numel用于计数,相等总数/验证集总数=准确率
参考文献
《深度学习理论及实战(MATLAB版)》清华大学出版社 . 赵小川、何灏著