一、简述
卷积神经网络是一种处理具有网格结构数据的深度学习模型,由输入层、卷积层、池化层、全连接层、输出层组成。
输出层:将图像转换为其对应的由像素值构成的二维矩阵,并存储二维矩阵
卷积层:提取图像的底层特征,在存在特征的区域确定高值,不存在的区域确定低值,计算其与卷积核的乘积值来确定得到特征图(卷积核通过在输入图像的二维矩阵上不停的移动,每一次移动都进行一次乘积的求和,作为此位置的值),整个卷积过程是一个降维过程,通过卷积核的不停移动计算,可以提取图像中最有用的特征,
池化层: 避免过拟合或维度过高,将得到的特征图再次进行特征提取,将其中最具有代表性的特征提取出来,提取方法常见有最大池化和平均池化,分别取区域中的最大值或者平均值代表最具代表性的特征
全连接层:对提取到的所有特征图进行降维,展开为一维的向量,计算得到最终的识别概率
输出层:根据全连接层的信息得到概率最大的结果
二、代码
clear
clc
%% 传入数据
%使用matlab内置的DigitDataset数据集
%定义数据集路径
%用fullfile函数构建一个文件路径,指向MATLAB安装目录下的示例数字数据集
%matlabroot表示根目录,是一个预定义变量
%'toolbox', 'nnet', 'nndemos', 'nndatasets', 'DigitDataset'为路径
digitDatasetPath = fullfile(matlabroot, 'toolbox', 'nnet', 'nndemos', 'nndatasets', 'DigitDataset');
%创建图像数据存储对象
%用imageDatastore函数创建一个图像数据存储对象imds
%digitDatasetPath指定图像所在的文件夹路径
%'IncludeSubfolders', true 表示即在指定的顶层文件夹中查找图像,也递归搜索所有子文件夹中的图像
%'LabelSource', 'foldernames' 指定图像标签的来源
imds = imageDatastore(digitDatasetPath, ...
'IncludeSubfolders', true, ...
'LabelSource', 'foldernames');
%绘出图像
figure;
%从1到10000中随机20个数
rand = randperm(10000, 20);
for i = 1:20
%在4x5的网格布局中选择第i个位置显示图像
subplot(4, 5, i);
%显示随机选中的第perm(i)个图像文件
imshow(imds.Files{rand(i)});
end
%% 数据预处理
%初始化训练集的图像数量
num_train = 750;
%用splitEachLabel函数将原始数据集分割成训练集和测试集
%第一个传入参数表示分割的数据存储对象
%第二个传入参数表示从每个类别中分配给训练集的样本数量
%randomize表示在分割时随机打乱数据顺序
[train_imds, test_imds] = splitEachLabel(imds, num_train, 'randomize');
%% 构建卷积神经网络
%设置输入图像大小为28x28的灰度图,第三个参数表示只有一个颜色通道
inputSize = [28 28 1];
%计算数据集中不同类别的数量
num_class = numel(unique(imds.Labels));
%定义网络架构
layers = [
%输入层:指定输入图像的尺寸
imageInputLayer(inputSize)
%卷积层:3x3滤波器,8个滤波器,'same'表示输出尺寸与输入相同
convolution2dLayer(3, 8, 'Padding', 'same')
%归一化层
batchNormalizationLayer
%relu激活层:引入非线性
reluLayer
%最大池化层:2x2池化窗口,步长为2,减小特征图尺寸
maxPooling2dLayer(2, 'Stride', 2)
%另一个卷积层
convolution2dLayer(3, 16, 'Padding', 'same')
batchNormalizationLayer
reluLayer
%全连接层:输出层的单元数等于类别数
fullyConnectedLayer(num_class)
%将全连接层的输出转换为概率分布
softmaxLayer
%计算分类损失
classificationLayer
];
% 设置训练选项
options = trainingOptions('sgdm', ... % 使用随机梯度下降作为优化算法
'InitialLearnRate', 0.01, ... % 初始学习率
'MaxEpochs', 10, ... % 设置最大训练周期数
'MiniBatchSize', 128, ... % 每个小批次包含128个样本
'ValidationData', test_imds, ... % 验证数据集
'ValidationFrequency', 30, ... % 每30次迭代后进行一次验证
'Verbose', false, ...
'Plots', 'training-progress');
%用trainNetwork函数训练网络
net = trainNetwork(train_imds, layers, options);
%% 测试数据
%用classify函数使用训练好的网络对测试数据集进行分类
sim_y = classify(net, test_imds);
%测试数据集的实际分类
test_y = test_imds.Labels;
%计算分类的准确率
accuracy = sum(sim_y == test_y) / numel(test_y);
%% 绘图
figure;
hold on;
%绘制实际分类的结果
plot(1:length(test_y), test_y, 'r-', 'DisplayName', '实际分类');
%表示正确的预测和错误的分类
correct_y = sim_y == test_y;
error_y = ~correct_y;
%分别绘制正确和错误分类的散点图
%用find函数正确和错误分类的位置
scatter(find(correct_y), sim_y(correct_y), 'g.', 'DisplayName', '正确分类');
scatter(find(error_y), sim_y(error_y), 'rx', 'DisplayName', '错误分类');
xlabel('样本数据');
ylabel('分类');
title('测试结果和实际结果');
legend('Location', 'best');
hold off
三、运行结果