Main Content

使用深度网络设计器为迁移学习准备网络

此示例说明如何使用深度网络设计器为以交互方式迁移学习准备网络。

迁移学习指采用预训练的深度学习网络并对其进行微调以学习新任务的过程。使用迁移学习通常比从头开始训练网络更快、更简单。您可以使用更少的数据量将学习到的特征快速迁移到新任务中。

提取数据

提取 MathWorks Merch 数据集。这是包含 75 幅 MathWorks 商品图像的小型数据集,这些商品分属五个不同类(瓶盖、魔方、扑克牌、螺丝刀和手电筒)。数据的排列使得图像位于对应于这五个类的子文件夹中。

folderName = "MerchData";
unzip("MerchData.zip",folderName);

创建一个图像数据存储。通过图像数据存储可以存储大图像数据集合,包括无法放入内存的数据,并在神经网络的训练过程中高效分批读取图像。指定包含提取图像的文件夹,并指示子文件夹名称与图像标签对应。

imds = imageDatastore(folderName, ...
    IncludeSubfolders=true, ...
    LabelSource="foldernames");

显示一些示例图像。

numImages = numel(imds.Labels);
idx = randperm(numImages,16);
I = imtile(imds,Frames=idx);
figure
imshow(I)

提取类名称和类数目。

classNames = categories(imds.Labels);
numClasses = numel(classNames)
numClasses = 5

将数据划分为训练、验证和测试数据集。将 70% 的图像用于训练,15% 的图像用于验证,15% 的图像用于测试。splitEachLabel 函数将图像数据存储拆分为两个新数据存储。

[imdsTrain,imdsValidation,imdsTest] = splitEachLabel(imds,0.7,0.15,0.15,"randomized");

选择预训练网络

要打开深度网络设计器,请在 App 选项卡上的机器学习和深度学习下,点击该 App 的图标。您也可以从命令行打开该 App:

deepNetworkDesigner

深度网络设计器提供一些精选的预训练图像分类网络,这些网络已学习适用于各种图像的丰富特征表示。如果您的图像与最初用于训练网络的图像相似,迁移学习效果最好。如果您的训练图像是像 ImageNet 数据库中那样的自然图像,则任一预训练网络都合适。有关可用网络的列表以及如何比较它们,请参阅预训练的深度神经网络

如果您的数据与 ImageNet 数据相差很大(例如,如果您有很小的图像、频谱图或非图像数据),训练新网络可能效果更好。有关如何从头开始训练网络的示例,请参阅Get Started with Time Series Forecasting

SqueezeNet 不需要额外的支持包。对于其他预训练网络,如果您没有安装所需的支持包,则该 App 提供安装选项。

从预训练网络列表中选择 SqueezeNet,然后点击打开

浏览网络

深度网络设计器在设计器窗格中显示整个网络的缩小视图。

浏览网络图。要使用鼠标放大,请使用 Ctrl + 滚轮。要平移,请使用箭头键,或按住滚轮并拖动鼠标。选择一个层以查看其属性。取消选择所有层,以在属性窗格中查看网络摘要。

选择图像输入层 'input'。您可以看到该网络的输入大小为 227×227×3 像素。

将输入大小保存在变量 inputSize 中。

inputSize = [227 227 3];

准备要训练的网络

要使用预训练网络进行迁移学习,您必须更改类的数量以匹配新数据集。首先,找到网络中的最后一个可学习层。对于 SqueezeNet,最后一个可学习层是最后一个卷积层,'conv10'。选择 'conv10' 层。在属性窗格的底部,点击解锁层。在出现的警告对话框中,点击仍要解锁。这将解锁层属性,以便您可以使其适应新任务。

在 R2023b 之前:要使网络适应新数据,您必须替换层而不是解锁层。在新的卷积二维层中,将 FilterSize 设置为 [1 1]。

NumFilters 属性定义用于分类问题的类的数量。将 NumFilters 更改为新数据中的类数量,此示例中为 5

