基于循环学习率的训练网络快照集成
这个例子展示了如何训练一个网络来分类对象的图像,使用循环学习率计划和快照集成,以获得更好的测试准确性。在本例中,您将学习如何使用余弦函数来设置学习率计划,在训练期间对网络进行快照以创建模型集成,并将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进行训练。
的权重衰减值正则化权重 .
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
函数按照以下步骤对数据进行预处理:
从传入单元格数组中提取图像数据并连接到数值数组中。将图像数据连接到第四个维度将为每个图像添加第三个维度,用作单通道维度。
从传入的单元格数组中提取标签数据,并沿着第二次维度连接到一个分类数组中。
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.
另请参阅
dlnetwork
|layerGraph
|dlarray
|sgdmupdate
|dlfeval
|dlgradient
|乙状结肠
|minibatchqueue
|onehotencode
|onehotdecode