主要内容

基于循环学习率的训练网络快照集成

这个例子展示了如何训练一个网络来分类对象的图像,使用循环学习率计划和快照集成,以获得更好的测试准确性。在本例中,您将学习如何使用余弦函数来设置学习率计划,在训练期间对网络进行快照以创建模型集成,并将l2范数正则化(权值衰减)添加到训练损失中。

本例使用自定义循环学习率在CIFAR-10数据集[2]上训练残差网络[1]:对于每次迭代,求解器使用移位余弦函数[3]给出的学习率α(t) = (alpha0/2) * cos(π*国防部(t - 1 t / M) / (t / M) + 1),在那里t是迭代数,T是训练迭代的总次数,alpha0初始学习率,和是循环/快照的数量。这个学习率计划有效地将训练过程分成周期。每个周期都以一个单调衰减的大学习率开始,迫使网络探索不同的局部最小值。在每个训练周期结束时,您对网络进行快照(即在此迭代中保存模型),然后对所有快照模型的预测进行平均,也称为快照集成[4],以提高最终测试的准确性。

准备数据

下载CIFAR-10数据集[2]。该数据集包含60,000张图像。每张图像大小为32x32,有三个颜色通道(RGB)。数据集的大小为175 MB。根据您的互联网连接,下载过程可能需要时间。

Datadir = tempdir;downloadCIFARData (datadir);

将CIFAR-10训练和测试图像加载为4-D数组。训练集包含50,000张图像,测试集包含10,000张图像。

[XTrain,TTrain,XTest,TTest] = loadCIFARData(datadir);类=类别(TTrain);numClasses = nummel(类);

您可以使用以下代码显示训练图像的随机样本。

图;idx = randperm(size(XTrain,4),20);我= imtile (XTrain (:,:,:, idx) ThumbnailSize =(96、96));imshow (im)

创建一个augmentedImageDatastore对象用于网络培训。在训练期间,数据存储沿垂直轴随机翻转训练图像,并在水平和垂直上将它们随机转换为4个像素。数据增强有助于防止网络过度拟合和记忆训练图像的确切细节。

imageSize = [32 32 3];pixelRange = [-4 4];imageAugmenter = imageDataAugmenter(...RandXReflection = true,...RandXTranslation = pixelRange,...RandYTranslation = pixelRange);augimdsTrain = augmentedimagedastore (imageSize,XTrain,TTrain,...DataAugmentation = imageAugmenter);

定义网络架构

创建一个残差网络[1],具有6个标准卷积单元(每个阶段2个单元),宽度为16。总网络深度为2*6+2 = 14。方法指定平均图像的意思是选项在图像输入层。

