文章目录
1、数据集准备
首先准备一个包含十个数字文件夹的DigitsData,每个数字文件夹里包含1000张对应这个数字的图片,图片的尺寸都是 28×28×1 像素的,如下图所示

matlab 中imageDatastore
函数会根据文件夹名称自动为图像进行分类标注。该数据集包含 10 个类别。
% 创建一个图像数据存储对象 `imds`,用于从名为 "DigitsData" 的文件夹中加载图像数据
imds = imageDatastore("DigitsData", ...
IncludeSubfolders=true, ... % 指定在加载数据时包含子文件夹中的图像
LabelSource="foldernames"); % 使用子文件夹的名称作为图像的标签(自动分类)
% 获取数据集中所有的类别名称(即文件夹名),并将其存储在变量 classNames 中
classNames = categories(imds.Labels); % 将 imds.Labels
将数据划分为训练集、验证集和测试集。使用 70% 的图像作为训练数据,15% 作为验证数据,15% 作为测试数据。指定使用 "randomized"(随机化),以便从每个类别中按指定比例随机分配图像到新的数据集中。
splitEachLabel
函数用于将图像数据存储对象划分成三个新的数据存储对象。
% 使用 splitEachLabel 函数将原始图像数据集 imds 随机划分为训练集、验证集和测试集
[imdsTrain, imdsValidation, imdsTest] = splitEachLabel(imds, 0.7, 0.15, 0.15, "randomized");
splitEachLabel
:MATLAB 中的函数,用于根据每个标签(类别)分别划分图像数据集。这样可以确保每个类别在训练集、验证集和测试集中都有代表性。imds
:原始的图像数据存储对象,包含所有图像和对应的标签。0.7
:表示将每个类别中 70% 的图像用于训练集。0.15
:表示每个类别中 15% 的图像用于验证集。0.15
:表示每个类别中 15% 的图像用于测试集。"randomized"
:表示在划分数据集时使用随机抽样,避免按文件顺序导致划分不均衡。[imdsTrain, imdsValidation, imdsTest]
:返回三个新的imageDatastore
对象,分别代表:
imdsTrain
:训练数据集imdsValidation
:验证数据集imdsTest
:测试数据集
2、网络搭建
这里,我们需要借用到matlab工具栏里APPS里的Deep Network Designer,如下图所示

在Deep Network Designer, 我们创建一个空白Designer画布

然后我们可以拖动相应的层到Designer里,并连接各个层,如下图所示

这里,我们只需要改一下输入层的InputSize就行,如下图

然后,我们可以检查这个网络可行不可行,通过Analyze按钮,就会得到这个网络的分析结果,如下图

没有错误,就可以通过Export按钮输出这个网络到Matlab工作区,这个网络被自动被命名为net_1。
3、训练网络
指定训练选项。不同选项的选择需要依赖实验分析(即通过反复试验和比较来确定最优配置)。
% 设置用于网络训练的选项,这里使用的是随机梯度下降动量法(SGDM)
% 最大训练轮数(epoch):训练过程中将整个训练集完整迭代 4 次
% 指定验证数据集,用于在训练过程中评估模型的泛化能力
% 每训练 30 个 mini-batch 执行一次验证评估
% 在训练过程中显示实时图形界面,包括损失值和准确率的变化曲线
% 指定训练期间关注的评估指标为准确率(accuracy)
% 禁止在命令行窗口输出详细训练信息(安静模式)
options = trainingOptions("sgdm", ...
MaxEpochs = 4, ...
ValidationData = imdsValidation, ...
ValidationFrequency = 30, ...
Plots = "training-progress", ...
Metrics = "accuracy", ...
Verbose = false);
trainingOptions
是 MATLAB 中用于设置神经网络训练参数的函数。
"sgdm"
是一种常用优化算法,适用于多数分类问题。
MaxEpochs=4
设置为 4 是为了快速试验,实际训练中可以设置更大,比如 10、20 甚至更多。
ValidationFrequency=30
表示每 30 次 mini-batch 后在验证集上评估一次性能,值越小越频繁,但也会增加验证的耗时。
Plots="training-progress"
是非常有用的调试和可视化工具,能帮助你观察训练是否收敛。
Verbose=false
适合在图形界面中查看结果时使用;如果希望看到文字日志,可以设置为true
。
使用 trainnet
函数训练神经网络。由于目标是分类任务,因此使用交叉熵损失函数(cross-entropy loss)。
% 使用 trainnet 函数对神经网络进行训练
net = trainnet(imdsTrain, net_1, "crossentropy", options);
imdsTrain
:训练数据集,是一个图像数据存储对象(imageDatastore),包含用于训练的图像和对应标签。net_1
:要训练的神经网络结构(可由layerGraph
或dlnetwork
等方式定义的网络)。"crossentropy"
:指定损失函数为交叉熵损失函数(cross-entropy loss),这是分类任务中最常用的损失函数,特别适用于多类分类问题。options
:训练选项,由前面设置的trainingOptions
定义,包含训练轮数、验证数据、优化器、可视化等信息。返回值:
net
:训练完成后的神经网络,包含了优化后的权重和结构,可用于后续的预测或评估。

