Main Content

minibatchqueue

深層学習用のミニバッチの作成

説明

minibatchqueue オブジェクトを使って、カスタム学習ループによる学習で使用するデータのミニバッチの作成、前処理、管理を行います。

minibatchqueue オブジェクトは、データストアに対して反復処理を行い、カスタム学習ループによる学習に適した形式のデータを提供します。このオブジェクトは、オンデマンドで前処理されたミニバッチのキューを準備します。minibatchqueue オブジェクトを使用すると、dlarraygpuArray へのデータの自動変換、異なる精度へのデータの変換、またはデータを前処理するためのカスタム関数の適用を行うことができます。バックグラウンドで並列処理してデータを準備できます。

minibatchqueue オブジェクトを使用すると、学習中にデータを管理できます。関数 shuffle を使用して各学習エポックの開始時にデータをシャッフルし、関数 next を使用して学習の反復ごとにキューからデータを収集することができます。関数 hasdata を使用してキューにデータが残っていないかチェックし、キューが空になったときに reset を使用してキューをリセットすることができます。

作成

説明

mbq = minibatchqueue(ds) は、入力データストア ds から minibatchqueue オブジェクトを作成します。mbq に格納されるミニバッチの数は、入力データストアに対して read を実行した結果として得られる変数の数と同じです。

mbq = minibatchqueue(ds,numOutputs) は、入力データストア ds から minibatchqueue オブジェクトを作成し、各ミニバッチに含まれる変数の数を設定します。MiniBatchFcn を使用して入力データストア ds の変数の数と異なる数の出力をもつミニバッチ前処理関数を指定する場合、この構文を使用します。

mbq = minibatchqueue(___,Name,Value) は、名前と値のオプションを使用して 1 つ以上のプロパティを設定します。たとえば、minibatchqueue(ds, "MiniBatchSize",64,"PartialMiniBatches","discard") は、返されるミニバッチのサイズを 64 に設定し、観測値の数が 64 個より少ないミニバッチを破棄します。

入力引数

すべて展開する

入力データストア。MATLAB® のデータストアまたはカスタム データストアとして指定します。

深層学習用のデータストアの詳細については、深層学習用のデータストアを参照してください。

ミニバッチ変数の数。正の整数として指定します。既定では、ミニバッチ変数の数は入力データストアの変数の数に等しくなります。

read(ds) の出力を調べることで、入力データストアの変数の数を判断できます。データストアが table を返す場合、変数の数は table に含まれる変数の数になります。データストアが cell 配列を返す場合、変数の数は cell 配列の 2 番目の次元のサイズになります。

名前と値の引数 MiniBatchFcn を使用して、入力データストアと異なる数の変数を返すミニバッチ前処理関数を指定する場合、関数の出力の数と一致するように numOutputs を設定しなければなりません。

例: 2

プロパティ

すべて展開する

このプロパティは読み取り専用です。

関数 next によって返されるミニバッチのサイズ。正の整数として指定します。既定値は 128 です。

例: 256

不完全なミニバッチを返すか破棄するか。"return" または "discard" として指定します。

観測値の総数が MiniBatchSize で割り切れない場合、関数 next によって最後に返されるミニバッチは、観測値の数が MiniBatchSize より少なくなる可能性があります。このプロパティは、次のオプションを使用して、不完全なミニバッチをどのように処理するかを指定します。

  • "return" — ミニバッチは MiniBatchSize より少ない数の観測値をもつことができます。すべてのデータが返されます。

    "discard" — すべてのミニバッチに MiniBatchSize と同じ数の観測値が含まれていなければなりません。完全なミニバッチを構成するのに十分なデータが存在しない場合、キューに含まれるデータの一部が破棄される可能性があります。

すべてのミニバッチを同じサイズにする必要がある場合は、PartialMiniBatch"discard" に設定します。

例: "discard"

データ型: char | string

このプロパティは読み取り専用です。

ミニバッチ前処理関数。"collate" または関数ハンドルとして指定します。

MiniBatchFcn の既定値は "collate" です。この関数は、ミニバッチ変数を連結して配列とします。

カスタム学習で使用するミニバッチを前処理するため、カスタム関数への関数ハンドルを使用します。分類ラベルの one-hot 符号化、シーケンス データのパディング、平均イメージの計算などでは、この方法を推奨します。サイズの異なる配列で構成された cell 配列がデータに含まれている場合、カスタム関数を指定しなければなりません。

