主要内容

与自定义训练循环并行的训练网络

此示例演示如何设置自定义训练循环以并行训练网络。在本示例中,并行工作人员在整个小批量的部分上进行训练。如果您有GPU,则在GPU上进行训练。在训练期间DataQueue对象将训练进度信息发送回MATLAB客户端。

加载数据集

加载数字数据集并为该数据集创建图像数据存储。以随机方式将数据存储划分为训练和测试数据存储。创建一个augmentedImageDatastore包含训练数据。

digitDatasetPath=fullfile(matlabroot,“工具箱”“nnet”“nndemos”...“nndatasets”“DigitDataset”);imds=图像数据存储(digitDatasetPath,...“包含子文件夹”符合事实的...“标签源”“foldernames”);[imdsTrain, imdsTest] = splitEachLabel (imd, 0.9,“随机”);inputSize = [28 28 1];augimdsTrain = augmentedImageDatastore (inputSize (1:2), imdsTrain);

确定训练集中的不同类。

类=类别(imdsTrain.Labels);numClasses =元素个数(类);

定义网络

定义您的网络架构,并通过使用分层图函数。这种网络结构包括批处理归一化层,跟踪数据集的均值和方差统计量。并行训练时,在每个迭代步骤结束时,结合所有工作者的统计信息,以确保网络状态反映整个小批。否则,网络状态可能会在各个worker之间发散。例如,如果您正在训练有状态递归神经网络(rnn),使用被分割成更小序列的序列数据来训练包含LSTM或GRU层的网络,您还必须管理工作人员之间的状态。

[imageInputLayer([28 28 1],]),“名字”“输入”“归一化”“没有”20岁的)convolution2dLayer (5“名字”“conv1”) batchNormalizationLayer (“名字”“bn1”) reluLayer (“名字”“relu1”20岁的)convolution2dLayer (3“填充”,1,“名字”“conv2”) batchNormalizationLayer (“名字”“bn2”) reluLayer (“名字”“relu2”20岁的)convolution2dLayer (3“填充”,1,“名字”“conv3”) batchNormalizationLayer (“名字”“bn3”) reluLayer (“名字”“relu3”)完全连接层(NumClass,“名字”“fc”)]; lgraph=层图(层);

创建一个dlnetwork对象从层图。dlnetwork对象允许使用自定义循环进行训练。

dlnet = dlnetwork (lgraph)
dlnet =带有属性的dlnetwork: Layers: [11×1 nnet.cnn.layer.Layer] Connections: [10×2 table] Learnables: [14×3 table] State: [6×3 table] InputNames: {'input'} OutputNames: {'fc'} Initialized: 1

建立并行环境

确定是否有可供MATLAB使用的GPUcanUseGPU函数。

  • 如果有可用的GPU,则在GPU上进行培训。创建一个与GPU数量相同的并行池。

  • 如果没有可用的gpu,那么在cpu上进行培训。创建一个具有默认工作人员数量的并行池。

如果canUseGPU执行环境=“gpu”;numberOfGPUs = gpuDeviceCount (“可用”);pool=parpool(numberOfGPUs);其他的executionEnvironment =“cpu”;池= parpool;结束
使用“local”配置文件启动并行池(parpool)…连接到并行池(工作人员数量:4)。

获取并行池中工作人员的数量。在本例的后面,您将根据这个数字划分工作负载。

N=池。NumWorkers;

列车模型

指定培训选项。

numEpochs = 20;miniBatchSize = 128;速度= [];

对于GPU培训,推荐的做法是随着GPU的数量线性增加最小批量大小,以保持每个GPU上的工作负载不变。有关更多相关建议,请参阅基于MATLAB的多gpu深度学习

如果executionEnvironment = =“gpu”miniBatchSize=miniBatchSize.*N结束
miniBatchSize=512

计算每个工人的小批量大小,方法是将整个小批量大小在工人之间平均分割。把剩下的分配给第一个工人。

workerMiniBatchSize=楼层(miniBatchSize./repmat(N,1,N));余数=miniBatchSize-和(workerMiniBatchSize);workerMiniBatchSize=workerMiniBatchSize+[一(1,余数)零(1,N-余数)]
workerMiniBatchSize =1×4128 128 128 128

该网络包含批处理归一化层,用于跟踪网络所训练的数据的均值和方差。因为每个工作者在每次迭代中处理每个小批的一部分,所以平均值和方差必须在所有工作者中进行汇总。找出网络状态属性中批处理归一化层的均值和方差状态参数的指标。

batchNormLayers = arrayfun (@ (l) isa (l,“nnet.cnn.layer.BatchNormalizationLayer”), dlnet.Layers);batchNormLayersNames =字符串({dlnet.Layers (batchNormLayers) . name});状态= dlnet.State;isBatchNormalizationStateMean = ismember(state. layer,batchNormLayersNames) & state。参数= =“TrainedMean”; isBatchNormalizationStateVariance=ismember(state.Layer,BatchNormalLayersNames)&state.Parameter==“培训差异”

初始化培训进度图。

