主要内容

使用模型函数更新批处理归一化统计

这个例子展示了如何在一个定义为函数的网络中更新网络状态。

批量归一化操作将每个输入通道正常化跨批次的每个输入通道。为了加快卷积神经网络的培训,降低网络初始化的敏感性,在卷积和非线性之间使用批量归一化操作,例如Relu层。

在训练期间,批量归一化操作首先通过减去Mini-Batch均值并除以迷你批量标准偏差来归一化每个信道的激活。然后,操作通过可学习的偏移移动输入β然后用一个可学习的比例因子来缩放γ

当您使用训练过的网络对新数据进行预测时,批处理归一化操作使用训练过的数据集均值和方差而不是小批均值和方差对激活进行归一化。

要计算数据集统计信息,必须使用持续更新状态跟踪小批统计信息。

如果在模型函数中使用批量归一化操作,则必须定义培训和预测的行为。例如,您可以指定布尔选项doTraining控制模型是使用小批量统计进行训练还是使用数据集统计进行预测。

这段来自模型函数的示例代码展示了如何应用批处理规范化操作并在训练期间只更新数据集统计信息。

如果doTraining [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);%更新状态state.batchnorm1。TrainedMean = TrainedMean;state.batchnorm1。TrainedVariance = TrainedVariance;别的海底= batchnorm(海底、抵消、规模、trainedMean trainedVariance);结束

负载培训数据

digittrain4darraydata.功能加载图像,数字标签,以及从垂直旋转的旋转角度。创建一个ArrayDataStore.对象的图像、标签和角度,然后使用结合函数制作包含所有培训数据的单个数据存储。提取无字体响应的类名称和数量。

[XTrain, YTrain anglesTrain] = digitTrain4DArrayData;dsXTrain = arrayDatastore (XTrain,'iteationdimension'4);dsYTrain = arrayDatastore (YTrain);dsAnglesTrain = arrayDatastore (anglesTrain);dsTrain =结合(dsXTrain dsYTrain dsAnglesTrain);一会=类别(YTrain);numClasses =元素个数(类名);numResponses =大小(anglesTrain, 2);numObservations =元素个数(YTrain);

从训练数据中查看一些图像。

idx = randperm (numObservations, 64);我= imtile (XTrain (:,:,:, idx));图imshow(我)

定义深度学习模型

定义下面的网络来预测标签和旋转角度。

  • 具有16个5×5滤波器的卷积 - Batchnorm-Relu块。

  • 两个卷积批量范数块的一个分支,每个块都有32个3 × 3滤波器,中间有一个ReLU操作

  • 带有带有32个1 × 1卷积的卷积-批norm块的跳过连接。

  • 使用加法后跟Relu操作组合两个分支机构

  • 对于回归输出,一个具有完全连接操作的分支,大小为1(响应的数量)。

  • 对于分类输出,一个具有大小为10(类的数量)的全连接操作和softmax操作的分支。

定义和初始化模型参数和状态

定义每个操作的参数,并将它们包含在结构中。使用格式parameters.operationName.ParameterName.parametername.在哪里参数是struct,operationName操作的名称(例如“conv1”)和ParameterName.是参数的名称(例如,“权重”)。

创建一个结构体参数包含模型参数。使用该初始化可知层权重和偏差initializeGlorotinitializeZeros例子函数,分别。属性初始化批处理归一化偏移量和比例参数initializeZerosinitializeon.例子函数,分别。

要使用批处理规范化层执行训练和推断,还必须管理网络状态。在进行预测之前,您必须指定来自训练数据的数据集均值和方差。创建一个结构体状态包含状态参数。批量归一化统计信息不得是dlarray.对象。初始化批量归一化训练均值和训练方差状态使用0函数,分别。

初始化示例函数作为支持文件附加到本示例中。金宝app

初始化第一个卷积层的参数。

filterSize = [5 5];numChannels = 1;numFilters = 16;sz = [filterSize numChannels numFilters];numOut = prod(filterSize) * numFilters;numIn = prod(filterSize) * numFilters;parameters.conv1。重量= initializeGlorot(深圳、numOut numIn);parameters.conv1。Bias = initializeZeros([numFilters 1]);

初始化第一个批量归一化层的参数和状态。

parameters.batchnorm1。Offset = initializeZeros([numFilters 1]);parameters.batchnorm1。Scale = initializeOnes([numFilters 1]);state.batchnorm1。TrainedMean = 0 (numFilters 1“单一”);state.batchnorm1。TrainedVariance = 1 (numFilters 1“单一”);

初始化第二个卷积层的参数。