カスタム ミニバッチ前処理関数を指定する場合、その関数は、前処理後に出力変数の各バッチを連結して配列とし、各変数を個別の関数出力として返さなければなりません。この関数は、少なくとも基になるデータストアの変数と同じ数の入力を受け入れなければなりません。入力は N 行 1 列の cell 配列としてカスタム関数に渡されます。ここで、N はミニバッチに含まれる観測値の数です。この関数は必要な数だけ変数を返すことができます。MiniBatchFcn で指定された関数が入力と異なる数の出力を返す場合、関数の出力の数として numOutputs を指定します。

カスタム関数の内部で、以下のアクションは推奨されません。目的の動作を再現するには、minibatchqueue オブジェクトの作成時に、対応するプロパティを設定します。

アクション推奨されるプロパティ
変数を別のデータ型にキャスト。OutputCast
データを GPU に移動。OutputEnvironment
データを dlarray に変換。OutputAsDlarray
dlarray 変数にデータ形式を適用。MiniBatchFormat

例: @myCustomFunction

データ型: char | string | function_handle

並列プールにおけるバックグラウンドでのミニバッチの前処理。数値または logical の 1 (true) または 0 (false) として指定します。

このオプションを使用するには、Parallel Computing Toolbox™ が必要です。入力データストア ds はサブセット化または分割が可能でなければなりません。このオプションを使用するため、カスタム データストアは matlab.io.datastore.Subsettable クラスを実装しなければなりません。

ミニバッチの前処理に大きな負荷がかかる場合は、このオプションを使用します。このオプションは、学習中にミニバッチが使用されているときに、並列プールを使用してバックグラウンドでミニバッチを準備します。

プール内のワーカーが、MiniBatchFcn で指定された関数を適用してミニバッチを処理します。OutputCastOutputEnvironmentOutputAsDlarray、および MiniBatchFormat の効果の適用といった追加の処理は、ワーカーで行われません。

DispatchInBackgroundtrue に設定されている場合、ローカル プールが開かれていなければ、ソフトウェアは現在の設定を使用してローカル並列プールを開きます。ローカルではないプールはサポートされません。このプールは、next が最初に呼び出されたときに開きます。

例: true

データ型: logical

このプロパティは読み取り専用です。

各ミニバッチ変数のデータ型。'single''double''int8''int16''int32''int64''uint8''uint16''uint32''uint64''logical''char'、またはこれらの値の cell 配列、あるいは空のベクトルとして指定します。

OutputCast を空のベクトルとして指定した場合、各ミニバッチ変数のデータ型は変更されません。ミニバッチ変数ごとに異なるデータ型を指定するには、各ミニバッチ変数のエントリが格納された cell 配列を指定します。この cell 配列の要素の順序は、ミニバッチ変数が返される順序と同じでなければなりません。この順序は、MiniBatchFcn で指定された関数から返される変数の順序と同じです。MiniBatchFcn のカスタム関数を指定しない場合、この順序は、基になるデータストアによって返される変数の順序と同じになります。

OutputCast の値が OutputAsDlarray プロパティまたは OutputEnvironment プロパティの値と競合しないことを確認してください。OutputAsDlarraytrue または 1 として指定した場合、OutputCast で指定されたデータ型が dlarray によってサポートされていることを確認してください。OutputEnvironment"gpu" または "auto" として指定し、サポートされている GPU を利用できる場合、OutputCast で指定されたデータ型が gpuArray (Parallel Computing Toolbox) によってサポートされていることを確認してください。

例: {'single','single','logical'}

データ型: char | string

このプロパティは読み取り専用です。

ミニバッチ変数を dlarray に変換するフラグ。数値または logical の 1 (true) または 0 (false)、あるいは数値または logical 値のベクトルとして指定します。

出力ごとに異なる値を指定するには、各ミニバッチ変数のエントリが格納されたベクトルを指定します。このベクトルの要素の順序は、ミニバッチ変数が返される順序と同じでなければなりません。この順序は、MiniBatchFcn で指定された関数から返される変数の順序と同じです。MiniBatchFcn のカスタム関数を指定しない場合、この順序は、基になるデータストアによって返される変数の順序と同じになります。

