主要内容

カスタム学習ル,プを使用したネットワ,クの並列学習

この例では,ネットワ,クに並列学習させるためのカスタム学習ル,プを設定する方法を説明します。この例では,並列ワ,カ,によりミニバッチの一部で学習が実行されます。Gpuがある場合,Gpu上で学習が行われます。学習中、DataQueueオブジェクトによって,学習の進行状況の情報がmatlabクラescアントに送り返されます。

デ,タセットの読み込み

数字のデタセットを読み込み,このデタセットのメジデタストアを作成します。デ,タストアを学習デ,タストアとテストデ,タストアにランダムに分割します。学習デ,タを格納するaugmentedImageDatastoreを作成します。

digitDatasetPath = fullfile(toolboxdir(“nnet”),“nndemos”...“nndatasets”“DigitDataset”);imds = imageDatastore(digitDatasetPath,...IncludeSubfolders = true,...LabelSource =“foldernames”);[imdsTrain,imdsTest] = splitEachLabel(imds,0.9,“随机”);inputSize = [28 28 1];augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain);

学習セットに含まれる異なるクラスを判別します。

classes = categories(imdsTrain.Labels);numClasses = nummel(类);

ネットワ,クの定義

ネットワ,クア,キテクチャを定義します。このネットワ,クア,キテクチャには,バッチ正規化層が含まれています。この層は,デ,タセットの統計量である平均と分散を追跡します。並列学習の場合,各反復ステップの最後にすべてのワーカーからの統計量を結合して,ネットワークの状態が必ずミニバッチ全体を反映するようにします。そうでない場合,ネットワ,クの状態がワ,カ,間で異なる可能性があります。たとえば,ステートフル再帰型ニューラルネットワーク(RNN)の学習において,小さいシーケンスに分割されたシーケンスデータを使用してLSTM層または格勒乌層を含むネットワークに学習させる場合,ワーカー間の状態の管理もしなければなりません。

layers = [imageInputLayer(inputSize,归一化=“没有”) convolution2dLayer(5,20) batchNormalizationLayer relullayer (3,20,Padding=1) batchNormalizationLayer reluLayer convolution2dLayer(3,20,Padding=1) batchNormalizationLayer reluledlayer fullyConnectedLayer(numClasses) softmaxLayer];

層配列からdlnetworkオブジェクトを作成します。dlnetworkオブジェクトにより,カスタムル,プを使用した学習が可能になります。

Net = dlnetwork(layers)
net = dlnetwork with properties: Layers: [12×1 nnet.cnn.layer.Layer] Connections: [11×2 table] Learnables: [14×3 table] State: [6×3 table] InputNames: {'imageinput'} OutputNames: {'softmax'} Initialized: 1使用summary查看summary。

並列環境の設定

関数canUseGPUを使用し,matlabでgpuが使用可能かどうかを判定します。

  • 使用できるgpuがある場合,gpu上で学習を実行。Gpuと同じ数のワ,カ,を使用して並列プ,ルを作成。

  • 使用できるgpuがない場合,cpu上で学習を実行。既定の数のワ,カ,を使用して並列プ,ルを作成。

如果canUseGPU executionEnvironment =“图形”;numberofgpu = gpuDeviceCount(“可用”);pool = parpool(numberofgpu);其他的executionEnvironment =“cpu”;Pool = parpool;结束
使用'Processes'配置文件启动并行池(parpool)…连接到并行池(工人数量:4)。

並列プ,ル内のワ,カ,数を取得します。この例では後ほど,この数に基づいて作業負荷を分割します。

numWorkers = pool.NumWorkers;

モデルの学習

学習オプションを指定します。

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

GPUを使用した学習では,GPUの数でミニバッチサイズを線形にスケールアップし,各GPUにおける作業負荷を一定に保つことを推奨します。関連するアドバ化学键スの詳細に化学键いては,Matlabによる複数のgpuでの深層学習を参照してください。

如果executionEnvironment = =“图形”miniBatchSize = miniBatchSize .* numWorkers结束
miniBatchSize = 512

ミニバッチ全体のサズをワカ間で均等に配分し,各ワカのミニバッチサズを計算します。余りは最初のワ,カ,間で分配します。

workerMiniBatchSize = floor(miniBatchSize ./ repmat(numWorkers,1,numWorkers));剩余= miniBatchSize - sum(workerMiniBatchSize);workerMiniBatchSize = workerMiniBatchSize + [ones(1,余数)0 (1,numworkers -余数)]
workerMiniBatchSize =1×4128 128 128 128 128

このネットワークには,ネットワークに学習させているデータの平均と分散を追跡するバッチ正規化層が含まれています。各ワーカーは各反復中に各ミニバッチの一部を処理するため,平均と分散はすべてのワーカーにわたって集計しなければなりません。ネットワークの状態プロパティで,バッチ正規化層の平均と分散の状態パラメーターについて,インデックスを検索します。

