这个例子展示了如何使用循环学习速率计划和快照集成来训练网络对目标图像进行分类,以获得更好的测试准确性。在本例中,您将学习如何在学习率计划中使用余弦函数,在训练期间拍摄网络快照以创建模型集成,并将l2范数正则化(权重衰减)添加到训练损失中。
这个例子在cioe -10数据集[2]上训练残差网络[1],使用自定义的循环学习率:对于每一次迭代,求解器使用移位余弦函数[3]给出的学习率α(t) = (alpha0/2) * cos(π*国防部(t - 1 t / M) / (t / M) + 1)
,在那里t
为迭代数,T
为训练迭代的总次数,alpha0
是初始学习率,和米
为周期数/快照数。这种学习率计划有效地将训练过程分为米
周期。每个周期开始于一个大的单调衰减的学习速率,迫使网络探索不同的局部极小值。在每个训练周期结束时,您获取网络的一个快照(即在此迭代时保存模型),然后对所有快照模型的预测进行平均,也称为快照集成[4],以提高最终测试的准确性。
下载CIFAR-10数据集[2]。该数据集包含60,000张图像。每张图像大小为32 × 32,有三个彩色通道(RGB)。数据集的大小是175mb。根据你的互联网连接,下载过程可能需要时间。
datadir = tempdir;downloadCIFARData (datadir);
加载CIFAR-10训练和测试图像为4-D阵列。训练集包含50,000张图像,测试集包含10,000张图像。
[XTrain、YTrain XTest,欧美]= loadCIFARData (datadir);类=类别(YTrain);numClasses =元素个数(类);
您可以使用以下代码显示训练图像的随机样本。
图;idx = randperm(大小(XTrain, 4), 20);我= imtile (XTrain (:,:,:, idx),“ThumbnailSize”(96、96));imshow (im)
创建一个augmentedImageDatastore
目的用于网络训练。在训练期间,数据存储沿着垂直轴随机翻转训练图像,并随机将它们水平和垂直转换为4个像素。数据增强有助于防止网络过度拟合和记忆训练图像的确切细节。
imageSize = [32 32 3];pixelRange = [-4 4];imageAugmenter = imageDataAugmenter (...“RandXReflection”,真的,...“RandXTranslation”pixelRange,...“RandYTranslation”, pixelRange);augimdsTrain = augmentedImageDatastore(图象尺寸、XTrain YTrain,...“DataAugmentation”, imageAugmenter);
创建一个具有6个标准卷积单元(每级两个单元)和16宽的残差网络[1]。总网络深度为2*6+2 = 14。此外,使用“的意思是”
选项在图像输入层。
netWidth = 16;imageInputLayer = [imageInputLayer(imageSize,“名字”,“输入”,“的意思是”意思是(XTrain 4)) convolution2dLayer (3 netWidth“填充”,“相同”,“名字”,“convInp”) batchNormalizationLayer (“名字”,“BNInp”) reluLayer (“名字”,“reluInp”) convolutionalUnit (netWidth 1“S1U1”) additionLayer (2“名字”,“add11”) reluLayer (“名字”,“relu11”) convolutionalUnit (netWidth 1“S1U2”) additionLayer (2“名字”,“add12”) reluLayer (“名字”,“relu12”) convolutionalUnit (2 * netWidth 2“S2U1”) additionLayer (2“名字”,“add21”) reluLayer (“名字”,“relu21”) convolutionalUnit (2 * netWidth 1“S2U2”) additionLayer (2“名字”,“add22”) reluLayer (“名字”,“relu22”) convolutionalUnit (4 * netWidth 2“S3U1”) additionLayer (2“名字”,“add31”) reluLayer (“名字”,“relu31”) convolutionalUnit (4 * netWidth 1“S3U2”) additionLayer (2“名字”,“add32”) reluLayer (“名字”,“relu32”) averagePooling2dLayer (8,“名字”,“globalPool”) fullyConnectedLayer (10“名字”,“fcFinal”));lgraph = layerGraph(层);lgraph = connectLayers (lgraph,“reluInp”,“add11 / in2”);lgraph = connectLayers (lgraph,“relu11”,“add12 / in2”);skip1 =[卷积2dlayer (1,2*netWidth,“步”2,“名字”,“skipConv1”) batchNormalizationLayer (“名字”,“skipBN1”));lgraph = addLayers (lgraph skip1);lgraph = connectLayers (lgraph,“relu12”,“skipConv1”);lgraph = connectLayers (lgraph,“skipBN1”,“add21 / in2”);lgraph = connectLayers (lgraph,“relu21”,“add22 / in2”);skip2 =[卷积2dlayer (1,4*netWidth,“步”2,“名字”,“skipConv2”) batchNormalizationLayer (“名字”,“skipBN2”));lgraph = addLayers (lgraph skip2);lgraph = connectLayers (lgraph,“relu22”,“skipConv2”);lgraph = connectLayers (lgraph,“skipBN2”,“add31 / in2”);lgraph = connectLayers (lgraph,“relu31”,“add32 / in2”);
绘制ResNet架构。
图;情节(lgraph)
创建一个dlnetwork
对象从层图。
dlnet = dlnetwork (lgraph);
创建helper函数modelGradients
,列在示例的最后。函数接受adlnetwork
对象dlnet
和
一小批输入数据dlX
与相应的标签Y,
并返回损失相对于可学习参数的梯度dlnet
.该函数还返回给定迭代时网络的损失和不可学习参数的状态。
指定培训选项。训练200个时代,小批量64个。
numEpochs = 200;miniBatchSize = 64;numObservations =元素个数(YTrain);速度= [];动量= 0.9;weightDecay = 1的军医;
指定特定于周期学习率的培训选项。Alpha0
初始学习率是和吗numSnapshots
为训练期间的循环次数或快照次数。
alpha0 = 0.1;numSnapshots = 5;epochsPerSnapshot = numEpochs. / numSnapshots;iterationsPerSnapshot =装天花板(numObservations. / miniBatchSize) * numEpochs. / numSnapshots;modelPrefix =“SnapshotEpoch”;
在一个情节中想象训练的进展。
情节=“训练进步”;
初始化训练图。
如果情节= =“训练进步”[lossLine, learnRateLine] = plotLossAndLearnRate ();结束
使用minibatchqueue
在培训过程中处理和管理小批量的图像。为每个mini-batch:
使用自定义小批量预处理功能preprocessMiniBatch
(在本例的最后定义)一次性对类标签进行编码。
使用尺寸标签格式化图像数据“SSCB”
(spatial, spatial, channel, batch)。默认情况下,minibatchqueue
对象将数据转换为dlarray
具有底层类型的对象单
.不要向类标签添加格式。
在可用的GPU上进行训练。默认情况下,minibatchqueue
对象将每个输出转换为gpuArray
如果有可用的GPU。使用GPU需要并行计算工具箱™和支持的GPU设备。万博1manbetx有关支持的设备的信息,请参见万博1manbetxGPU支万博1manbetx持情况(并行计算工具箱).
augimdsTrain。米iniBatchSize = miniBatchSize; mbqTrain = minibatchqueue(augimdsTrain,...“MiniBatchSize”miniBatchSize,...“MiniBatchFcn”@preprocessMiniBatch,...“MiniBatchFormat”, {“SSCB”,''});
使用自定义训练循环训练模型。对于每个epoch,洗牌数据存储,循环小批数据,如果当前epoch是的倍数,则保存模型(快照)epochsPerSnapshot
.在每个纪元的末尾,展示训练的进展情况。为每个mini-batch:
评估模型梯度和损失使用dlfeval
和modelGradients
函数。
更新网络中不可学习参数的状态。
确定周期学习率计划的学习率。
使用sgdmupdate
函数。
绘制每一次迭代的损失和学习率。
对于本例,培训在NVIDIA™TITAN RTX上花费了大约14个小时。
迭代= 0;开始=抽搐;%循环纪元。为时代= 1:numEpochs%洗牌数据。洗牌(mbqTrain);%保存快照模型。如果~mod(epoch,epochsPerSnapshot“.mat”,“dlnet”);结束%循环小批。而hasdata(mbqTrain) iteration = iteration + 1;%读取小批数据。[dlX,海底]=下一个(mbqTrain);使用dlfeval和% modelGradients函数。[gradient, loss, state] = dlfeval(@modelGradients,dlnet,dlX,dlY,weightDecay);%更新不可学习参数的状态。dlnet。=状态;确定循环学习率计划的学习率。learnRate = 0.5 * alpha0 * (cos((π*国防部(迭代1,iterationsPerSnapshot)。/ iterationsPerSnapshot)) + 1);%使用SGDM优化器更新网络参数。[dlnet。= sgdmupdate(dlnet。学习性,梯度,速度,学习率,动量);%显示训练进度。如果情节= =“训练进步”D =持续时间(0,0,toc(开始),“格式”,“hh: mm: ss”);addpoints(lossLine,iteration,double(gather(extractdata(loss)))) addpoints(learnRateLine, iteration, learnRate));sgtitle (”时代:“+时代+”,过去:“+ drawnow字符串(D))结束结束结束
结合训练时拍摄的M张网络快照,形成最终的集成,并测试模型的分类精度。集合预测对应于所有M个独立模型的全连接层输出的平均值。
在CIFAR-10数据集提供的测试数据上测试模型。使用控件管理测试数据集minibatchqueue
对象的设置与训练数据相同。
augimdsTest = augmentedImageDatastore(图象尺寸、XTest欧美);augimdsTest。米iniBatchSize = miniBatchSize; mbqTest = minibatchqueue(augimdsTest,...“MiniBatchSize”miniBatchSize,...“MiniBatchFcn”@preprocessMiniBatch,...“MiniBatchFormat”, {“SSCB”,''});
评估每个快照网络的准确性。使用modelPredictions
函数,以遍历测试数据集中的所有数据。该函数从模型返回完全连接层的输出、预测的类以及与真实类的比较。
modelName =细胞(numSnapshots + 1, - 1);fcOutput = 0 (numClasses元素个数(欧美),numSnapshots + 1);classPredictions =细胞(1,numSnapshots + 1);modelAccuracy = 0 (numSnapshots + 1, - 1);为m = 1:numSnapshots modelName{m} = modelPrefix + m*epochsPerSnapshot;负载(modelName {m} +“.mat”);重置(mbqTest);[fcOutputTest, classPredTest classCorrTest] = modelPredictions (dlnet、mbqTest、类);fcOutput(:,:,米)= fcOutputTest;classPredictions {m} = classPredTest;modelAccuracy (m) = 100 *意味着(classCorrTest);disp (modelName {m} +准确性:“+ modelAccuracy (m) +“%”)结束
SnapshotEpoch40精度:88.35% SnapshotEpoch80精度:89.93% SnapshotEpoch120精度:90.51% SnapshotEpoch160精度:90.33% SnapshotEpoch200精度:90.63%
为了确定集成网络的输出,计算每个快照网络的全连接输出的平均值。使用集合网络查找预测的类onehotdecode
函数。通过与真实类的比较,来评价集成的准确性。
fcOutput(:,:,最后)=意味着(fcOutput (:,:, 1: end-1), 3);classPredictions{结束}= onehotdecode (softmax (fcOutput(:,:,结束),类,1,“分类”);classCorrEnsemble = classpredicted {end} == YTest';modelAccuracy(结束)= 100 *意味着(classCorrEnsemble);modelName{结束}=“合奏模式”;disp (“整体精度:“+ + modelAccuracy(结束)“%”)
整体精度:91.59%
绘制所有快照模型和集成模型在测试数据集上的准确性。
图;酒吧(modelAccuracy);ylabel (的精度(%));xticklabels (modelName) xtickangle(45)标题(“模型准确性”)
的modelGradients
函数接受dlnetwork
对象dlnet
,输入数据的一小批dlX
,标签Y,
以及权重衰减的参数。该函数返回梯度、损失和不可学习参数的状态。要自动计算梯度,请使用dlgradient
函数。
函数[gradient,loss,state] = modelGradients(dlnet,dlX,Y,weightDecay) [dlpred,state] = forward(dlnet,dlX);dlYPred = softmax (dlYPred);loss = cross - sentropy(dlYPred, Y);% l2 -正则化(重量衰减)allParams = dlnet.Learnables (dlnet.Learnables。参数= =“重量”| dlnet.Learnables.Parameter = =“规模”、:)value;@(x) sum(x.^2,)“所有”)、allParams“UniformOutput”、假);l2Norm =总和(猫(l2Norm {:}));loss = loss + weightDecay*0.5*l2Norm;梯度= dlgradient(损失、dlnet.Learnables);结束
的modelPredictions
函数接受输入adlnetwork
对象dlnet
,一个minibatchqueue
的输入数据兆贝可
,并通过迭代所有数据来计算模型预测minibatchqueue
.函数使用onehotdecode
函数查找得分最高的预测类,然后将预测与真实类进行比较。该函数返回网络输出、类预测以及表示正确和不正确预测的1和0向量。
函数[rawPredictions, claspredictions,classCorr] = modelPredictions(dlnet,mbq,classes) rawPredictions = [];classPredictions = [];classCorr = [];而hasdata(mbq) [dlX,dlY] = next(mbq);%进行预测dlYPred =预测(dlnet dlX);rawPredictions = [rawPredictions extractdata(gather(dlYPred)))];%将网络输出转换为概率并确定预测值%的类dlYPred = softmax (dlYPred);YPredBatch = onehotdecode (dlYPred类1);classptions = [classptions YPredBatch];%比较预测的和真实的类Y = onehotdecode(海底、类1);classCorr = [classCorr YPredBatch == Y];结束结束
的plotLossAndLearnRate
函数初始化用于显示训练期间每个迭代的损失和学习率的图。
函数[lossLine, learnRateLine] = plotLossAndLearnRate() figure subplot(2,1,1);lossLine = animatedline (“颜色”[0.85 0.325 0.098]);标题(“损失”);包含(“迭代”) ylabel (“损失”网格)在次要情节(2,1,2);learnRateLine = animatedline (“颜色”0.447 - 0.741 [0]);标题(学习速率的);包含(“迭代”) ylabel (学习速率的网格)在结束
的convolutionalUnit (numF、跨步、标签)
函数创建一个由两个卷积层和相应的批处理规范化和ReLU层组成的层数组。numF
为卷积滤波器的个数,步
是第一个卷积层的步幅,和标签
是附加在所有层名称前的标记。
函数layers =[卷积2dlayer (3,numF, numF,)]“填充”,“相同”,“步”步,“名字”,标签,“conv1”]) batchNormalizationLayer (“名字”,标签,“BN1”]) reluLayer (“名字”,标签,“relu1”numF]) convolution2dLayer(3日,“填充”,“相同”,“名字”,标签,“conv2”]) batchNormalizationLayer (“名字”,标签,“BN2”)));结束
的preprocessMiniBatch
函数使用以下步骤对数据进行预处理:
从传入的单元格数组中提取图像数据并连接到一个数字数组中。将图像数据连接到第四个维度上,为每个图像添加了第三个维度,用作单通道维度。
从传入的单元格数组中提取标签数据,并沿第2维连接到分类数组中。
一次性将分类标签编码为数字数组。编码到第一个维度会生成一个与网络输出形状匹配的编码数组。
函数(X, Y) = preprocessMiniBatch(伊势亚YCell)%从单元格提取图像数据并连接猫(X = 4,伊势亚{:});%从单元格中提取标签数据并连接Y =猫(2,YCell {:});%一次性编码标签Y, Y = onehotencode (1);结束
何开明,张翔宇,任少青,孙健“图像识别的深度残差学习”。在计算机视觉与模式识别IEEE会议论文集, 770 - 778页。2016.
[2] Krizhevsky,亚历克斯。“从微小图像中学习多层特征。”(2009)。https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf
Loshchilov, Ilya和Frank Hutter。"Sgdr:随机梯度下降与暖重启"(2016).arXiv预印本arXiv: 1608.03983.
[4] Huang, Gao, Yixuan Li, Geoff Pleiss, Zhuang Liu, John E. Hopcroft and Kilian Q. Weinberger。“集合快照:火车1号,免费。”(2017)。arXiv预印本arXiv: 1704.00109.
dlarray
|dlfeval
|dlgradient
|dlnetwork
|layerGraph
|minibatchqueue
|onehotdecode
|onehotencode
|sgdmupdate
|乙状结肠