dlarray に変換された変数は、基になるデータ型として OutputCast プロパティで指定されたデータ型をもちます。

例: [1,1,0]

データ型: logical

このプロパティは読み取り専用です。

ミニバッチ変数のデータ形式。文字ベクトル、または文字ベクトルの cell 配列として指定します。

このミニバッチの形式は、dlarray 変数にのみ適用されます。dlarray でないミニバッチ変数については、MiniBatchFormat'' に設定しなければなりません。

dlarray 変数と dlarray でない変数が混在しているときにエラーが発生するのを防ぐには、各ミニバッチ変数のエントリが格納された cell 配列を与えて各出力の値を指定しなければなりません。この cell 配列の要素の順序は、ミニバッチ変数が返される順序と同じでなければなりません。これは、MiniBatchFcn で指定された関数から返される変数の順序と同じです。MiniBatchFcn のカスタム関数を指定しない場合、この順序は、基になるデータストアによって返される変数の順序と同じになります。

例: {'SSCB', ''}

データ型: char | string

関数 next を使用して返されるミニバッチ変数のハードウェア リソース。次のいずれかの値として指定します。

  • 'auto' — 利用できる場合は GPU 上のミニバッチ変数を返します。そうでない場合は CPU 上のミニバッチ変数を返します。

  • 'gpu' — GPU 上のミニバッチ変数を返します。

  • 'cpu' — CPU 上のミニバッチ変数を返します。

GPU 上の特定の変数のみを返すには、各ミニバッチ変数のエントリが格納された cell 配列として OutputEnvironment を指定します。この cell 配列の要素の順序は、ミニバッチ変数が返される順序と同じでなければなりません。この順序は、MiniBatchFcn で指定された関数から返される変数の順序と同じです。カスタムの MiniBatchFcn を指定しない場合、この順序は、基になるデータストアによって返される変数の順序と同じになります。

GPU を使用するには Parallel Computing Toolbox が必要です。深層学習に GPU を使用するには、サポートされている GPU デバイスもなければなりません。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。'gpu' オプションを選択時に Parallel Computing Toolbox または適切な GPU が利用できない場合、エラーが返されます。

例: {'gpu','cpu'}

データ型: char | string

オブジェクト関数

hasdataDetermine if minibatchqueue can return mini-batch
nextミニバッチキューからの次のデータ ミニバッチの取得
partitionPartition minibatchqueue
resetReset minibatchqueue to start of data
shuffleShuffle data in minibatchqueue

すべて折りたたむ

minibatchqueue オブジェクトを使用して、カスタム学習ループにおける学習で使用するイメージと分類ラベルのミニバッチを自動的に準備します。

データストアを作成します。auimds に対して read を呼び出すと、イメージ データが格納された input および対応する分類ラベルが格納された response という 2 つの変数を含む table が生成されます。

auimds = augmentedImageDatastore([100 100],digitDatastore);
A = read(auimds);
head(A,2)
ans = 
         input         response
    _______________    ________

    {100×100 uint8}       0    
    {100×100 uint8}       0    

auimds から minibatchqueue オブジェクトを作成します。MiniBatchSize プロパティを 256 に設定します。

minibatchqueue オブジェクトは、auimds の変数 inputresponse からそれぞれ取得したイメージと分類ラベルである 2 つの出力変数をもちます。GPU 上で書式化された dlarray としてイメージを返すように、minibatchqueue オブジェクトを設定します。このイメージは、単一チャネルの白黒イメージです。形式 'SSBC' をバッチに適用し、大きさが 1 であるチャネル次元を追加します。CPU 上にあるラベルを非 dlarray として返します。

mbq = minibatchqueue(auimds,...
    'MiniBatchSize',256,...
    'OutputAsDlarray',[1,0],...
    'MiniBatchFormat',{'SSBC',''},...
    'OutputEnvironment',{'gpu','cpu'})

関数 next を使用して、mbq からミニバッチを取得します。

[X,Y] = next(mbq);

minibatchqueue およびカスタム ミニバッチ前処理関数を使用して、データを前処理します。このカスタム関数は、入力イメージ データを 0 ~ 1 の範囲に再スケーリングし、平均イメージを計算します。

データを解凍してデータストアを作成します。