filterSize = [3 3];numChannels = 16;numFilters = 32;sz = [filterSize numChannels numFilters];numOut = prod(filterSize) * numFilters;numIn = prod(filterSize) * numFilters;parameters.conv2。重量= initializeGlorot(深圳、numOut numIn);parameters.conv2。Bias = initializeZeros([numFilters 1]);

初始化第二批量归一化层的参数和状态。

参数.batchnorm2.offset = initializezeros([numfilters 1]);parameters.batchnorm2.scale = initialIzeone([numfilters 1]);State.batchnorm2.trountmean =零(numfilters,1,“单一”);state.batchnorm2.trainingvariance = into(numfilters,1,“单一”);

初始化第三卷积层的参数。

filterSize = [3 3];numChannels = 32;numFilters = 32;sz = [filterSize numChannels numFilters];numOut = prod(filterSize) * numFilters;numIn = prod(filterSize) * numFilters;parameters.conv3。重量= initializeGlorot(深圳、numOut numIn);parameters.conv3。Bias = initializeZeros([numFilters 1]);

初始化第三批标准化层的参数和状态。

parameters.batchnorm3。Offset = initializeZeros([numFilters 1]);parameters.batchnorm3。Scale = initializeOnes([numFilters 1]);state.batchnorm3。TrainedMean = 0 (numFilters 1“单一”);state.batchnorm3。TrainedVariance = 1 (numFilters 1“单一”);

在跳过连接中初始化卷积层的参数。

filterSize = [1 1];numChannels = 16;numFilters = 32;sz = [filterSize numChannels numFilters];numOut = prod(filterSize) * numFilters;numIn = prod(filterSize) * numFilters;parameters.convSkip.Weights = initializeGlorot(深圳、numOut numIn);parameters.convSkip.Bias = initializeZeros([numFilters 1]);

初始化跳过连接中批量归一化层的参数和状态。

parameters.batchnormSkip.Offset = initializeZeros([numFilters 1]);parameters.batchnormSkip.Scale = initializeOnes([numFilters 1]);state.batchnormSkip.TrainedMean = 0 ([numFilters 1],“单一”);state.batchnormSkip.TrainedVariance = ones([numFilters 1],“单一”);

初始化与分类输出对应的完全连接图层的参数。

sz = [numcrasses 6272];numout = numclasses;numIn = 6272;参数.fc1.weights = initializeglorot(sz,numout,numin);参数.fc1.bias = initializezeros([numclasses 1]);

初始化回归输出对应的全连接层的参数。

sz = [numResponses 6272]; / /numOut = numResponses;numIn = 6272;parameters.fc2。重量= initializeGlorot(深圳、numOut numIn);parameters.fc2。Bias = initializeZeros([numResponses 1]);

查看状态的结构。

状态
状态=结构与字段:[1×1 struct] batchnorm2: [1×1 struct] batchnorm3: [1×1 struct] batchnormSkip: [1×1 struct]

的状态参数batchnorm1操作。

State.batchnorm1.
ans =.结构与字段:TrainedMean: [16×1 single] TrainedVariance: [16×1 single]

定义模型函数

创建函数模型,它计算前面描述的深度学习模型的输出。

功能模型将模型参数作为输入参数, 输入数据dlX的国旗doTraining,指定模型是否返回培训或预测的输出,以及网络状态状态.网络输出标签的预测、角度的预测和更新后的网络状态。

定义模型渐变功能

创建函数MapicalGRADENTERS.,在示例的末尾列出,它将作为输入的迷你批次输入数据dlX与相应的目标T1T2分别包含标签和角度,并返回关于学习参数,更新的网络状态和相应损耗的损耗的渐变。

指定培训选项

指定培训选项。

numEpochs = 20;miniBatchSize = 128;情节=“训练进步”

火车模型

