Main Content

モデル関数を使用した予測の実行

この例では、データをミニバッチに分割することにより、モデル関数を使用して予測を行う方法を示します。

データ セットが大きい場合、またはメモリが限られたハードウェアで予測を行う場合、データをミニバッチに分割して予測を行います。dlnetwork オブジェクトで予測を行う場合、関数 minibatchpredict は入力データをミニバッチに自動的に分割します。モデル関数では、データをミニバッチに手動で分割しなければなりません。

モデル関数の作成とパラメーターの読み込み

MAT ファイル digitsMIMO.mat からモデル パラメーターを読み込みます。この MAT ファイルは、parameters という名前の struct にモデル パラメーター、state という名前の struct にモデルの状態、classNames にクラス名を格納しています。

s = load("digitsMIMO.mat");
parameters = s.parameters;
state = s.state;
classNames = s.classNames;

例の最後にリストされているモデル関数 model は、与えられたモデルのパラメーターと状態に基づいてモデルを定義します。

予測用データの読み込み

予測用の数字データを読み込みます。

unzip("DigitsData.zip");

dataFolder = "DigitsData";
imds = imageDatastore(dataFolder, ...
    IncludeSubfolders=true, ...
    LabelSource="foldernames");

numObservations = numel(imds.Files);

予測の実行

テスト データのミニバッチをループ処理して、カスタム予測ループを使って予測を行います。

minibatchqueueを使用して、イメージのミニバッチを処理および管理します。ミニバッチ サイズとして 128 を指定します。イメージ データストアの読み取りサイズ プロパティをミニバッチ サイズに設定します。

各ミニバッチで次を行います。

  • カスタム ミニバッチ前処理関数 preprocessMiniBatch (この例の最後に定義) を使用して、データをバッチに連結し、イメージを正規化。

  • イメージを次元 'SSCB' (spatial、spatial、channel、batch) で形式を整えます。既定では、minibatchqueue オブジェクトは、基となる型が singledlarray オブジェクトにデータを変換します。

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

miniBatchSize = 128;
imds.ReadSize = miniBatchSize;

mbq = minibatchqueue(imds,...
    MiniBatchSize=miniBatchSize,...
    MiniBatchFcn=@preprocessMiniBatch,...
    MiniBatchFormat="SSCB");

データのミニバッチをループ処理し、関数 predict を使用して予測を行います。関数 scores2label を使用して、クラス ラベルを判定します。予測クラス ラベルを保存します。

doTraining = false;
Y1 = [];
Y2 = [];

% Loop over mini-batches.
while hasdata(mbq)
    
    % Read mini-batch of data.
    X = next(mbq);
    
    % Make predictions using the predict function.
    [Y1Batch,Y2Batch] = model(parameters,X,doTraining,state);
    
    % Determine corresponding classes.
    Y1Batch = scores2label(Y1Batch,classNames);
    Y1 = [Y1 Y1Batch];
    
    Y2Batch = extractdata(Y2Batch);
    Y2 = [Y2 Y2Batch];

end

一部のイメージと、その予測を表示します。

idx = randperm(numObservations,9);
figure
for i = 1:9
    subplot(3,3,i)
    I = imread(imds.Files{idx(i)});
    imshow(I)
    hold on
    
    sz = size(I,1);
    offset = sz/2;
    
    thetaPred = Y2(idx(i));
    plot(offset*[1-tand(thetaPred) 1+tand(thetaPred)],[sz 0],"r--")
    
    hold off
    label = string(Y1(idx(i)));
    title("Label: " + label)
end

モデル関数

関数 model は、モデル パラメーター parameters、入力データ X、モデルが学習と予測のどちらの出力を返すべきかを指定するフラグ doTraining、およびネットワークの状態 state を受け取ります。ネットワークはラベルの予測、角度の予測、および更新されたネットワークの状態を出力します。

function [Y1,Y2,state] = model(parameters,X,doTraining,state)