unzip("MerchData.zip");
imds = imageDatastore("MerchData", ...
    IncludeSubfolders=true, ...
    LabelSource="foldernames"); 

minibatchqueue. を作成します。

  • 関数の出力の数と一致するように、出力の数を 2 に設定します。

  • ミニバッチのサイズを設定します。

  • この例の終わりに定義されているカスタム関数 preprocessMiniBatch を使用してデータを前処理します。このカスタム関数は、イメージ データを連結して数値配列とし、イメージを 0 ~ 1 の範囲に再スケーリングして、イメージ バッチの平均を計算します。この関数は、再スケーリングされたイメージ バッチおよび平均イメージを返します。

  • DispatchInBackground プロパティを true に設定し、並列プールを使用してバックグラウンドで前処理関数を適用します。DispatchInBackgroundtrue に設定するには、Parallel Computing Toolbox™ が必要です。

  • ミニバッチの出力変数は dlarray に変換しません。

mbq = minibatchqueue(imds,2,...
    MiniBatchSize=16,...
    MiniBatchFcn=@preprocessMiniBatch,...
    DispatchInBackground=true,...
    OutputAsDlarray=false)
mbq = 
minibatchqueue with 2 outputs and properties:

   Mini-batch creation:
           MiniBatchSize: 16
        PartialMiniBatch: 'return'
            MiniBatchFcn: @preprocessMiniBatch
    DispatchInBackground: 1

   Outputs:
              OutputCast: {'single'  'single'}
         OutputAsDlarray: [0 0]
         MiniBatchFormat: {''  ''}
       OutputEnvironment: {'auto'  'auto'}

並列プールがまだ開いていない状態で DispatchInBackground を使用している場合、ミニバッチ キューからデータを読み取ったときにローカルの並列プールが自動的に開きます。前処理関数がスレッドベースの環境に対応している場合、スレッドベースの並列プールを開くことで、メモリ使用量が減り、スケジューリングが高速になり、データ転送コストが少なくなります。詳細については、スレッドベースの環境またはプロセスベースの環境の選択 (Parallel Computing Toolbox)を参照してください。

parpool("Threads");
Starting parallel pool (parpool) using the 'Threads' profile ...
Connected to the parallel pool (number of workers: 4).

ミニバッチを取得し、ミニバッチに含まれるイメージの平均を表示します。スレッド ワーカーによって前処理関数が適用されます。

[X,averageImage] = next(mbq);
imshow(averageImage)

Figure contains an axes object. The axes object contains an object of type image.

function [X,averageImage] = preprocessMiniBatch(XCell)
    X = cat(4,XCell{:});
    
    X = rescale(X,InputMin=0,InputMax=255);
    averageImage = mean(X,4);
end

minibatchqueue を使用してネットワークに学習させ、ミニバッチの処理を管理します。

学習データの読み込み

数字の学習データを読み込み、そのデータをデータストアに格納します。arrayDatastore を使用して、イメージ用とラベル用のデータストアを作成します。その後、データストアを結合し、minibatchqueue で使用する 1 つのデータストアを生成します。

[XTrain,YTrain] = digitTrain4DArrayData;
dsX = arrayDatastore(XTrain,IterationDimension=4);
dsY = arrayDatastore(YTrain);

dsTrain = combine(dsX,dsY);

ラベル データに含まれる一意のクラスの数を判定します。

classes = categories(YTrain);
numClasses = numel(classes);

ネットワークの定義

ネットワークを定義し、イメージ入力層で Mean オプションを使用して平均イメージの値を指定します。

layers = [
    imageInputLayer([28 28 1],Mean=mean(XTrain,4))
    convolution2dLayer(5,20)
    reluLayer
    convolution2dLayer(3,20,Padding=1)
    reluLayer
    convolution2dLayer(3,20,Padding=1)
    reluLayer
    fullyConnectedLayer(numClasses)
    softmaxLayer];
lgraph = layerGraph(layers);

層グラフから dlnetwork オブジェクトを作成します。

net = dlnetwork(lgraph);

モデル損失関数の定義

例の最後にリストされている補助関数 modelLoss を作成します。この関数は、dlnetwork オブジェクト net、入力データのミニバッチ X とそれに対応するラベル Y を入力として受け取り、損失、および net 内の学習可能パラメーターについての損失の勾配を返します。

学習オプションの指定

