主要内容

在GPU上运行自定义训练循环和并行

你可以加快您的自定义训练循环运行在GPU,使用多个GPU并行,或集群。

建议使用GPU火车或多个GPU。如果你只使用单个CPU或多个CPU没有GPU。cpu通常要慢得多,gpu进行训练和推理。通常运行在一个单独的GPU提供了更好的性能比运行在多个CPU核心。

请注意

这个话题向您展示了如何执行定制培训gpu,并行,在云上。学习并行和GPU工作流使用trainNetwork功能,请参见:

使用GPU或平行的选项需要并行计算工具箱™。使用GPU还需要支持GPU设备。金宝app支持设备的信息,请参阅金宝appGPU的金宝app支持版本(并行计算工具箱)。还需要使用远程集群MATLAB®并行服务器™

列车网络GPU

默认情况下,自定义训练循环在CPU上运行。自动区分使用dlgradientdlfeval金宝app运行在GPU上的支持当你的数据在GPU。运行自定义训练循环GPU,简单地将数据转换成gpuArray(并行计算工具箱)在培训。

您可以使用minibatchqueue在训练管理你的数据。minibatchqueue自动为培训准备数据,包括定制的预处理和转换数据dlarraygpuArray。默认情况下,minibatchqueue返回所有mini-batch变量在GPU上如果有一个可用。你可以选择哪些变量返回GPU上使用OutputEnvironment财产。

一个例子,演示如何使用minibatchqueue火车在GPU上看到列车网络的使用自定义训练循环

或者,你可以手动转换数据gpuArray培训内循环。

容易地指定执行环境,创建变量executionEnvironment包含两“cpu”,“图形”,或“汽车”

executionEnvironment =“汽车”

培训期间,阅读mini-batch后,检查执行环境的选择和转换数据gpuArray如果有必要的话)。的canUseGPU函数检查可用的gpu。

如果(executionEnvironment = =“汽车”& & canUseGPU) | | executionEnvironment = =“图形”dlX = gpuArray (dlX);结束

火车单一网络并行

当你并行训练,每个工人列车网络同时使用mini-batch的一部分。这意味着您必须将渐变,损失,和任何状态参数在每次迭代之后,根据mini-batch加工的每个工人的比例。

你可以训练你的本地机器上并行,或远程集群上,例如,在云。开始一个平行池所需的资源和工人之间的数据分区。培训期间,结合梯度、损失和国家每一次迭代后,可学的参数对每个工人在同步更新。为一个例子,演示如何执行并行的定制培训,明白了列车网络与自定义训练循环

设置并行环境

建议使用GPU火车或多个GPU。如果你只使用单个CPU或多个CPU没有GPU。cpu通常要慢得多,gpu进行训练和推理。通常运行在一个单独的GPU提供了更好的性能比运行在多个CPU核心。

设置并行环境之前,您想要使用的培训。开始一个平行使用所需的资源池。培训使用多个gpu,开始尽可能多的工人提供gpu并行池。为获得最佳性能,MATLAB自动分配一个不同的GPU每个工人。

如果您使用的是你的本地机器上,您可以使用canUseGPUgpuDeviceCount(并行计算工具箱)确定如果你有可用的gpu。例如,检查可用性的gpu,开始一个平行的池和尽可能多的工人可用的gpu,使用以下代码:

如果canUseGPU executionEnvironment =“图形”;numberOfGPUs = gpuDeviceCount (“可用”);池= parpool (numberOfGPUs);其他的executionEnvironment =“cpu”;池= parpool;结束

如果您正在运行使用远程集群,例如,一个集群在云中,开始一个平行的池和尽可能多的工人每台机器的gpu的数量乘以数量的机器。

在选择特定的gpu的更多信息,见选择特定的gpu用于培训

指定Mini-Batch大小和分区的数据

指定您想要使用的mini-batch大小在训练。GPU训练,推荐的做法是加大mini-batch大小线性与GPU的数量,为了保持每个GPU的工作负载恒定。例如,如果您正在训练一个GPU使用mini-batch大小为64,和你想扩大培训四个相同类型的GPU,可以mini-batch大小增加到256个,这样每个GPU处理64观察每迭代。

您可以使用下面的代码来扩大mini-batch大小工人的数量,N是工人的数量在你的平行池。

如果executionEnvironment = =“图形”miniBatchSize = miniBatchSize。* N结束

如果你想使用一个mini-batch大小不是整除的工人数量在你平行池,然后分发其余工人。

workerMiniBatchSize =地板(miniBatchSize。/ repmat (1, N));剩余= miniBatchSize - sum (workerMiniBatchSize);workerMiniBatchSize = workerMiniBatchSize +[1(剩余)0 (N-remainder)]

开始时的训练,转移你的数据。分区数据,每个工人都有访问mini-batch的一部分。分区数据存储,使用分区函数。