batchNormLayers = arrayfun(@(l)isa(l,“nnet.cnn.layer.BatchNormalizationLayer”), net.Layers);batchNormLayersNames = string({net.Layers(batchNormLayers).Name});state = net.State;isBatchNormalizationStateMean = ismember(state. layer,batchNormLayersNames) &状态。参数= =“TrainedMean”;isBatchNormalizationStateVariance = ismember(state. layer,batchNormLayersNames) &状态。参数= =“TrainedVariance”

TrainingProgressMonitorオブジェクトを初期化します。米onitor オブジェクトを作成するとタイマーが開始されるため、学習ループに近いところでオブジェクトを作成するようにしてください。

monitor = trainingProgressMonitor(...指标=“TrainingLoss”...信息= [“时代”“工人”),...包含=“迭代”);

ワ,カ,でDataqueueオブジェクトを作成して,[停止]ボタンが押されたときに学習を停止するためのフラグを送信します。

spmdstopTrainingEventQueue = parallel.pool.DataQueue;结束stopTrainingQueue = stopTrainingEventQueue{1};

学習中にワ,カ,からデ,タを返すため,DataQueueオブジェクトを作成します。afterEachを使用して関数displayTrainingProgressを設定し,ワ,カ,がデ,タを送信するたびに呼び出されるようにします。displayTrainingProgressは,TrainingProgressMonitorオブジェクトを更新して表示し,ワーカーから送信される学習の進行状況の情報を表示し,[停止]ボタンが押された場合にワーカーにフラグを送信するサポート関数(この例の最後で定義)です。

dataQueue = parallel.pool.DataQueue;displayFcn = @(x) displayTrainingProgress(x,numEpochs,numWorkers,monitor,stopTrainingQueue);afterEach (dataQueue displayFcn)

次の手順で詳しく説明するように,カスタム並列学習ル,プを使用してモデルに学習させます。すべてのワ,カ,で同時にコ,ドを実行するには,spmdブロックを使用します。spmdブロック内のspmdIndexにより,現在コドを実行しているワカのンデックスが与えられます。

学習前に,関数分区を使用して各ワ,カ,のデ,タストアを分割します。分割されたデ,タストアを使用して,各ワ,カ,にminibatchqueueを作成します。各ミニバッチで次を行います。

  • カスタムミニバッチ前処理関数preprocessMiniBatch(この例の最後に定義)を使用して,データを正規化し,ラベルを一个炎热符号化変数に変換し,ミニバッチ内の観測値の数を判定します。

  • イメージデータを次元ラベル“SSCB”(空间,空间,通道,批次)で書式設定します。既定では,minibatchqueueオブジェクトは,基となる型がdlarrayオブジェクトにデ,タを変換します。クラスラベルや観測数には書式を追加しないでください。

  • Gpuが利用できる場合,Gpuで学習を行います。既定では,minibatchqueueオブジェクトは,gpuが利用可能な場合,各出力をgpuArrayに変換します。GPUを使用するには,并行计算工具箱™とサポートされているGPUデバイスが必要です。サポトされているデバスにいては,Gpu計算の要件(并行计算工具箱)(并行计算工具箱)を参照してください。

関数重置と関数洗牌を使用し,エポックごとにデ,タストアをリセットしてシャッフルします。エポック内のそれぞれの反復で次を行います。

  • デ,タの並列処理を開始する前に,spmdreduceを使用してグロ,バルな而且演算を関数hasdataの結果に対して実行し,すべてのワ,カ,に利用可能なデ,タがあることを確認。

  • 関数下一个を使用して,minibatchqueueからミニバッチを読み取ります。

  • 関数modelLossdlfevalを呼び出すことによって,各ワ,カ,のネットワ,クの損失と勾配を計算。関数dlfevalは,自動微分を有効にして補助関数modelLossを評価し,modelLossが損失の勾配を自動的に計算できるようにします。modelLoss(この例の最後で定義)は,ネットワーク,データのミニバッチ,真のラベルを受け取り,損失と勾配を返します。

  • 全体的な損失を取得するために,すべてのワ,カ,の損失を集計。この例では,損失関数の交差エントロピ,を使用します。集計された損失はすべての損失の合計です。集計する前に,ミニバッチ全体のうワカが処理している割合で乗算し,各損失を正規化します。spmdPlusを使用してすべての損失を加算し,ワ,カ,全体にその結果を複製します。

  • すべてのワ,カ,の勾配を集計および更新するために,関数aggregateGradientsで関数dlupdateを使用。aggregateGradientsはこの例の終わりで定義するサポ,ト関数です。この関数は,ミニバッチ全体のうち各ワーカーが処理している割合に基づいて正規化した後、spmdPlusを使用し,勾配を加算してワ,カ,全体に複製します。

  • 関数aggregateStateを使用して,すべてのワ,カ,のネットワ,クの状態を集約。aggregateStateは,この例の最後で定義されているサポ,ト関数です。ネットワ,クのバッチ正規化層がデ,タの平均と分散を追跡します。ミニバッチ全体が複数のワーカーに分散されているため,各反復の後にネットワークの状態を集計し,ミニバッチ全体の平均と分散を計算します。

  • 最終勾配を計算した後,関数sgdmupdateを使用し,ネットワ,クの学習可能なパラメ,タ,を更新。