通过将 WeightLearnRateFactorBiasLearnRateFactor 设置为 10 来更改学习率,使新层中的学习速度快于迁移层的学习速度。

检查网络

要检查网络是否准备好进行训练,请点击分析。深度学习网络分析器报告零错误或警告,因此,网络已准备就绪,可以开始进行训练。要导出网络,请点击导出。该 App 将网络保存在变量 net_1 中。

准备要训练的数据

数据存储中图像的大小可以不同。要自动调整训练图像的大小,请使用增强的图像数据存储。数据增强还有助于防止网络过拟合和记忆训练图像的具体细节。指定要对训练图像额外执行的这些增强操作:沿垂直轴随机翻转训练图像,以及在水平和垂直方向上随机平移训练图像最多 30 个像素。

pixelRange = [-30 30];

imageAugmenter = imageDataAugmenter( ...
    RandXReflection=true, ...
    RandXTranslation=pixelRange, ...
    RandYTranslation=pixelRange);

augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain, ...
    DataAugmentation=imageAugmenter);

要在不执行进一步数据增强的情况下自动调整验证和测试图像的大小,请使用增强的图像数据存储,而不指定任何其他预处理操作。

augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);
augimdsTest = augmentedImageDatastore(inputSize(1:2),imdsTest);

指定训练选项

指定训练选项。在选项中进行选择需要经验分析。要通过运行试验探索不同训练选项配置,您可以使用Experiment Manager

  • 使用 Adam 优化器进行训练。

  • 将初始学习率设置为较小的值以减慢迁移的层中的学习速度。

  • 指定少量轮数。一轮训练是对整个训练数据集的一个完整训练周期。对于迁移学习,所需的训练轮数相对较少。

  • 指定验证数据和验证频率,以便每经过一轮训练就计算一次基于验证数据的准确度。

  • 指定小批量大小,即每次迭代中使用多少个图像。为了确保在每轮训练中都使用整个数据集,请设置小批量大小以均分训练样本的数量。

  • 在图中显示训练进度并监控准确度度量。

  • 禁用详尽输出。

options = trainingOptions("adam", ...
    InitialLearnRate=0.0001, ...
    MaxEpochs=8, ...
    ValidationData=imdsValidation, ...
    ValidationFrequency=5, ...
    MiniBatchSize=11, ...
    Plots="training-progress", ...
    Metrics="accuracy", ...
    Verbose=false);

训练神经网络

使用 trainnet 函数训练神经网络。对于分类任务,使用交叉熵损失。默认情况下,trainnet 函数使用 GPU(如果有)。使用 GPU 需要 Parallel Computing Toolbox™ 许可证和受支持的 GPU 设备。有关受支持设备的信息,请参阅GPU Computing Requirements (Parallel Computing Toolbox)。否则,trainnet 函数使用 CPU。要指定执行环境,请使用 ExecutionEnvironment 训练选项。

net = trainnet(imdsTrain,net_1,"crossentropy",options);

测试神经网络

对测试图像进行分类。要使用多个观测值进行预测,请使用 minibatchpredict 函数。要将预测分数转换为标签,请使用 scores2label 函数。minibatchpredict 函数自动使用 GPU(如果有)。

YTest = minibatchpredict(net,augimdsTest);
YTest = scores2label(YTest,classNames);

在混淆图中可视化分类准确度。

TTest = imdsTest.Labels;
figure
confusionchart(TTest,YTest);

使用新数据进行预测

对一个图像进行分类。从 JPEG 文件中读取一个图像,调整其大小,并将其转换为单精度数据类型。

im = imread("MerchDataTest.jpg");
im = imresize(im,inputSize(1:2));
X = single(im);

对图像进行分类。要使用单个观测值进行预测,请使用 predict 函数。要使用 GPU,请先将数据转换为 gpuArray

if canUseGPU
    X = gpuArray(X);
end
scores = predict(net,X);
[label,score] = scores2label(scores,classNames);

显示具有预测标签和对应分数的图像。

figure
imshow(im)
title(string(label) + " (Score: " + gather(score) + ")")

另请参阅

相关主题