您可以使用minibatchqueue管理数据在每个工人培训。minibatchqueue自动为培训准备数据,包括定制的预处理和转换数据dlarraygpuArray。每个工人使用分区上创建一个minibatchqueue数据存储。设置MiniBatchSize财产使用mini-batch大小计算出每个工人。

每个训练迭代开始时,使用共和党(并行计算工具箱)函数来检查所有工人minibatchqueue对象可以返回数据。如果任何工人用完的数据,停止训练。如果你的整体mini-batch大小并不完全数的整除工人和你不抛弃部分mini-batches,一些工人可能在其他人之前的数据。

写你的代码在一个培训spmd(并行计算工具箱)块,每个工人的训练循环执行。

spmd%重置和洗牌数据存储。重置(augimdsTrain);augimdsTrain = shuffle (augimdsTrain);%分区数据存储。workerImds =分区(augimdsTrain N labindex);%使用分区创建minibatchqueue数据存储在每个工人workerMbq = minibatchqueue (workerImds,“MiniBatchSize”workerMiniBatchSize (labindex),“MiniBatchFcn”,@preprocessMiniBatch);时代= 1:numEpochs%重置和洗牌minibatchqueue每个工人。洗牌(workerMbq);%在mini-batches循环。共和党(@and hasdata (workerMbq))%的定制培训循环结束结束结束

总梯度

确保网络每个工人可以从所有的数据,而不仅仅是工人的数据,总梯度和使用聚合的梯度来更新网络上每个工人。

例如,假设您正在训练网络dlnet使用模型梯度函数modelGradients。你的训练循环包含以下代码来评估梯度,损失,对每个工人和统计:

[workerGradients, dlworkerLoss workerState] = dlfeval (@modelGradients、dlnet dlworkerX, workerY);
dlworkerXworkerY每个工人的预测和真正的反应,分别。

总梯度,用加权和。定义一个helper函数和梯度。

函数梯度= aggregateGradients (dlgradients因素)梯度= extractdata (dlgradients);梯度= gplus(因子*渐变)公关;结束

在训练循环,使用dlupdate应用函数的梯度可学的参数。

workerGradients。值= dlupdate (@aggregateGradients workerGradients.Value, {workerNormalizationFactor});

总损失和准确性

找到网络损耗和准确性,例如,在培训监控进展,把它们总损失的值在所有的工人和准确性。通常,聚合值的总和值在每个工人,加权的比例mini-batch用于每个工人。总损失和每次迭代精度,计算每个工人的加权因子和使用gplus(并行计算工具箱)对每个工人求和的值。

workerNormalizationFactor = workerMiniBatchSize (labindex)。/ miniBatchSize;损失= gplus (workerNormalizationFactor * extractdata (dlworkerLoss));精度= gplus (workerNormalizationFactor * extractdata (dlworkerAccuracy));

总统计

如果您的网络包含层追踪你的训练数据的统计,如批量标准化层,那么你必须总统计每个训练迭代后所有工人。这样做确保了网络学习统计数据代表的整个训练集。

您可以识别层包含统计信息之前培训。例如,如果您使用的是dlnetwork与批量标准化层,您可以使用下面的代码来找到相关的层。

batchNormLayers = arrayfun (@ (l) isa (l,“nnet.cnn.layer.BatchNormalizationLayer”),dlnet.Layers);batchNormLayersNames =字符串({dlnet.Layers (batchNormLayers) . name});状态= dlnet.State;isBatchNormalizationStateMean = ismember (state.Layer batchNormLayersNames) &状态。参数= =“TrainedMean”;isBatchNormalizationStateVariance = ismember (state.Layer batchNormLayersNames) &状态。参数= =“TrainedVariance”;
定义一个helper函数总您所使用的统计数据。批标准化层跟踪输入数据的均值和方差。你可以在所有的工人总平均使用加权平均。方差计算聚合 年代 c 2 ,使用下面的公式形式。

年代 c 2 = 1 j = 1 N j ( 年代 j 2 + ( x ¯ j x ¯ c ) 2 )

N工人总数,是在mini-batch观测的总数,j观察上处理的数量吗jth工人, x ¯ j 年代 j 2 均值和方差的统计计算,工人,然后呢 x ¯ c 是聚合所有工人。

函数状态= aggregateState(状态、因素isBatchNormalizationStateMean isBatchNormalizationStateVariance) stateMeans = state.Value (isBatchNormalizationStateMean);stateVariances = state.Value (isBatchNormalizationStateVariance);j = 1:元素个数(stateMeans) meanVal = stateMeans {};varVal = stateVariances {};%计算结合的意思combinedMean = gplus(因子* meanVal)公关;%计算结合方差和条款varTerm =因素。* (varVal + (meanVal combinedMean) ^ 2);%更新状态stateMeans {j} = combinedMean;stateVariances {j} = gplus (varTerm)公关;结束state.Value (isBatchNormalizationStateMean) = stateMeans;state.Value (isBatchNormalizationStateVariance) = stateVariances;结束

在训练循环,使用辅助函数来更新批的状态组合的均值和方差归一化层。