% Convolution
weights = parameters.conv1.Weights;
bias = parameters.conv1.Bias;
Y = dlconv(X,weights,bias,Padding="same");

% Batch normalization, ReLU
offset = parameters.batchnorm1.Offset;
scale = parameters.batchnorm1.Scale;
trainedMean = state.batchnorm1.TrainedMean;
trainedVariance = state.batchnorm1.TrainedVariance;

if doTraining
    [Y,trainedMean,trainedVariance] = batchnorm(Y,offset,scale,trainedMean,trainedVariance);
    
    % Update state
    state.batchnorm1.TrainedMean = trainedMean;
    state.batchnorm1.TrainedVariance = trainedVariance;
else
    Y = batchnorm(Y,offset,scale,trainedMean,trainedVariance);
end

Y = relu(Y);

% Convolution, batch normalization (Skip connection)
weights = parameters.convSkip.Weights;
bias = parameters.convSkip.Bias;
YSkip = dlconv(Y,weights,bias,Stride=2);

offset = parameters.batchnormSkip.Offset;
scale = parameters.batchnormSkip.Scale;
trainedMean = state.batchnormSkip.TrainedMean;
trainedVariance = state.batchnormSkip.TrainedVariance;

if doTraining
    [YSkip,trainedMean,trainedVariance] = batchnorm(YSkip,offset,scale,trainedMean,trainedVariance);
    
    % Update state
    state.batchnormSkip.TrainedMean = trainedMean;
    state.batchnormSkip.TrainedVariance = trainedVariance;
else
    YSkip = batchnorm(YSkip,offset,scale,trainedMean,trainedVariance);
end

% Convolution
weights = parameters.conv2.Weights;
bias = parameters.conv2.Bias;
Y = dlconv(Y,weights,bias,Padding="same",Stride=2);

% Batch normalization, ReLU
offset = parameters.batchnorm2.Offset;
scale = parameters.batchnorm2.Scale;
trainedMean = state.batchnorm2.TrainedMean;
trainedVariance = state.batchnorm2.TrainedVariance;

if doTraining
    [Y,trainedMean,trainedVariance] = batchnorm(Y,offset,scale,trainedMean,trainedVariance);
    
    % Update state
    state.batchnorm2.TrainedMean = trainedMean;
    state.batchnorm2.TrainedVariance = trainedVariance;
else
    Y = batchnorm(Y,offset,scale,trainedMean,trainedVariance);
end

Y = relu(Y);

% Convolution
weights = parameters.conv3.Weights;
bias = parameters.conv3.Bias;
Y = dlconv(Y,weights,bias,Padding="same");

% Batch normalization
offset = parameters.batchnorm3.Offset;
scale = parameters.batchnorm3.Scale;
trainedMean = state.batchnorm3.TrainedMean;
trainedVariance = state.batchnorm3.TrainedVariance;

if doTraining
    [Y,trainedMean,trainedVariance] = batchnorm(Y,offset,scale,trainedMean,trainedVariance);
    
    % Update state
    state.batchnorm3.TrainedMean = trainedMean;
    state.batchnorm3.TrainedVariance = trainedVariance;
else
    Y = batchnorm(Y,offset,scale,trainedMean,trainedVariance);
end

% Addition, ReLU
Y = YSkip + Y;
Y = relu(Y);

% Fully connect, softmax (labels)
weights = parameters.fc1.Weights;
bias = parameters.fc1.Bias;
Y1 = fullyconnect(Y,weights,bias);
Y1 = softmax(Y1);

% Fully connect (angles)
weights = parameters.fc2.Weights;
bias = parameters.fc2.Bias;
Y2 = fullyconnect(Y,weights,bias);

end

ミニバッチ前処理関数

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

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

  2. 01 の間のピクセル値を正規化します。

function X = preprocessMiniBatch(data)    
    % Extract image data from cell and concatenate
    X = cat(4,data{:});
    
    % Normalize the images.
    X = X/255;
end

参考

| | | | | | | | | |

関連するトピック