netWidth = 16;layers = [imageInputLayer(imageSize,Mean= Mean (XTrain,4))卷积2dlayer (3,netWidth,Padding=“相同”batchNormalizationLayer reluLayer(Name= .“reluInp”) convolutionalUnit(netWidth,1) additionLayer(2,Name=“add11”) reluLayer (Name =“relu11”) convolutionalUnit(netWidth,1) additionLayer(2,Name=“add12”) reluLayer (Name =“relu12”) convolutionalUnit(2*netWidth,2“add21”) reluLayer (Name =“relu21”) convolutionalUnit(2*netWidth,1) additionLayer(2,Name=“add22”) reluLayer (Name =“relu22”) convolutionalUnit(4*netWidth,2) additionLayer(2,Name=“add31”) reluLayer (Name =“relu31”) convolutionalUnit(4*netWidth,1) additionLayer(2,Name=“add32”) reluLayer (Name =“relu32”) globalAveragePooling2dLayer fullyConnectedLayer(numClasses) softmaxLayer];lgraph = layerGraph(图层);lgraph = connectLayers(“reluInp”“add11 / in2”);lgraph = connectLayers(“relu11”“add12 / in2”);skip1 = [convolution2dLayer(1,2*netWidth,Stride=2,Name= .“skipConv1”) batchNormalizationLayer (Name =“skipBN1”));lgraph = addLayers(lgraph,skip1);lgraph = connectLayers(“relu12”“skipConv1”);lgraph = connectLayers(“skipBN1”“add21 / in2”);lgraph = connectLayers(“relu21”“add22 / in2”);skip2 = [convolution2dLayer(1,4*netWidth,Stride=2,Name= .“skipConv2”) batchNormalizationLayer (Name =“skipBN2”));lgraph = addLayers(lgraph,skip2);lgraph = connectLayers(“relu22”“skipConv2”);lgraph = connectLayers(“skipBN2”“add31 / in2”);lgraph = connectLayers(“relu31”“add32 / in2”);

绘制ResNet架构。

图绘制(lgraph)

创建一个dlnetwork对象从图层图。

Net = dlnetwork(lgraph);

定义模型损失函数

创建helper函数modelLoss,在示例的末尾列出。函数的参数是adlnetwork对象而且一小批输入数据X有相应的标签T,并返回损失,关于可学习参数的损失梯度,以及在给定迭代时网络的不可学习参数的状态。

指定培训项目

指定培训选项。

  • 训练200个epoch,迷你批量大小为64。

  • 使用动量为0.9的SGDM进行训练。

  • 的权重衰减值正则化权重 1 0 - 4

numEpochs = 200;miniBatchSize = 64;动量= 0.9;weightDecay = 1e-4;

确定要对其应用权重衰减的权重的指标。

idxWeights = ismember(net.Learnables.Parameter,[“重量”“规模”]);

初始化SGDM优化的参数。

速度= [];

指定特定于循环学习率的培训选项。alpha0初始学习率和numSnapshots是训练期间拍摄的循环或快照的数量。

Alpha0 = 0.1;numSnapshots = 5;epochsPerSnapshot = nummepochs ./numSnapshots;numObservations = numel(TTrain);iterationsPerSnapshot = ceil(numObservations./miniBatchSize)*numEpochs./numSnapshots;modelPrefix =“SnapshotEpoch”

初始化训练数据。

[lossLine,learnRateLine] = plotLossAndLearnRate;

火车模型

使用minibatchqueue在训练过程中处理和管理小批量图像。对于每个小批量:

  • 使用自定义小批量预处理功能preprocessMiniBatch(在本例末尾定义)来对类标签进行一次性编码。

  • 用尺寸标签格式化图像数据“SSCB”(空间,空间,通道,批次)。默认情况下,minibatchqueue对象将数据转换为dlarray具有基础类型的对象.不要向类标签添加格式。

  • 如果有GPU,可以在GPU上进行训练。默认情况下,minibatchqueue对象将每个输出转换为gpuArray如果GPU可用。使用GPU需要并行计算工具箱™和受支持的GPU设备。金宝app有关受支持设备的信息,请参见金宝appGPU计算要求(并行计算工具箱)

augimdsTrain。米iniBatchSize = miniBatchSize; mbqTrain = minibatchqueue(augimdsTrain,...MiniBatchSize = MiniBatchSize,...MiniBatchFcn = @preprocessMiniBatch,...MiniBatchFormat = [“SSCB”""]);

加快modelLoss函数使用dlaccelerate

accfun = dlaccelerate(@modelLoss);

使用自定义训练循环训练模型。对于每个epoch,洗牌数据存储,在小批量数据上循环,如果当前epoch是的倍数,则保存模型(快照)epochsPerSnapshot.在每个纪元结束时,显示训练进度。对于每个小批量:

  • 评估模型损失和梯度使用dlfeval加速的modelLoss函数。

  • 更新网络中不可学习参数的状态。

  • 确定循环学习率计划的学习率。

  • 方法更新网络参数sgdmupdate函数。

  • 绘制每次迭代的损失和学习率。

对于本例,在NVIDIA™TITAN RTX上进行的培训大约花费了11个小时。

迭代= 0;开始= tic;%遍历epoch。epoch = 1:numEpochs% Shuffle数据。洗牌(mbqTrain);保存快照模型。如果~mod(epoch,epochsPerSnapshot) save(modelPrefix + epoch + .“.mat”“净”);结束在小批上循环。hasdata(mbqTrain)迭代=迭代+ 1;读取小批数据。[X,T] = next(mbqTrain);计算模型损失和梯度使用dlfeval和%加速modelLoss函数。[loss, gradients, state] = dlfeval(accfun,net,X,T,weightDecay,idxWeights);更新不可学习参数的状态。网状态=状态;确定循环学习率计划的学习率。learnRate = 0.5*alpha0*(cos((pi*mod(迭代-1,iterationsPerSnapshot)./iterationsPerSnapshot))+1);使用SGDM优化器更新网络参数。[net, velocity] = sgdmupdate(net, gradients, velocity, learnRate, momentum);%显示培训进度。D = duration(0,0,toc(start),Format=“hh: mm: ss”);addpoints(lossLine,迭代,双(损失))addpoints(learnRateLine,迭代,学习率);sgtitle (”时代:“+ epoch +,消失:"+字符串(D))现在绘制结束结束

创建快照集成和测试模型

将训练过程中拍摄的M个网络快照组合起来,形成最终的集合,并测试模型的分类精度。集合预测对应于所有M个独立模型的全连接层输出的平均值。

在CIFAR-10数据集提供的测试数据上测试模型。方法管理测试数据集minibatchqueue对象使用与训练数据相同的设置。

augimdsTest = augmentedimagedastore (imageSize,XTest,TTest);augimdsTest。米iniBatchSize = miniBatchSize; mbqTest = minibatchqueue(augimdsTest,...MiniBatchSize = MiniBatchSize,...MiniBatchFcn = @preprocessMiniBatch,...MiniBatchFormat = [“SSCB”""]);

评估每个快照网络的准确性。使用modelPredictions在本例末尾定义的函数,用于遍历测试数据集中的所有数据。该函数返回来自模型的全连接层的输出、预测的类以及与真实类的比较。

modelName = cell(numSnapshots+1,1);fcOutput = 0 (numClasses, nummel (TTest),numSnapshots+1);类预测=单元格(1,numSnapshots+1);modelAccuracy = 0 (numSnapshots+1,1);m = 1:numSnapshots modelName{m} = modelPrefix + m*epochsPerSnapshot;负载(modelName {m} +“.mat”);重置(mbqTest);[fcOutputTest,classPredTest,classCorrTest] = modelforecasts (net,mbqTest,classes);fcOutput(:,:,m) = fcOutputTest;claspredictions {m} = classPredTest;modelAccuracy(m) = 100*mean(classCorrTest);disp (modelName {m} +“准确性:”+ modelAccuracy(m) +“%”结束
SnapshotEpoch40 accuracy: 87.93% SnapshotEpoch80 accuracy: 89.92% SnapshotEpoch120 accuracy: 90.55% SnapshotEpoch160 accuracy: 90.67% SnapshotEpoch200 accuracy: 91.33%

为了确定集成网络的输出,计算每个快照网络的全连接输出的平均值。类从集成网络中查找预测的类onehotdecode函数。与真实类进行比较,以评估集成的准确性。

fcOutput(:,:,最后)=意味着(fcOutput (:,:, 1: end-1), 3);类预测{end} = onehotdecode(softmax(fcOutput(:,:,end)),类,1,“分类”);classCorrEnsemble = claspredictions {end} == TTest';modelAccuracy(end) = 100*mean(classCorrEnsemble);modelName{结束}=“合奏模式”;disp (“整体精度:”+ modelAccuracy(end) +“%”
集成精度:91.74%

情节的准确性

绘制所有快照模型和集成模型在测试数据集上的准确性。

图;酒吧(modelAccuracy);ylabel (“精度(%)”);xticklabels(modelName) xtickangle(45) title(“模型准确性”

辅助函数

模型损失函数

modelLoss函数的参数为dlnetwork对象,一小批输入数据X,标签T为权值衰减参数,为权值衰减指标。该函数返回损失、梯度和不可学习参数的状态。要自动计算梯度,请使用dlgradient函数。

函数[Y,state] = forward(net,X,T,weightDecay,idxWeights);损失=交叉熵(Y, T);% l2正则化(权值衰减)allParams = net.Learnables(idxWeights,:).Value;L = dlupdate(@(x) sum(x.^2,“所有”), allParams);L = sum(1,L{:});损耗=损耗+重量衰减*0.5*L;gradients = dlgradient(loss,net.Learnables);结束

模型预测函数

modelPredictions函数以a作为输入dlnetwork对象,一个minibatchqueue输入数据的兆贝可中所有数据的迭代计算模型预测minibatchqueue.函数使用onehotdecode函数来查找得分最高的预测班级,然后将预测结果与真实班级进行比较。该函数返回网络输出、类预测以及表示正确和不正确预测的1和0向量。

函数[rawforecasts, clasforecasts,classCorr] = modelforecasts (net,mbq,classes) rawforecasts = [];claspredictions = [];classCorr = [];hasdata(mbq) [X,T] = next(mbq);%做预测YPred = predict(net,X);rawforecasts = [rawforecasts extractdata(gather(YPred))];将网络输出转换为概率并确定预测%的类YPred = softmax(YPred);YPredBatch = onehotdecode(YPred,classes,1);claspredictions = [claspredictions YPredBatch];比较预测的和真实的类。T = onehotdecode(T,classes,1);classCorr = [classCorr YPredBatch == T];结束结束

地块损失和学习率函数

plotLossAndLearnRate函数初始化用于在训练期间的每次迭代中显示损失和学习率的图。

函数[lossLine, learnRateLine] = plotLossAndLearnRate图subplot(2,1,1);lossLine = animatedline(Color=[0.85 0.325 0.098]);标题(“损失”);包含(“迭代”) ylabel (“损失”网格)次要情节(2,1,2);learnRateLine = animatedline(Color=[0 0.447 0.741]);标题(“学习”);包含(“迭代”) ylabel (“学习”网格)结束

卷积单位函数

convolutionalUnit (numF步)函数创建了一个层数组,其中包含两个卷积层和相应的批处理归一化层和ReLU层。numF卷积滤波器的个数和是第一卷积层的步幅。

函数layers = convolutionalUnit(numF,stride) layers = [convolution2dLayer(3,numF,Padding=“相同”,Stride= Stride) batchNormalizationLayer relullayer convolution2dLayer(3,numF,Padding=“相同”) batchNormalizationLayer);结束

数据预处理功能

preprocessMiniBatch函数按照以下步骤对数据进行预处理:

  1. 从传入单元格数组中提取图像数据并连接到数值数组中。将图像数据连接到第四个维度将为每个图像添加第三个维度,用作单通道维度。

  2. 从传入的单元格数组中提取标签数据,并沿着第二次维度连接到一个分类数组中。

  3. One-hot将分类标签编码为数字数组。编码到第一个维度会产生一个与网络输出形状匹配的编码数组。

函数[X,T] = preprocessMiniBatch(XCell,TCell)从单元格和拼接中提取图像数据X = cat(4,XCell{:});从单元格和级联中提取标签数据T = cat(2,TCell{:});单热编码标签T = onehotencode(T,1);结束

参考文献

[1]何开明,张翔宇,任少卿,孙健。“用于图像识别的深度剩余学习。”在IEEE计算机视觉和模式识别会议论文集,第770-778页。2016.

[2]克里哲夫斯基,亚历克斯。“从微小的图像中学习多层特征。”(2009)。https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf

Loshchilov, Ilya和Frank Hutter。"Sgdr:随机梯度下降,热重启"(2016)。arXiv预印arXiv:1608.03983

[4]黄,高,李以轩,Geoff Pleiss,刘庄,John E. Hopcroft, Kilian Q. Weinberger。"快照集合:第1列,免费得到第m列"(2017)。arXiv预印本:1704.00109

另请参阅

|||||||||

相关的话题