figure lineosstrain = animatedline(“颜色”[0.85 0.325 0.098]);ylim([0正])包含(“迭代”)伊拉贝尔(“损失”网格)在…上

为了在培训期间从工人那里发回数据,创建一个DataQueue对象。使用之后为了建立一个函数,displayTrainingProgress,在每次工作人员发送数据时调用。displayTrainingProgress是一个支持万博1manbetx函数,在本示例的最后定义,它显示来自工人的培训进度信息。

Q = parallel.pool.DataQueue;displayFcn = @(x) displayTrainingProgress(x,lineLossTrain);afterEach (Q, displayFcn);

使用自定义并行训练循环训练模型,如下步骤所述spmd块在spmd块,labindex给出当前执行代码的工作程序的索引。

在培训之前,使用分区使用分区数据存储创建小型批处理队列在每个工人身上。对于每个小批量:

  • 使用自定义小批量预处理功能preprocessMiniBatch(在本例末尾定义)以规范化数据,将标签转换为一个热编码变量,并确定小批量中的观察数。

  • 使用尺寸标签格式化图像数据“SSCB”(spatial, spatial, channel, batch)。默认情况下,小型批处理队列对象将数据转换为dlarray具有基础类型的对象.不要在类标签或观察数中添加格式。

  • 在可用的GPU上进行训练。默认情况下,小型批处理队列对象将每个输出转换为gpuArray如果有可用的GPU。使用GPU需要并行计算工具箱™和支持的GPU设备。万博1manbetx有关支持的设备的信息,请参见万博1manbetxGPU支万博1manbetx持情况(并行计算工具箱)(并行计算工具箱)。

对于每个历元,使用重置洗牌功能。对于历元中的每个迭代:

  • 在开始并行处理之前,请确保所有工作人员都有可用的数据操作(共和党)的结果hasdata函数。

  • 小型批处理队列通过使用下一个函数。

  • 通过调用,计算每个worker上的梯度和网络损失dlfevalmodelGradients函数。的dlfeval函数计算helper函数modelGradients有了自动区分,所以modelGradients可以自动计算与损失相关的梯度。modelGradients在示例的最后定义,并在给定网络、小批量数据和真实标签的情况下返回损失和梯度。

  • 要得到整体损失,就要把所有工人的损失加起来。这个例子使用交叉熵作为损失函数,而累计损失是所有损失的总和。在聚合之前,将每个损失乘上工作者正在处理的整个小批的比例进行归一化。使用gplus将所有损失加在一起,并在员工中复制结果。

  • 要聚合和更新所有工作人员的梯度,请使用dlupdate函数与aggregateGradients函数。aggregateGradients是在本示例万博1manbetx最后定义的支持函数。这个函数使用gplus根据每个工人正在处理的整个小批量的比例,在标准化之后,在工人之间添加和复制渐变。

  • 聚合使用的所有工作者的网络状态aggregateState函数。aggregateState是本例末尾万博1manbetx定义的支持函数。网络中的批次标准化层跟踪数据的平均值和方差。由于完整的小批次分布在多个工作人员中,因此在每次迭代后聚合网络状态,以计算整个小批次的平均值和方差。

  • 在计算出最终的梯度后,用sgdmupdate函数。

  • 使用将培训进度信息发送回客户端发送函数与DataQueue.只使用一个工作人员发送数据,因为所有工作人员都有相同的丢失信息。为了确保数据在CPU上,以便没有GPU的客户端机器可以访问它,使用收集dlarray在发送之前。