dlnet。状态= aggregateState (workerState workerNormalizationFactor,isBatchNormalizationStateMean isBatchNormalizationStateVariance);

阴谋的结果在训练

如果你想把结果在训练,你可以从员工到客户端发送数据使用DataQueue对象。

很容易地指定情节应该打开或关闭,创建变量情节包含两“训练进步”“没有”

情节=“训练进步”;

在培训之前,初始化DataQueue和动画线使用animatedline函数。

如果情节= =“训练进步”图lineLossTrain = animatedline (“颜色”[0.85 0.325 0.098]);ylim([0正])包含(“迭代”)ylabel (“损失”网格)结束
创建DataQueue对象。使用afterEachhelper函数displayTrainingProgress每次从工人到客户端发送的数据。
Q = parallel.pool.DataQueue;displayFcn = @ (x) displayTrainingProgress (x, lineLossTrain);afterEach (Q, displayFcn);
displayTrainingProgresshelper函数包含用于添加的代码点动画线和显示培训时代和持续时间。
函数displayTrainingProgress(数据行)addpoints(线、双(数据(3))、双(数据(2)))D =时间(0,0,(4)数据,“格式”,“hh: mm: ss”);标题(”时代:“(1)+ +数据”,过去:“+ drawnow字符串(D))结束

内部培训循环,每个时代的结束时,使用DataQueue将工人的训练数据发送到客户机。在每个迭代中,每个工人的累积损失是相同的,所以你可以发送数据从一个工人。

%显示培训进展信息。如果labindex = = 1数据=[时代损失迭代toc (start)];发送(Q,收集(数据));结束

火车并行多个网络

并行训练多个网络,开始一个平行池所需的资源和使用parfor(并行计算工具箱)训练一个网络在每个工人。

你可以在本地运行或使用远程集群。使用远程集群需要MATLAB并行服务器。关于集群资源管理的更多信息,请参阅发现集群和集群配置文件使用(并行计算工具箱)。如果您有多个gpu和想排除一些培训,您可以选择您所使用的gpu来训练。在选择特定的gpu的更多信息,见选择特定的gpu用于培训

您可以修改网络或训练参数对每个工人并行执行参数扫描。例如,在网络是一个数组的dlnetwork对象,您可以使用下面的代码形式训练多个不同的网络使用相同的数据。

parpool (“本地”,numNetworks);parforidx = 1: numNetworks迭代= 0;速度= [];%的人均分配一个网络dlnet =网络(idx)%循环时期。时代= 1:numEpochs%洗牌数据。洗牌(兆贝可);%在mini-batches循环。hasdata(兆贝可)迭代=迭代+ 1;%的定制培训循环结束结束%将训练网络发送回客户端。trainedNetworks {idx} = dlnet;结束
parfor完成后,trainedNetworks包含生成的网络训练的工人。

阴谋的结果在训练

监控培训的进展工作人员,您可以使用一个DataQueue发送数据的工人。

很容易地指定情节应该打开或关闭,创建变量情节包含两“训练进步”“没有”

情节=“训练进步”;

在培训之前,初始化DataQueue和动画线使用animatedline函数。为每个网络创建一个次要情节你训练。

如果情节= =“训练进步”f =图;f。可见= true;i = 1: numNetworks次要情节(numNetworks 1我)包含(“迭代”);ylabel (“损失”);行(i) = animatedline;结束结束
创建DataQueue对象。使用afterEachhelper函数displayTrainingProgress每次从工人到客户端发送的数据。
Q = parallel.pool.DataQueue;displayFcn = @ (x) displayTrainingProgress (x线);afterEach (Q, displayFcn);
displayTrainingProgresshelper函数包含用于添加的代码点的动画线条。
函数displayTrainingProgress(数据行)addpoints(行(1)双(数据(4)),双(数据(3)))D =时间(0,0,(5)的数据,“格式”,“hh: mm: ss”);标题(”时代:“+(2)+数据”,过去:“+ drawnow字符串(D))limitratenocallbacks结束

在训练循环,在每次迭代结束时,使用DataQueue将工人的训练数据发送到客户机。发送parfor循环索引以及培训信息,点添加到每个工人正确的线。

%显示培训进展信息。data = [idx时代损失迭代toc(开始)];发送(Q,收集(数据));

使用实验管理器并行训练

您可以使用实验经理定制培训循环并行运行。你可以同时运行多个路径,或运行一个审判一次使用并行资源。

同时运行多个试验使用一个为每个审判并行工作,设置自定义训练实验支持使用并行选择之前运行实验。

每次运行单个试验使用多个平行的工人,定义你的并行环境实验培训功能和使用spmd并行块来训练网络。更多信息在培训一个网络与一个定制的循环,明白了火车单一网络并行

有关培训的更多信息并行使用实验管理器,看看使用实验管理器并行训练

另请参阅

(并行计算工具箱)|(并行计算工具箱)|(并行计算工具箱)||

相关的话题