使用自定义训练循环训练模型。使用minibatchqueue处理和管理小批量图像。为每个mini-batch:

  • 使用自定义小批量预处理功能preprocessMiniBatch(在此示例的末尾定义为单热编码类标签。

  • 使用尺寸标签格式化图像数据“SSCB”(spatial, spatial, channel, batch)。默认情况下,minibatchqueue对象将数据转换为dlarray.底层类型的对象.不要向类标签或角度添加格式。

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

兆贝可= minibatchqueue (dsTrain,...“MiniBatchSize”miniBatchSize,...“MiniBatchFcn”@preprocessMiniBatch,...“MiniBatchFormat”,{“SSCB”''''});

对于每个epoch,洗牌数据并在小批数据上循环。在每个纪元的末尾,展示训练的进展情况。为每个mini-batch:

  • 评估模型梯度和损失使用dlfevalMapicalGRADENTERS.函数。

  • 使用adamupdate.函数。

初始化亚当求解器的参数。

trailingAvg = [];trailingAvgSq = [];

初始化培训进度图。

如果plots ==.“训练进步”figure lineosstrain = animatedline(“颜色”,[0.85 0.325 0.098]);ylim([0 inf])xlabel(“迭代”)ylabel(“损失”网格)结束

火车模型。

迭代= 0;开始=抽搐;%循环纪元。时代= 1:numEpochs%Shuffle数据。洗牌(兆贝可)%循环小批尽管Hasdata (mbq) iteration = iteration + 1;[dlX, dlY1 dlY2] =下一个(兆贝可);%评估模型渐变,状态和使用DLFeval和丢失% modelGradients函数。[gradient,state,loss] = dlfeval(@modelGradients, parameters, dlX, dlY1, dlY2, state);%使用Adam优化器更新网络参数。(参数、trailingAvg trailingAvgSq) = adamupdate(参数、渐变...trailingavg,trailingavgsq,迭代);%显示训练进度。如果plots ==.“训练进步”d =持续时间(0,0,toc(start),“格式”“hh: mm: ss”);addpoints (lineLossTrain、迭代、双(收集(extractdata(损失))))标题(”时代:“+时代+”,过去:“+字符串(d))绘制结束结束结束

测试模型

通过将测试集上的预测与真实标签和角度进行比较,检验模型的分类精度。使用控件管理测试数据集minibatchqueue对象的设置与训练数据相同。

[XTest, Y1Test anglesTest] = digitTest4DArrayData;dsXTest = arrayDatastore (XTest,'iteationdimension'4);dsYTest = arrayDatastore (Y1Test);dsAnglesTest = arrayDatastore (anglesTest);dst =结合(dsXTest dsYTest dsAnglesTest);mbqTest = minibatchqueue (dst,...“MiniBatchSize”miniBatchSize,...“MiniBatchFcn”@preprocessMiniBatch,...“MiniBatchFormat”,{“SSCB”''''});

要预测验证数据的标签和角度,请使用modelPredictions函数,列在示例的最后。该函数返回预测的类和角度,以及与真实值的比较。

[classesPredictions, anglesPredictions classCorr angleDiff] = modelPredictions(参数、状态、mbqTest类名);

评估分类准确性。

精度=均值(ClassCorr)
精度= 0.9840.

评估回归的准确性。

angleRMSE =√意味着(angleDiff ^ 2))
angleRMSE =6.3669.

使用他们的预测查看一些图像。以红色和正确的角度显示预测的角度。

idx = randperm(大小(XTest, 4), 9);数字i = 1:9 subplot(3,3,i) i = XTest(:,:,:,idx(i));imshow (I)深圳=大小(我,1);抵消= sz / 2;thetaPred = anglesPredictions (idx (i));情节(抵消* [1-tand (thetaPred) 1 +罐内(thetaPred)], [sz 0],“r——”)ThetAvalidation = Anglyest(IDX(i));绘图(偏移* [1-TAND(TOTAVATHATION)1 + TAND(THETAV alation)],[SZ 0],“g——”) 抓住离开标签=字符串(classesPredictions (idx (i)));标题(”的标签:“+标签)结束

模型功能

功能模型将模型参数作为输入参数,输入数据dlX的国旗doTraining,它指定模型是返回用于训练还是预测的输出,以及网络状态状态.该函数返回标签的预测,角度的预测,以及更新的网络状态。

功能[Dly1,Dly2,状态] =模型(参数,DLX,dotraing,状态)%卷积重量= parameters.conv1.Weights;偏见= parameters.conv1.Bias;海底= dlconv (dlX、权重、偏见,“填充”,2);%批处理规范化,ReLU抵消= parameters.batchnorm1.Offset;规模= parameters.batchnorm1.Scale;trainedMean = state.batchnorm1.TrainedMean;trainedVariance = state.batchnorm1.TrainedVariance;如果doTraining [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);%更新状态state.batchnorm1。TrainedMean = TrainedMean;state.batchnorm1。TrainedVariance = TrainedVariance;别的海底= batchnorm(海底、抵消、规模、trainedMean trainedVariance);结束海底= relu(海底);%卷积,批量标准化(跳过连接)重量= parameters.convSkip.Weights;偏见= parameters.convSkip.Bias;dlYSkip = dlconv(海底,重量、偏见,“步”,2);offset = parameters.batchnormskip.offset;scale = parameters.batchnormskip.scale;受过训练的训练= state.batchnormskip.troundmean;troustainvariance = state.batchnormskip.troundvariance;如果doTraining [dlskip,trainedMean,trainedVariance] = batchnorm(dlskip,offset,scale,trainedMean,trainedVariance);%更新状态state.batchnormSkip.TrainedMean = trainedMean;state.batchnormSkip.TrainedVariance = trainedVariance;别的dlYSkip = batchnorm (dlYSkip、抵消、规模、trainedMean trainedVariance);结束%卷积重量= parameters.conv2.Weights;偏见= parameters.conv2.Bias;海底= dlconv(海底,重量、偏见,“填充”, 1“步”,2);%批处理规范化,ReLU抵消= parameters.batchnorm2.Offset;规模= parameters.batchnorm2.Scale;trainedMean = state.batchnorm2.TrainedMean;trainedVariance = state.batchnorm2.TrainedVariance;如果doTraining [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);%更新状态State.batchnorm2.trountmean =训练有素;State.batchnorm2.trountavariance =训练variance;别的海底= batchnorm(海底、抵消、规模、trainedMean trainedVariance);结束海底= relu(海底);%卷积权重= parameters.conv3.weights;bias = parameters.conv3.bias;海底= dlconv(海底,重量、偏见,“填充”,1);%批正常化offset = parameters.batchnorm3.offset;scale = parameters.batchnorm3.scale;受过训练的训练= state.batchnorm3.trainedmean;TroughtVariance = State.batchnorm3.TrountaInvaniance;如果doTraining [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);%更新状态state.batchnorm3。TrainedMean = TrainedMean;state.batchnorm3。TrainedVariance = TrainedVariance;别的海底= batchnorm(海底、抵消、规模、trainedMean trainedVariance);结束%, ReLUly = dlskip + ly;海底= relu(海底);%完全连接,softmax(标签)重量= parameters.fc1.Weights;偏见= parameters.fc1.Bias;dlY1 = fullyconnect(海底,重量、偏见);dlY1 = softmax (dlY1);完全连接(角度)权重= parameters.fc2.weights;bias = parameters.fc2.bias;dly2 =全协调(DLY,重量,偏见);结束

模型梯度函数

MapicalGRADENTERS.函数将模型参数作为输入,即输入数据的一小批dlX与相应的目标T1T2分别包含标签和角度,并返回关于学习参数,更新的网络状态和相应损耗的损耗的渐变。

功能[gradient,state,loss] = modelGradients(parameters,dlX,T1,T2,state) doTraining = true;[dlY1、dlY2] =模型(参数、dlX doTraining、状态);lossLabels = crossentropy (dlY1, T1);lossAngles = mse (dlY2, T2);loss = lossLabels + 0.1*lossAngles;梯度= dlgradient(损失、参数);结束

模型的预测函数

modelPredictions函数取模型参数、网络状态、aminibatchqueue的输入数据MBQ.类中的所有数据进行迭代,返回模型预测minibatchqueue使用模型用来的功能doTraining选项设置为.该函数返回预测的类和角度,以及与真实值的比较。对于类,比较是表示正确和不正确的预测的零的矢量。对于角度,比较是预测角度和真实值之间的差异。

功能[classesPredictions,anglesPredictions,classCorr,angleDiff] = modelPredictions(parameters,state,mbq,classes) doTraining = false;classesPredictions = [];anglesPredictions = [];classCorr = [];angleDiff = [];尽管hasdata(mbq) [dlX,dlY1,dlY2] = next(mbq);%使用模型函数进行预测。[dlY1Pred, dlY2Pred] =模型(参数、dlX doTraining、状态);%确定预测的类。Y1PredBatch = onehotdecode (dlY1Pred类1);classesPredictions = [classesPredictions Y1PredBatch];Dermine预测角度Y2PredBatch = extractdata (dlY2Pred);anglesPredictions = [anglesPredictions Y2PredBatch];%比较预测的和真实的类日元= onehotdecode (dlY1类1);classCorr = [classCorr Y1PredBatch == Y1];比较预测的和真实的角度angleDiffBatch = Y2PredBatch - dlY2;angleDiff = [angleDiff extractdata(gather(angleDiffBatch))];结束结束

Mini-Batch预处理功能

preprocessMiniBatch函数使用以下步骤对数据进行预处理:

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

  2. 从传入单元阵列中提取标签和角度数据,分别连接到分类阵列和数字阵列中。

  3. 单热编码分类标签到数字阵列中。编码到第一维度生成符合网络输出的形状的编码阵列。

功能(X, Y,角)= preprocessMiniBatch(伊势亚、YCell angleCell)%从单元格提取图像数据并连接猫(X = 4,伊势亚{:});%提取来自细胞和连接的标记数据Y =猫(2,YCell {:});%从单元格提取角度数据并连接角度=猫(2,AngleCell {:});%一次性编码标签Y, Y = onehotencode (1);结束

另请参阅

||||||||||||

相关的话题