开始=抽搐;spmd重置并洗牌数据存储。重置(augimdsTrain);augimdsTrain = shuffle (augimdsTrain);%分区数据存储。workerImds =分区(augimdsTrain N labindex);%在每个worker上使用分区数据存储创建minibatchqueueworkerMbq=小批量队列(workerImds,3,...“最小批量大小”workerMiniBatchSize (labindex),...“MiniBatchFcn”@preprocessMiniBatch,...“MiniBatchFormat”,{“SSCB”''''});workerVelocity =速度;迭代= 0;epoch = 1:numEpochs shuffle(workerMbq);%循环小批。虽然@and,hasdata(workerMbq)) iteration = iteration + 1;%读取一小批数据。[dlworkerX, workerY workerNumObservations] =下一个(workerMbq);评估模型的梯度和工人的损失。[workerGradients, dlworkerLoss workerState] = dlfeval (@modelGradients、dlnet dlworkerX, workerY);合计所有工人的损失。workerNormalizationFactor = workerMiniBatchSize (labindex)。/ miniBatchSize;损失= gplus (workerNormalizationFactor * extractdata (dlworkerLoss));%聚合所有worker的网络状态dlnet。状态= aggregateState (workerState workerNormalizationFactor,...isBatchNormalizationStateMean isBatchNormalizationStateVariance);汇总所有工人的梯度。workerGradients。值= dlupdate (@aggregateGradients workerGradients.Value, {workerNormalizationFactor});%使用SGDM优化器更新网络参数。[dlnet。可学的,workerVelocity] = sgdmupdate (dlnet.Learnables、workerGradients workerVelocity);结束%显示培训进度信息。如果Labindex == 1 data = [epoch loss iteration toc(start)];发送(Q,收集(数据));结束结束结束

测试模型

训练网络后,可以测试其准确性。

使用将测试图像加载到内存中readall在测试数据存储中,连接它们并将它们规范化。

XTest = readall (imdsTest);XTest =猫(4 XTest {:});XTest = single(XTest) ./ 255;欧美= imdsTest.Labels;

培训完成后,所有员工都拥有相同的完整培训网络。检索其中任何一个。

dlnetFinal = dlnet {1};

对图像进行分类dlnetwork对象,使用预测函数在一个dlarray

dlYPredScores =预测(dlnetFinal dlarray (XTest“SSCB”));

从预测的分数中,找出得分最高的班级最大值作用在执行此操作之前,请从dlarrayextractdata函数。

[~, idx] = max (extractdata (dlYPredScores), [], 1);YPred =类(idx);

为了获得模型的分类精度,将测试集上的预测与真实标签进行比较。

精度=意味着(YPred = =次)
精度=0.8960

小批量预处理功能

preprocessMiniBatch函数使用以下步骤对一小批预测器和标签进行预处理:

  1. 确定小批量中观察的数量

  2. 对图像进行预处理preprocessMiniBatchPredictors函数。

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

  4. 一种是将分类标签热编码为数字数组。编码为第一维将生成与网络输出形状匹配的编码数组。

作用[X,Y, nummobs] = preprocessMiniBatch(XCell,YCell) nummobs = nummel (YCell);%预处理预测。X=预处理预测值(XCell);%从单元格中提取标签数据并连接。Y =猫(2,YCell{1:结束});%一次性编码标签。Y=onehotcode(Y,1);结束

小批量预测器预处理函数

preprocessMiniBatchPredictors函数通过从输入单元数组提取图像数据并连接到一个数字数组来预处理一小批预测器。对于灰度输入,连接第四个维度为每个图像添加第三个维度,用作单通道维度。然后对数据进行规范化。

作用X = preprocessMiniBatchPredictors(伊势亚)%连接。猫(X = 4,伊势亚{1:结束});%正常化。X=X./255;结束

模型梯度函数

定义一个函数,modelGradients,计算损失相对于网络可学习参数的梯度。此函数用于计算小批量的网络输出X向前地softmax在给定真实输出的情况下,使用交叉熵计算损失dlfeval,启用自动区分,并且梯度可自动计算与可学习值相关的损失梯度。

作用[dlgradients,dlloss,state] = modelGradients(dlnet,dlX,dlY) [dlpred,state] = forward(dlnet,dlX);dlYPred = softmax (dlYPred);dlloss = crossentropy (dlYPred、海底);dlgradients = dlgradient (dlloss dlnet.Learnables);结束

显示培训进度命令功能

定义一个函数来显示来自工人的培训进度信息。的DataQueue在这个例子中,每当一个worker发送数据时调用这个函数。

作用displayTrainingProgress (data,line) addpoints(line,double(data(3)),double(data(2)))) D = duration(0,0,data(4)),“格式”“hh: mm: ss”);标题(”时代:“(1) + +数据”,过去:“+字符串(D)现在开始结束

总梯度函数

定义一个函数,通过将所有辅助对象的渐变添加到一起来聚合这些渐变。gplus将辅助对象上的所有渐变添加到一起并复制。在将它们添加到一起之前,通过将它们乘以表示辅助对象正在处理的整个小批量的比例的因子来规范化它们。要检索dlarrayuseextractdata

作用gradient = aggregateGradients(dlgradients,factor)梯度= gplus(因子*渐变)公关;结束

聚合状态函数

定义一个函数,聚合所有工作者的网络状态。网络状态包含数据集经过训练的批归一化统计信息。由于每个worker只看到迷你批处理的一部分,所以聚合网络状态,以便统计信息能够代表所有数据的统计信息。对于每个小批,合并的平均值被计算为每个迭代中所有工作人员平均值的加权平均值。组合方差的计算公式如下:

年代 c 2 1 j 1 N j 年代 j 2 + x j - x c 2

在哪里 N 为工人总数, 为小批处理中观察的总数, j 是多少个观测值处理的 j th工人, x j 年代 j 2 均值和方差统计数据是计算在那个工人身上的吗 x c 是所有工人的综合平均数。

作用状态=总不动产(状态、系数、,...isBatchNormalizationStateMean,isBatchNormalizationStateVariance) statemans = state.Value(isBatchNormalizationStateMean);stateVariances = state.Value (isBatchNormalizationStateVariance);j = 1:numel(stateMeans) meanVal = stateMeans{j};varVal = stateVariances {};%计算组合平均数combinedMean = gplus(因子* meanVal)公关;计算合并方差项的总和varTerm =因素。*(varVal + (meanVal - combinedMean).^2);%更新状态stateMeans {j} = combinedMean;stateVariances {j} = gplus (varTerm)公关;结束state.Value(isBatchNormalizationStateMean)=状态均值;state.Value(isBatchNormalizationStateVariance)=状态方差;结束

另请参阅

|||||||||

相关话题