原文链接
此示例显示了如何微调预训练的AlexNet卷积神经网络,以对新的图像集合进行分类。
AlexNet已经接受了超过一百万张图像的培训,可以将图像分类为1000个对象类别(例如键盘,咖啡杯,铅笔和许多动物)。该网络已经为各种图像学习了丰富的功能表示。网络将图像作为输入,并输出图像中对象的标签以及每个对象类别的概率。
转移学习通常用于深度学习应用程序。您可以采用经过预训练的网络,并将其用作学习新任务的起点。与使用从头开始随机初始化的权重训练网络相比,使用迁移学习对网络进行微调通常会更快,更容易。您可以使用少量训练图像将学习到的功能快速转移到新任务中。
图1. 预训练好的AlexNet网络
载入数据
解压缩并将新图像加载为图像数据存储。imageDatastore
根据文件夹名称自动标记图像,并将数据存储为ImageDatastore
对象。图像数据存储库使您可以存储大的图像数据(包括内存中不适合的数据),并在训练卷积神经网络期间有效地读取一批图像。
unzip('MerchData.zip');
imds = imageDatastore('MerchData', ...
'IncludeSubfolders',true, ...
'LabelSource','foldernames');
将数据分成训练和测试集,70%用于训练,30%用于测试。splitEachLabel
将图片分成两部分。
[imdsTrain,imdsValidation] = splitEachLabel(imds,0.7,'randomized');
这个小的数据集包含55个训练图片和20个验证图片,展示一下这些图片。
numTrainImages = numel(imdsTrain.Labels);
idx = randperm(numTrainImages,16);
figure
for i = 1:16
subplot(4,4,i)
I = readimage(imdsTrain,idx(i));
imshow(I)
end
加载预训练好的网络
加载预训练的AlexNet神经网络。如果未安装_用于AlexNet网络的_Deep Learning Toolbox™模型,则该软件将提供下载链接。AlexNet接受了超过一百万张图像的培训,可以将图像分类为1000种对象类别,例如键盘,鼠标,铅笔和许多动物。结果,该模型为各种图像学习了丰富的特征表示。
net = alexnet;
使用analyzeNetwork
展示网络架构和许多关于网络层的接口。
analyzeNetwork(net)
图3. 网络的可视化
第一层,是图片的输入层,要求输入图片的大小为227x227x3,这个3是指的彩色图的3通道。
inputSize = net.Layers(1).InputSize
inputSize = 1×3
227 227 3
换掉最后一层
预训练网络的最后三层net
配置为1000个班级。对于新的分类问题,必须对这三层进行微调。从预训练的网络中提取除最后三层以外的所有层。
layersTransfer = net.Layers(1:end-3);
通过将最后三层替换为完全连接的层,softmax层和分类输出层,将层转移到新的分类任务。根据新数据指定新的完全连接层的选项。将完全连接的层设置为与新数据中的类数相同的大小。要在新层中学习比在传输层中学习更快,请增加完全连接层的WeightLearnRateFactor
和BiasLearnRateFactor
值。
numClasses = numel(categories(imdsTrain.Labels))
numClasses = 5
layers = [
layersTransfer
fullyConnectedLayer(numClasses,'WeightLearnRateFactor',20,'BiasLearnRateFactor',20)
softmaxLayer
classificationLayer];
训练网络
网络要求输入图像的大小为227×227×3,但是图像数据存储区中的图像具有不同的大小。使用增强图像数据存储区来自动调整训练图像的大小。指定要在训练图像上执行的其他增强操作:沿垂直轴随机翻转训练图像,然后将它们随机水平和垂直平移最多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);
指定训练选项。对于转移学习,请保留预训练网络早期层的特征(转移层权重)。要减慢传输层中的学习速度,请将初始学习速率设置为较小的值。在上一步中,您增加了全连接层的学习速率因子,以加快新的最终层的学习速度。学习率设置的这种组合导致仅在新层中进行快速学习,而在其他层中进行较慢的学习。进行转学时,您不需要培训很多时间。时期是整个训练数据集的完整训练周期。指定小批量大小和验证数据。该软件ValidationFrequency
在训练过程中的每一次迭代都会验证网络。
options = trainingOptions('sgdm', ...
'MiniBatchSize',10, ...
'MaxEpochs',6, ...
'InitialLearnRate',1e-4, ...
'Shuffle','every-epoch', ...
'ValidationData',augimdsValidation, ...
'ValidationFrequency',3, ...
'Verbose',false, ...
'Plots','training-progress');
训练由传输层和新层组成的网络。默认情况下,trainNetwork
使用GPU(如果有)(需要Parallel Computing Toolbox™和具有CUDA®功能且计算能力为3.0或更高的GPU)。否则,它将使用CPU。您还可以通过使用'ExecutionEnvironment'
名称/值对参数指定执行环境trainingOptions
。
netTransfer = trainNetwork(augimdsTrain,layers,options);
分类验证数据
使用 classify
来对验证集进行分类
[YPred, scores] = classify(netTransfer, augimdsValidation);
展示一些验证集照片和它们的预测结果
图5. 预测结果
计算分类结果的准确性
YValidation = imdsValidation.Labels;
accuracy = mean(YPred == YValidation)
accuracy = 1
要提升分类的准确率,参见Deep Learning Tips and Tricks.