各エポックの後,[停止]ボタンが押されたかどうかを確認し,Dataqueueオブジェクトと関数发送を使用して学習の進行状況の情報をクラ@ @アントに送り返します。すべてのワーカーが同じ損失情報をもっているため,必要なのは1つのワーカーを使用してデータを送り返すことだけです。データが確実にCPU上にあり,GPUを搭載していないクライアントマシンがデータにアクセスできるようにするには,データをクライアントに送信する前に,dlarrayに対して收集を使用します。各エポックの後にワ,カ,間の通信が発生するため,[停止]をクリックして,現在のエポックの最後で学習を停止します。各反復の最後に[停止]ボタンで学習を停止させる場合,[停止]ボタンが押されたかどうかを確認し,反復ごとに学習の進行状況の情報をクライアントに送り返せますが,通信オーバーヘッドが増加します。

spmd重置并洗牌数据存储。重置(augimdsTrain);augimdsTrain = shuffle(augimdsTrain);分区数据存储。workerImds = partition(augimdsTrain,numWorkers,spmdIndex);在每个worker上使用分区的数据存储创建minibatchqueueworkerMbq = minibatchqueue(workerImds,3,...MiniBatchSize = workerMiniBatchSize (spmdIndex),...MiniBatchFcn = @preprocessMiniBatch,...MiniBatchFormat = [“SSCB”""""]);workerVelocity =速度;Epoch = 0;迭代= 0;stopRequest = false;epoch < numEpochs && ~stopRequest epoch = epoch + 1;洗牌(workerMbq);在小批上循环spmreduce (@and,hasdata(workerMbq)) && ~stopRequest迭代=迭代+ 1;读取一个小批数据[workerX,workerT,workerNumObservations] = next(workerMbq);评估模型损失和工人的梯度。[workerLoss,workerGradients,workerState] = dlfeval(@modelLoss,net,workerX,workerT);所有工人损失的总和workerNormalizationFactor = workerMiniBatchSize(spmdIndex)./miniBatchSize;损失= spmdPlus(workerNormalizationFactor*extractdata(workerLoss));聚合所有worker上的网络状态网状态= aggregateState(workerState,workerNormalizationFactor,...isBatchNormalizationStateMean isBatchNormalizationStateVariance);聚合所有工人的梯度workerGradients。Value = dlupdate(@aggregateGradients,workerGradients.Value,{workerNormalizationFactor});使用SGDM优化器更新网络参数[net,workerVelocity] = sgdmupdate(net,workerGradients,workerVelocity);结束%停止训练,如果已点击停止按钮stopRequest = spmdPlus(stopTrainingEventQueue.QueueLength);向客户端发送培训进度信息。如果spmdIndex == 1 data = [epoch loss iteration];发送(dataQueue,收集(数据));结束结束结束

モデルのテスト

ネットワ,クに学習させた後,その精度をテストできます。

readallを使用してテストデータストアにあるテストイメージをメモリに読み込み,それらを連結して正規化します。

XTest = readall(imdsTest);XTest = cat(4,XTest{:});XTest = single(XTest) ./ 255;TTest = imdsTest.Labels;

学習が完了すると,各ワカがも完全な学習済みネットワクはすべて同じになります。それらのいずれかを取得します。

netFinal = net{1};

dlnetworkオブジェクトを使用してメジを分類するには,dlarrayに対して関数预测を使用します。

YTest =预测(netFinal,dlarray(XTest,“SSCB”));

関数马克斯を使用し,予測スコアからスコアが最も高いクラスを見けます。これを行う前に,関数extractdataを使用してdlarrayからデ,タを抽出します。

[~,idx] = max(extractdata(YTest),[],1);YTest = classes(idx);

モデルの分類精度を取得するには,テストセットにおける予測を真のラベルと比較します。

精度=平均值(YTest==TTest)
准确度= 0.9440

ミニバッチ前処理関数

関数preprocessMiniBatchは,次の手順を使用して予測子とラベルのミニバッチを前処理します。

  1. ミニバッチ内の観測数を判定します。

  2. 関数preprocessMiniBatchPredictorsを使用して▪▪メ▪▪ジを前処理します。

  3. 入力电池配列からラベルデータを抽出し,2番目の次元に沿って直言配列に連結します。

  4. カテゴリカルラベルを数値配列に一热符号化します。最初の次元への符号化は,ネットワ,ク出力の形状と一致する符号化された配列を生成します。

函数[X,Y,numObs] = preprocessMiniBatch(XCell,YCell) numObs = num (YCell);预处理预测器。X = preprocessMiniBatchPredictors(XCell);从单元格和级联中提取标签数据。Y = cat(2,YCell{1:end});单热编码标签。Y = onehotencode(Y,1);结束

ミニバッチ予測子前処理関数

関数preprocessMiniBatchPredictorsは,入力电池配列からイメージデータを抽出することで予測子のミニバッチを前処理し,数値配列に連結します。グレースケール入力では,4番目の次元で連結することにより,3番目の次元が各イメージに追加されます。この次元は,シングルトンチャネル次元として使用されることになります。その後,デ,タが正規化されます。

函数X = preprocessMiniBatchPredictors(XCell)%连接。X = cat(4,XCell{1:end});%正常化。X = X ./ 255;结束

モデル損失関数

ネットワクの学習可能なパラメタにいて損失の勾配を計算する関数modelLossを定義します。この関数は,向前を使用してミニバッチXに対するネットワークの出力を計算し,クロスエントロピーを使用して,本来の出力が与えられたときの損失を計算します。dlfevalと共にこの関数を呼び出すと,自動微分が有効になり,dlgradientは学習可能なパラメタにいての損失の勾配を自動的に計算できます。

函数[Y,state] = forward(net,X);损失=交叉熵(Y,T);gradients = dlgradient(loss,net.Learnables);结束

学習の進行状況を表示する関数

ワ,カ,から送信される学習の進行状況の情報を表示し,[停止]ボタンがクリックされたかどうかを確認する関数を定義します。[停止]ボタンがクリックされると,学習を停止する必要があることを示すフラグがワ,カ,に送信されます。この例では,ワ,カ,がデ,タを送信するたびにDataQueueによってこの関数が呼び出されます。

函数displayTrainingProgress(data,numEpochs,numWorkers,monitor,stopTrainingQueue) epoch = data(1);损失=数据(2);迭代=数据(3);recordMetrics(监控、迭代TrainingLoss =损失);updateInfo(监视、时代=时代+“的”+ nummepochs, Workers= numWorkers);班长。进度= 100 * epoch/numEpochs;如果班长。停止发送(stopTrainingQueue,真实);结束结束

勾配集計関数

すべてのワ,カ,の勾配を加算して集計する関数を定義します。spmdPlusは,ワ,カ,上ですべての勾配を加算して複製します。加算する前に,ミニバッチ全体のうちワーカーが処理している割合を表す係数を勾配に乗算し,それらを正規化します。dlarrayの内容を取得するには,extractdataを使用します。

函数gradients = aggregateGradients(gradients,factor) gradients = extractdata(gradients);梯度= spmdPlus(因子*梯度);结束

状態集計関数

すべてのワ,カ,でネットワ,クの状態を集計する関数を定義します。このネットワ,クの状態には,デ,タセットの学習済みバッチ正規化統計量が含まれます。各ワーカーが処理するのはミニバッチの一部のみなの,ですべてのデータの統計を表すように,ネットワークの状態を集計します。ミニバッチごとに,統合平均が,各反復のワ,カ,全体の平均に対する加重平均として計算されます。統合分散は,次の式に従って計算されます。

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

ここで, N はワ,カ,の合計数, はミニバッチの観測値の合計数, j j 番目のワ,カ,で処理された観測値の数, x j 年代 j 2 はそのワ,カ,で計算された平均と分散の統計, x c はすべてのワ,カ,全体の統合平均です。

函数状态= aggregateState(状态,因子,...isBatchNormalizationStateMean,isBatchNormalizationStateVariance) stateMeans = state.Value(isBatchNormalizationStateMean);stateVariances = state.Value(isBatchNormalizationStateVariance);j = 1:numel(stateMeans) meanVal = stateMeans{j};varVal = stateVariances{j};计算组合平均值combinedMean = spmdPlus(factor*meanVal);计算组合方差项求和varTerm = factor。*(varVal + (meanVal - combinedMean).^2);%更新状态stateMeans{j} = combinedMean;stateVariances{j} = spmdPlus(varTerm);结束state.Value(isBatchNormalizationStateMean) = stateMeans;state.Value(isBatchNormalizationStateVariance) = stateVariances;结束

参考

|||||||||

関連するトピック