这个例子展示了如何用多个输出来训练一个深度学习网络,预测手写数字的标签和旋转角度。
要使用多个输出训练网络,必须使用自定义训练循环培训网络。
这digittrain4darraydata.
功能加载图像,数字标签,以及从垂直旋转的旋转角度。创建一个ArrayDataStore.
对象的图像、标签和角度,然后使用结合
函数创建一个包含所有训练数据的单一数据存储。提取类名和非离散响应的数量。
[Xtrain,Ytrain,Anglestain] = DigitTrain4darraydata;dsxtrain = ArrayDataStore(XTrain,'iteationdimension'4);dsytrain = ArrayDataStore(Ytrain);dsanglestrain = ArrayDataStore(Anglestrain);dstrain =组合(Dsxtrain,Dstrain,dsanglestrain);ClassNames =类别(Ytrain);numclasses = numel(classnames);numobservations = numel(ytrain);
从训练数据中查看一些图像。
idx = randperm (numObservations, 64);我= imtile (XTrain (:,:,:, idx));图imshow(我)
定义下面的网络来预测标签和旋转角度。
具有16个5×5滤波器的卷积 - Batchnorm-Relu块。
两个卷积 - Batchnorm-Relu块,每个块有32个3×3滤波器。
围绕前两个块的跳过连接,包含带有32个1乘1卷积的卷积- batchnorml - relu块。
使用添加合并跳过连接。
对于分类输出,一个具有大小为10(类的数量)的全连接操作和softmax操作的分支。
对于回归输出,一个具有完全连接操作的分支,大小为1(响应的数量)。
将层的主要块定义为层图。
[imageInputLayer([28 28 1],]),“归一化”那'没有任何'那'姓名'那“在”16) convolution2dLayer(5日,“填充”那“相同”那'姓名'那'conv1') batchNormalizationLayer ('姓名'那“bn1”)剥离('姓名'那“relu1”32岁的)convolution2dLayer (3“填充”那“相同”那'走吧'2,'姓名'那'conv2') batchNormalizationLayer ('姓名'那“bn2”)剥离('姓名'那“relu2”32岁的)convolution2dLayer (3“填充”那“相同”那'姓名'那'conv3') batchNormalizationLayer ('姓名'那“bn3”)剥离('姓名'那“relu4”)附加层(2,'姓名'那'添加')全连接列(numcrasses,'姓名'那“fc1”)softmaxlayer('姓名'那“softmax”)];Lgraph = LayerGraph(层);
添加跳过连接。
layers =[卷积2dlayer (1,32,'走吧'2,'姓名'那“convSkip”) batchNormalizationLayer ('姓名'那'bnskip')剥离('姓名'那“reluSkip”)];lgraph = addLayers (lgraph层);Lgraph = ConnectLayers(LAPHAGE,“relu1”那“convSkip”);Lgraph = ConnectLayers(LAPHAGE,“reluSkip”那'添加/ IN2');
添加完全连接层用于回归。
图层=全连接层(1,'姓名'那“取得”);lgraph = addLayers (lgraph层);Lgraph = ConnectLayers(LAPHAGE,'添加'那“取得”);
在绘图中查看图层图。
图绘制(lgraph)
创建一个dlnetwork
对象从层图。
DLNET = DLNETWORK(LGAPRO)
dlnet = dlnetwork with属性:图层:[17×1 nnet.cnn.layer.layer]连接:[17×2表]了解:[20×3表]状态:[8×3表]输入名称:{'进入'} OutputNames:{'softmax''fc2'}
创建函数modelGradients
,在示例的末尾列出,即输入,dlnetwork
目的DLNET.
,输入数据的一小批DLX.
与相应的目标T1
和T2
分别包含标签和角度,并返回损耗相对于可学习参数的梯度、更新后的网络状态和相应的损耗。
指定培训选项。使用128个小批量进行30个纪元的训练。
numEpochs = 30;miniBatchSize = 128;
可视化情节中的培训进度。
plots =.“训练进步”;
用minibatchqueue
处理和管理小批量图像。为每个mini-batch:
使用自定义迷你批处理预处理功能Preprocessminibatch.
(在此示例的末尾定义为单热编码类标签。
使用尺寸标签格式化图像数据“SSCB”
(spatial, spatial, channel, batch)。默认情况下,minibatchqueue
对象将数据转换为dlarray.
底层类型的对象单
.不要向类标签或角度添加格式。
在可用的GPU上进行训练。默认情况下,minibatchqueue
对象将每个输出转换为agpuArray
如果有可用的GPU。使用GPU需要并行计算工具箱™和支持的GPU设备。金宝app有关支持的设备的信息,请参见金宝appGPU支金宝app持情况(并行计算工具箱).
兆贝可= minibatchqueue (dsTrain,...“MiniBatchSize”miniBatchSize,...“MiniBatchFcn”,@preprocessdata,...“MiniBatchFormat”,{“SSCB”那''那''});
使用自定义训练循环训练模型。对于每个epoch,洗牌数据并在小批数据上循环。在每次迭代结束时,显示训练进度。为每个mini-batch:
评估模型梯度和损失使用dlfeval
和modelGradients
功能。
使用使用的网络参数更新网络参数adamupdate
功能。
初始化培训进度图。
如果plots ==“训练进步”figure lineosstrain = animatedline(“颜色”,[0.85 0.325 0.098]);ylim([0 inf])xlabel(“迭代”) ylabel (“损失”网格)在结尾
初始化Adam的参数。
trailingavg = [];trailingavgsq = [];
训练模型。
迭代= 0;开始=抽搐;%循环纪元。为了时代= 1:numEpochs%Shuffle数据。Shuffle(MBQ)%循环小批尽管Hasdata (mbq) iteration = iteration + 1;[dlX, dlY1 dlY2] =下一个(兆贝可);使用dlfeval和% modelGradients函数。[梯度,状态,损失] = DLFeval(@Modelgradients,DLNET,DLX,DLY1,DLY2);dlnet.state = state;%使用Adam优化器更新网络参数。[Dlnet,trailingavg,trailingavgsq] = adamupdate(Dlnet,渐变,...trailingavg,trailingavgsq,迭代);%显示培训进度。如果plots ==“训练进步”d =持续时间(0,0,toc(start),“格式”那“hh: mm: ss”);addpoints (lineLossTrain、迭代、双(收集(extractdata(损失))))标题(”时代:“+ epoch +“,经过:”+字符串(d))绘制结尾结尾结尾
通过比较具有真标标签和角度的测试集的预测来测试模型的分类准确性。使用a管理测试数据集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”,@preprocessdata,...“MiniBatchFormat”,{“SSCB”那''那''});
要预测验证数据的标签和角度,对小批进行循环,并使用预测
功能。存储预测的类和角度。比较预测和真实的类和角度并存储结果。
classespredictions = [];AnglesPredictions = [];classcorr = [];anglediff = [];%循环小批。尽管hasdata (mbqTest)%读取小批数据。[dlXTest, dlY1Test dlY2Test] =下一个(mbqTest);%使用predict函数进行预测。[Dly1pred,dly2pred] =预测(Dlnet,dlxtest,“输出”,[“softmax”“fc2”]);%确定预测的类。Y1PredBatch = onehotdecode (dlY1Pred一会1);classesPredictions = [classesPredictions Y1PredBatch];%Dermine预测角度Y2PredBatch = extractdata (dlY2Pred);anglesPredictions = [anglesPredictions Y2PredBatch];%比较预测的和真实的类y1test = onehotdecode(dly1test,classnames,1);classcorr = [classcorr y1predbatch == y1test];比较预测的和真实的角度angleDiffBatch = Y2PredBatch - dlY2Test;angleDiff = [angleDiff extractdata(gather(angleDiffBatch))];结尾
评估分类精度。
精度=意味着(classCorr)
精度= 0.9814.
评估回归的准确性。
angleRMSE =√意味着(angleDiff ^ 2))
angleRMSE =单7.7431
看看一些图片和他们的预测。红色显示预测的角度,绿色显示正确的标签。
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——”) = anglesTest(idx(i));情节(抵消* [1-tand (thetaValidation) 1 +罐内(thetaValidation)], [sz 0],“g——”)举行离开标签=字符串(classesPredictions (idx (i)));标题(“标签: ”+标签)结尾
这modelGradients
函数的输入为dlnetwork
目的DLNET.
,输入数据的一小批DLX.
与相应的目标T1
和T2
分别包含标签和角度,并返回损耗相对于可学习参数的梯度、更新后的网络状态和相应的损耗。
功能[gradient,state,loss] = model gradient (dlnet,dlX,T1,T2) [dlY1,dlY2,state] = forward(dlnet,dlX,“输出”,[“softmax”“fc2”]);lossLabels = crossentropy (dlY1, T1);lossAngles = mse (dlY2, T2);loss = lossLabels + 0.1*lossAngles;梯度= dlgradient(损失、dlnet.Learnables);结尾
这Preprocessminibatch.
函数使用以下步骤对数据进行预处理:
从传入单元格数组中提取图像数据并将其连接到数字阵列中。通过第四维度连接图像数据将第三维度添加到每个图像,以用作单例通道维度。
从传入的单元格数组中提取标签和角度数据,并沿着第二个维度分别连接到分类数组和数字数组中。
单热编码分类标签到数字阵列中。编码到第一维度生成符合网络输出的形状的编码阵列。
功能(X, Y,角)= preprocessData(伊势亚、YCell angleCell)%从单元格提取图像数据并连接X = CAT(4,Xcell {:});%提取来自细胞和连接的标记数据y =猫(2,Ycell {:});%从单元格提取角度数据并连接角度=猫(2,AngleCell {:});%一次性编码标签Y, Y = onehotencode (1);结尾
batchNormalizationLayer
|convolution2dLayer
|dlarray.
|dlfeval
|Dlgradient.
|全康统计层
|minibatchqueue
|onehotdecode.
|onehotencode
|抵押者
|sgdmupdate.
|softmaxLayer