学習中に使用するオプションを指定します。

numEpochs = 10;
miniBatchSize = 128;

学習の進行状況をプロットに可視化します。

plots = "training-progress";

minibatchqueue を作成します。

minibatchqueue を使用して、イメージのミニバッチを処理および管理します。各ミニバッチで次を行います。

  • 部分的なミニバッチは破棄します。

  • カスタム ミニバッチ前処理関数 preprocessMiniBatch (この例の最後に定義) を使用して、クラス ラベルを one-hot 符号化します。

  • イメージ データを次元ラベル 'SSCB' (spatial、spatial、channel、batch) で書式設定します。既定では、minibatchqueue オブジェクトは、基となるデータ型が singledlarray オブジェクトにデータを変換します。書式をクラス ラベルに追加しないでください。

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

mbq = minibatchqueue(dsTrain,...
    MiniBatchSize=miniBatchSize,...
    PartialMiniBatch="discard",...
    MiniBatchFcn=@preprocessMiniBatch,...    
    MiniBatchFormat=["SSCB",""]);

ネットワークの学習

カスタム学習ループを使用してモデルに学習させます。各エポックについて、minibatchqueue にデータが残っている間、データをシャッフルしてミニバッチをループで回します。関数 adamupdate を使用してネットワーク パラメーターを更新します。各エポックの最後に、学習の進行状況を表示します。

平均勾配および 2 乗平均勾配を初期化します。

averageGrad = [];
averageSqGrad = [];

学習の進行状況モニター用に合計反復回数を計算します。

numObservationsTrain = numel(YTrain);
numIterationsPerEpoch = ceil(numObservationsTrain / miniBatchSize);
numIterations = numEpochs * numIterationsPerEpoch;

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

if plots == "training-progress"
    monitor = trainingProgressMonitor(Metrics="Loss",Info="Epoch",XLabel="Iteration");
end

ネットワークに学習をさせます。

iteration = 0;
epoch = 0;

while epoch < numEpochs && ~monitor.Stop
    epoch = epoch + 1;

    % Shuffle data.
    shuffle (mbq);
        
    while hasdata(mbq)  && ~monitor.Stop
        iteration = iteration + 1;
        
        % Read mini-batch of data.
        [X,Y] = next(mbq);
              
        % Evaluate the model loss and gradients using dlfeval and the
        % modelLoss helper function.
        [loss,grad] = dlfeval(@modelLoss,net,X,Y);

        % Update the network parameters using the Adam optimizer.
        [net,averageGrad,averageSqGrad] = adamupdate(net,grad,averageGrad,averageSqGrad,iteration);

        % Update the training progress monitor.
        if plots == "training-progress"
            recordMetrics(monitor,iteration,Loss=loss);
            updateInfo(monitor,Epoch=epoch + " of " + numEpochs);
            monitor.Progress = 100 * iteration/numIterations;
        end
    end
end

モデル損失関数

補助関数 modelLoss は、dlnetwork オブジェクト net、入力データのミニバッチ X とそれに対応するラベル Y を入力として受け取り、損失、および net 内の学習可能パラメーターについての損失の勾配を返します。勾配を自動的に計算するには、関数 dlgradient を使用します。

function [loss,gradients] = modelLoss(net,X,Y)
    YPred = forward(net,X);    
    loss = crossentropy(YPred,Y);    
    gradients = dlgradient(loss,net.Learnables);
    
end

ミニバッチ前処理関数

関数 preprocessMiniBatch は、次の手順でデータを前処理します。

  1. 入力 cell 配列からイメージ データを抽出し、そのデータを連結して数値配列とします。4 番目の次元でイメージ データを連結することにより、3 番目の次元が各イメージに追加されます。この次元は、シングルトン チャネル次元として使用されます。

  2. 入力 cell 配列からラベル データを抽出し、2 番目の次元に沿って連結して categorical 配列とします。

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

function [X,Y] = preprocessMiniBatch(XCell,YCell)
    % Extract image data from the cell array and concatenate over fourth
    % dimension to add a third singleton dimension, as the channel
    % dimension.
    X = cat(4,XCell{:});

    % Extract label data from cell and concatenate.
    Y = cat(2,YCell{:});
    
    % One-hot encode labels.
    Y = onehotencode(Y,1);

end

バージョン履歴

R2020b で導入