4、测试神经网络
使用 testnet
函数对神经网络进行测试。对于单标签分类任务,评估指标为准确率(accuracy) ,即预测正确的百分比。默认情况下,testnet
函数会在可用时自动使用 GPU 。如果希望手动选择执行环境,可以使用 testnet
函数的 ExecutionEnvironment
参数进行设置。
% 使用 testnet 函数对训练好的神经网络进行验证,并评估其准确率
accuracy = testnet(net, imdsTest, "accuracy");
net
:已训练好的神经网络模型,是前面通过trainnet
得到的结果。imdsTest
:测试数据集,是一个图像数据存储对象(imageDatastore),用于测试模型的性能。"accuracy"
:评估指标,这里指定为准确率,即预测正确的样本数量占总样本数量的百分比。返回值:
accuracy
:一个介于 0 和 1 之间的小数,表示模型在测试集上的准确率。例如,accuracy = 0.93
表示模型在测试集中有 93% 的预测是正确的。
testnet
函数自动根据你的硬件情况选择在 CPU 还是 GPU 上运行。如果你想手动指定环境,比如使用 CPU,可以这样写:
accuracy = testnet(net, imdsTest, "accuracy", ExecutionEnvironment="cpu");
5、进行预测
使用 minibatchpredict
函数进行预测,并通过 scores2label
函数将预测得分转换为类别标签。默认情况下,如果有可用的 GPU,minibatchpredict
会自动使用 GPU 进行计算。
% 对测试集进行批量预测,输出每个图像对应的类别得分(概率)
scores = minibatchpredict(net, imdsValidation);
% 将得分(scores)转换为类别标签,使用 classNames 映射到原始类名
YValidation = scores2label(scores, classNames);
可视化部分预测结果:
% 获取测试集图像的总数量
numTestObservations = numel(imdsTest.Files);
% 从测试集中随机选取 9 个样本用于可视化
idx = randi(numTestObservations, 9, 1);
% 创建一个新的图形窗口
figure
tiledlayout("flow") % 使用自动流式布局排列子图(tiled layout)
% 遍历 9 张图像,显示图像并在标题中标注预测类别
for i = 1:9
nexttile % 在下一个网格位置准备绘图
img = readimage(imdsTest, idx(i)); % 读取第 idx(i) 张图像
imshow(img) % 显示图像
title("Predicted Class: " + string(YTest(idx(i)))) % 设置标题,显示预测类别
end

6、完整代码
% 创建一个图像数据存储对象 `imds`,用于从名为 "DigitsData" 的文件夹中加载图像数据
imds = imageDatastore("DigitsData", ...
IncludeSubfolders=true, ... % 指定在加载数据时包含子文件夹中的图像
LabelSource="foldernames"); % 使用子文件夹的名称作为图像的标签(自动分类)
% 获取数据集中所有的类别名称(即文件夹名),并将其存储在变量 classNames 中
classNames = categories(imds.Labels); % 将 imds.Labels
%%
% 使用 splitEachLabel 函数将原始图像数据集 imds 随机划分为训练集、验证集和测试集
[imdsTrain, imdsValidation, imdsTest] = splitEachLabel(imds, 0.7, 0.15, 0.15, "randomized");
% 设置用于网络训练的选项,这里使用的是随机梯度下降动量法(SGDM)
% 最大训练轮数(epoch):训练过程中将整个训练集完整迭代 4 次
% 指定验证数据集,用于在训练过程中评估模型的泛化能力
% 每训练 30 个 mini-batch 执行一次验证评估
% 在训练过程中显示实时图形界面,包括损失值和准确率的变化曲线
% 指定训练期间关注的评估指标为准确率(accuracy)
% 禁止在命令行窗口输出详细训练信息(安静模式)
options = trainingOptions("sgdm", ...
MaxEpochs = 4, ...
ValidationData = imdsValidation, ...
ValidationFrequency = 30, ...
Plots = "training-progress", ...
Metrics = "accuracy", ...
Verbose = false);
% 使用 trainnet 函数对神经网络进行训练
net = trainnet(imdsTrain, net_1, "crossentropy", options);
%%
% 使用 testnet 函数对训练好的神经网络进行验证,并评估其准确率
accuracy = testnet(net, imdsTest, "accuracy");
%%
% 对测试集进行批量预测,输出每个图像对应的类别得分(概率)
scores = minibatchpredict(net, imdsTest);
% 将得分(scores)转换为类别标签,使用 classNames 映射到原始类名
YTest = scores2label(scores, classNames);
% 获取测试集图像的总数量
numTestObservations = numel(imdsTest.Files);
% 从测试集中随机选取 9 个样本用于可视化
idx = randi(numTestObservations, 9, 1);
% 创建一个新的图形窗口
figure
tiledlayout("flow") % 使用自动流式布局排列子图(tiled layout)
% 遍历 9 张图像,显示图像并在标题中标注预测类别
for i = 1:9
nexttile % 在下一个网格位置准备绘图
img = readimage(imdsTest, idx(i)); % 读取第 idx(i) 张图像
imshow(img) % 显示图像
title("Predicted Class: " + string(YTest(idx(i)))) % 设置标题,显示预测类别
end