メインコンテンツ

forward

学習用の深層学習ネットワーク出力の計算

説明

深層学習層によっては学習時と推論時 (予測時) の動作が異なる場合があります。たとえば、学習時には過適合を防ぐためにドロップアウト層によって入力要素がランダムに 0 に設定されますが、推論時にはドロップアウト層によって入力が変更されることはありません。

学習用のネットワーク出力を計算するには、関数 forward を使用します。推論用のネットワーク出力を計算するには、関数 predict を使用します。

[Y1,...,YN] = forward(net,X1,...,XM) は、入力データ X1, …, XM、およびニューラル ネットワーク net が与えられたときに、学習用のネットワーク出力 Y1, …, YN を返します。

[Y1,...,YN,state] = forward(X1,...,XM) は更新されたネットワークの状態も返します。

[Y1,...,YN,state,pruningActivations] = forward(X1,...,XM) は、枝刈り層の活性化の cell 配列も返します。この構文は、netTaylorPrunableNetwork オブジェクトである場合にのみ適用できます。

深層ニューラル ネットワークの枝刈りを行うには、Deep Learning Toolbox™ Model Compression Library サポート パッケージが必要です。このサポート パッケージは無料のアドオンで、アドオン エクスプローラーを使用してダウンロードできます。または、Deep Learning Toolbox Model Compression Library を参照してください。

___ = forward(___,Name=Value) は、1 つ以上の名前と値の引数を使用して追加オプションを指定します。

すべて折りたたむ

この例では、カスタム学習率スケジュールで手書きの数字を分類するネットワークに学習させる方法を示します。

ほとんどのタイプのニューラル ネットワークは、関数trainnetと関数trainingOptionsを使用して学習させることができます。必要なオプション (カスタム ソルバーなど) が trainingOptions 関数に用意されていない場合、自動微分のために dlarray オブジェクトと dlnetwork オブジェクトを使用して独自のカスタム学習ループを定義できます。関数 trainnet を使用して事前学習済みの深層学習ネットワークに再学習させる方法を示す例については、新しいイメージを分類するためのニューラル ネットワークの再学習を参照してください。

深層ニューラル ネットワークの学習は最適化タスクです。ニューラル ネットワークを関数 f(X;θ) と見なすことにより (ここで、X はネットワーク入力、θ は学習可能なパラメーターのセット)、θ を最適化して学習データに基づく損失値を最小化できます。たとえば、与えらえた入力 X と対応するターゲット T に対して、予測 Y=f(X;θ)T の間の誤差が最小になるように、学習可能なパラメーター θ を最適化します。

使用される損失関数は、タスクのタイプによって異なります。以下に例を示します。

  • 分類タスクの場合、予測とターゲットの間のクロス エントロピー誤差を最小化できます。

  • 回帰タスクの場合、予測とターゲットの間の平均二乗誤差を最小化できます。

勾配降下法を使用して目的を最適化できます。勾配降下法では、学習可能なパラメーターについての損失の勾配を使用して最小化に向けてステップを実行することで、学習可能なパラメーター θ を反復的に更新することにより、損失 L を最小化します。勾配降下法アルゴリズムは通常、θt+1=θt-ρL の形式の更新ステップのバリアントを使用して、学習可能なパラメーターを更新します。ここで、t は反復回数、ρ は学習率、L は勾配 (学習可能なパラメーターについての損失の微分) を表します。

この例では、確率的勾配降下アルゴリズム (モーメンタムなし) を使用して手書きの数字を分類するためにネットワークに学習させます。

学習データの読み込み

関数 imageDatastore を使用して数字データをイメージ データストアとして読み込み、イメージ データが格納されているフォルダーを指定します。

unzip("DigitsData.zip")

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

データを学習セットとテスト セットに分割します。splitEachLabel 関数を使用して、データの 10% をテスト用に確保します。

[imdsTrain,imdsTest] = splitEachLabel(imds,0.9,"randomize");

この例で使用されるネットワークには、サイズが 28 x 28 x 1 の入力イメージが必要です。学習イメージのサイズを自動的に変更するには、拡張イメージ データストアを使用します。学習イメージに対して実行する追加の拡張演算として、イメージを水平軸方向および垂直軸方向に最大 5 ピクセルだけランダムに平行移動させる演算を指定します。データ拡張は、ネットワークで過適合が発生したり、学習イメージの正確な詳細が記憶されたりすることを防止するのに役立ちます。

inputSize = [28 28 1];
pixelRange = [-5 5];

imageAugmenter = imageDataAugmenter( ...
    RandXTranslation=pixelRange, ...
    RandYTranslation=pixelRange);

augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain,DataAugmentation=imageAugmenter);

他のデータ拡張を実行せずにテスト イメージのサイズを自動的に変更するには、追加の前処理演算を指定せずに拡張イメージ データストアを使用します。

augimdsTest = augmentedImageDatastore(inputSize(1:2),imdsTest);

学習データ内のクラスの数を決定します。

classes = categories(imdsTrain.Labels);
numClasses = numel(classes);

ネットワークの定義

イメージ分類のネットワークを定義します。

  • イメージ入力用に、学習データと一致する入力サイズのイメージ入力層を指定します。

  • イメージ入力は正規化せず、入力層の Normalization オプションを "none" に設定します。

  • convolution-batchnorm-ReLU ブロックを 3 つ指定します。

  • Padding オプションを "same" に設定して、出力が同じサイズになるように畳み込み層に入力をパディングします。

  • 最初の畳み込み層には、サイズ 5 のフィルターを 20 個指定します。残りの畳み込み層には、サイズ 3 のフィルターを 20 個指定します。

  • 分類用に、クラスの数と一致するサイズの全結合層を指定します。

  • 出力を確率にマッピングするために、ソフトマックス層を含めます。

カスタム学習ループを使用してネットワークに学習させる場合、出力層は含めません。

layers = [
    imageInputLayer(inputSize,Normalization="none")
    convolution2dLayer(5,20,Padding="same")
    batchNormalizationLayer
    reluLayer
    convolution2dLayer(3,20,Padding="same")
    batchNormalizationLayer
    reluLayer
    convolution2dLayer(3,20,Padding="same")
    batchNormalizationLayer
    reluLayer
    fullyConnectedLayer(numClasses)
    softmaxLayer];

層配列から 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

  View summary with summary.

モデル損失関数の定義

深層ニューラル ネットワークの学習は最適化タスクです。ニューラル ネットワークを関数 f(X;θ) と見なすことにより (ここで、X はネットワーク入力、θ は学習可能なパラメーターのセット)、θ を最適化して学習データに基づく損失値を最小化できます。たとえば、与えらえた入力 X と対応するターゲット T に対して、予測 Y=f(X;θ)T の間の誤差が最小になるように、学習可能なパラメーター θ を最適化します。

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

function [loss,gradients,state] = modelLoss(net,X,T)

% Forward data through network.
[Y,state] = forward(net,X);

% Calculate cross-entropy loss.
loss = crossentropy(Y,T);

% Calculate gradients of loss with respect to learnable parameters.
gradients = dlgradient(loss,net.Learnables);

end

SGD 関数の定義

パラメーターと、パラメーターについての損失の勾配を受け取り、確率的勾配降下アルゴリズムを使用して更新されたパラメーターを返す関数 sgdStep を作成します。このアルゴリズムは θt+1=θt-ρL として表現されます。ここで、t は反復回数、ρ は学習率、L は勾配 (学習可能なパラメーターについての損失の微分) を表します。

function parameters = sgdStep(parameters,gradients,learnRate)

parameters = parameters - learnRate .* gradients;

end

カスタム更新関数の定義は、カスタム学習ループに必要な手順ではありません。あるいは、sgdmupdateadamupdate、およびrmspropupdateなどの組み込み更新関数を使用することもできます。

学習オプションの指定

ミニバッチ サイズを 128、学習率を 0.01 として 15 エポック学習させます。

numEpochs = 15;
miniBatchSize = 128;
learnRate = 0.01;

モデルの学習

学習中にイメージのミニバッチを処理および管理する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(augimdsTrain,...
    MiniBatchSize=miniBatchSize,...
    MiniBatchFcn=@preprocessMiniBatch,...
    MiniBatchFormat=["SSCB" ""], ...
    PartialMiniBatch="discard");

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

numObservationsTrain = numel(imdsTrain.Files);
numIterationsPerEpoch = floor(numObservationsTrain / miniBatchSize);
numIterations = numEpochs * numIterationsPerEpoch;

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

monitor = trainingProgressMonitor( ...
    Metrics="Loss", ...
    Info="Epoch", ...
    XLabel="Iteration");

カスタム学習ループを使用してネットワークに学習させます。各エポックについて、データをシャッフルしてデータのミニバッチをループで回します。各ミニバッチで次を行います。

  • 関数 dlfeval と関数 modelLoss を使用してモデルの損失、勾配、および状態を評価し、ネットワークの状態を更新します。

  • カスタム更新関数と共に dlupdate 関数を使用して、ネットワーク パラメーターを更新します。

  • 学習の進行状況モニターで、損失とエポックの値を更新します。

  • モニターの Stop プロパティが true の場合は停止します。[停止] ボタンをクリックすると、TrainingProgressMonitor オブジェクトの Stop プロパティ値が true に変わります。

epoch = 0;
iteration = 0;

% Loop over epochs.
while epoch < numEpochs && ~monitor.Stop
    
    epoch = epoch + 1;

    % Shuffle data.
    shuffle(mbq);
    
    % Loop over mini-batches.
    while hasdata(mbq) && ~monitor.Stop

        iteration = iteration + 1;
        
        % Read mini-batch of data.
        [X,T] = next(mbq);
        
        % Evaluate the model gradients, state, and loss using dlfeval and the
        % modelLoss function and update the network state.
        [loss,gradients,state] = dlfeval(@modelLoss,net,X,T);
        net.State = state;
        
        % Update the network parameters using SGD.
        updateFcn = @(parameters,gradients) sgdStep(parameters,gradients,learnRate);
        net = dlupdate(updateFcn,net,gradients);
        
        % Update the training progress monitor.
        recordMetrics(monitor,iteration,Loss=loss);
        updateInfo(monitor,Epoch=epoch);
        monitor.Progress = 100 * iteration/numIterations;
    end
end

モデルのテスト

testnet関数を使用してニューラル ネットワークをテストします。単一ラベルの分類では、精度を評価します。精度は、正しい予測の割合です。既定では、testnet 関数は利用可能な GPU がある場合にそれを使用します。実行環境を手動で選択するには、testnet 関数の ExecutionEnvironment 引数を使用します。

accuracy = testnet(net,augimdsTest,"accuracy")
accuracy = 
96.3000

混同チャートで予測を可視化します。minibatchpredict関数を使用して予測を行い、scores2label関数を使用して分類スコアをラベルに変換します。既定では、関数 minibatchpredict は利用可能な GPU がある場合にそれを使用します。実行環境を手動で選択するには、minibatchpredict 関数の ExecutionEnvironment 引数を使用します。

scores = minibatchpredict(net,augimdsTest);
YTest = scores2label(scores,classes);

混同チャートで予測を可視化します。

TTest = imdsTest.Labels;
figure
confusionchart(TTest,YTest)

対角線上の大きな値は、対応するクラスに対する正確な予測を示しています。対角線外の大きな値は、対応するクラス間での強い混同を示しています。

サポート関数

ミニ バッチ前処理関数

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

  1. 関数 preprocessMiniBatchPredictors を使用してイメージを前処理します。

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

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

function [X,T] = preprocessMiniBatch(dataX,dataT)

% Preprocess predictors.
X = preprocessMiniBatchPredictors(dataX);

% Extract label data from cell and concatenate.
T = cat(2,dataT{:});

% One-hot encode labels.
T = onehotencode(T,1);

end

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

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

function X = preprocessMiniBatchPredictors(dataX)

% Concatenate.
X = cat(4,dataX{:});

end

入力引数

すべて折りたたむ

ニューラル ネットワーク。次のいずれかの値として指定します。

  • dlnetwork オブジェクト — カスタム学習ループ用のニューラル ネットワーク。

  • TaylorPrunableNetwork オブジェクト — カスタム枝刈りループ用のニューラル ネットワーク。

深層ニューラル ネットワークの枝刈りを行うには、Deep Learning Toolbox Model Compression Library サポート パッケージが必要です。このサポート パッケージは無料のアドオンで、アドオン エクスプローラーを使用してダウンロードできます。または、Deep Learning Toolbox Model Compression Library を参照してください。

入力データ。それぞれ次のいずれかの値として指定します。

  • 形式を整えた dlarray オブジェクト

  • 形式を整えていない dlarray オブジェクト (R2025a 以降)

  • 数値配列 (R2025a 以降)

入力 Xi は、ネットワーク入力 net.InputNames(i) に対応します。

自動微分を使用するカスタム学習ループを使用してニューラル ネットワークに学習させるには、入力データが形式を整えた (または形式を整えていない) dlarray オブジェクトでなければなりません。

ヒント

ニューラル ネットワークには、特定のレイアウトをもつ入力データが必要です。たとえば、ベクトルシーケンス分類ネットワークは通常、tc 列の配列として表されたベクトルシーケンスを必要とします。ここで、tc は、それぞれタイム ステップの数とシーケンスのチャネル数です。ニューラル ネットワークの入力層では、通常、必要とされるデータ レイアウトが指定されています。

ほとんどのデータストアと関数は、ネットワークで必要とされるレイアウトでデータを出力します。データのレイアウトがネットワークで必要とされるレイアウトと異なる場合、InputDataFormats オプションを使用するか、形式を整えた dlarray オブジェクトとして入力データを指定し、データのレイアウトが異なることを示します。通常、入力データを前処理するよりも、InputDataFormats 学習オプションを調整する方が簡単です。

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

形式を整えていないデータを受け取るニューラル ネットワークを作成するには、inputLayer オブジェクトを使用し、形式を指定しないでください。形式を整えていないデータをネットワークに直接入力するには、InputDataFormats 引数を指定しないでください。 (R2025a 以降)

R2025a より前: 入力層を持たないニューラル ネットワークの場合、引数 InputDataFormats を使用して形式を指定するか、形式を整えた dlarray オブジェクトを入力として使用しなければなりません。

名前と値の引数

すべて折りたたむ

オプションの引数のペアを Name1=Value1,...,NameN=ValueN として指定します。ここで、Name は引数名で、Value は対応する値です。名前と値の引数は他の引数の後に指定しなければなりませんが、ペアの順序は重要ではありません。

例: forward(net,X,Outputs=["relu1" "relu2"]) は、名前が "relu1" および "relu2" である層から出力を抽出することを指定します。

ニューラル ネットワーク出力。層の名前または層の出力パスから成る string 配列または文字ベクトルの cell 配列として指定します。次のいずれかの形式を使用して出力を指定します。

  • "layerName"。ここで、layerName は 1 つの出力をもつ層の名前です。

  • "layerName/outputName"。ここで、layerName は層の名前、outputName は層の出力の名前です。

  • "layerName1/.../layerNameK/layerName"。ここで、layerName1, …, layerNameK はサブネットワークを含む一連の層であり、layerName は 1 つの出力をもつ層の名前です。

  • "layerName1/.../layerNameK/layerName/outputName"。ここで、layerName1, …, layerNameK はサブネットワークを含む一連の層、layerName は層の名前、outputName は層の出力の名前です。

  • 1 つの出力をもつ層の場合、層の名前または層の出力のパスを指定します。たとえば、層の名前が "relu1" で、"out" という名前の出力をもつ ReLU 層の場合、層の名前 "relu1" または層の出力パス "relu1/out" を指定します。

  • 複数の出力をもつ層の場合、層の出力のパスを指定します。たとえば、名前が "lstm1" で、"out""hidden"、および "cell" という名前の出力をもつ LSTM 層の場合、"out" という名前の出力を指定するには、層の出力パス "lstm1/out" を指定します。

  • 入れ子ネットワーク内の層の場合、入れ子層を通過する層の出力のパスを指定します。

出力を抽出する層を指定しない場合、既定では、ソフトウェアは net.Outputs で指定された出力を使用します。

パフォーマンスの最適化。次のいずれかの値として指定します。

  • "auto" – 入力ネットワークとハードウェア リソースに適した最適化の回数を自動的に適用します。

  • "none" – すべての最適化を無効にします。

"auto" 高速化オプションを使用すると、パフォーマンス上のメリットが得られますが、初期実行時間が長くなります。互換性のあるパラメーターを使用した後続の呼び出しは、より高速になります。サイズと形状が同じである異なる入力データを使用して関数を複数回呼び出す場合は、パフォーマンスの最適化を使用してください。

R2025a 以降

入力データの次元の説明。string 配列、文字ベクトル、または文字ベクトルの cell 配列として指定します。

InputDataFormats"auto" の場合、ソフトウェアは、ネットワークの入力で必要とされる形式を使用します。そうでない場合、ソフトウェアは、該当するネットワーク入力に対して指定された形式を使用します。

データ形式は文字列で、各文字は対応するデータ次元のタイプを表します。

各文字は以下のとおりです。

  • "S" — 空間

  • "C" — チャネル

  • "B" — バッチ

  • "T" — 時間

  • "U" — 指定なし

たとえば、シーケンスのバッチを表し、1 番目、2 番目、および 3 番目の次元がそれぞれチャネル、観測値、およびタイム ステップに対応する配列があるとします。データは "CBT" (チャネル、バッチ、時間) の形式で記述できます。

"S" または "U" のラベルが付いた次元については、複数回指定できます。ラベル "C""B"、および "T" はそれぞれ 1 回まで使用できます。ソフトウェアは、2 番目の次元の後ろにある大きさが 1 の "U" 次元を無視します。

複数の入力をもつニューラル ネットワーク net の場合、入力データ形式の配列を指定します。ここで、InputDataFormats(i) は入力 net.InputNames(i) に対応します。

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

形式を整えていないデータを受け取るニューラル ネットワークを作成するには、inputLayer オブジェクトを使用し、形式を指定しないでください。形式を整えていないデータをネットワークに直接入力するには、InputDataFormats 引数を指定しないでください。 (R2025a 以降)

R2025a より前: 入力層を持たないニューラル ネットワークの場合、引数 InputDataFormats を使用して形式を指定するか、形式を整えた dlarray オブジェクトを入力として使用しなければなりません。

データ型: char | string | cell

R2025a 以降

出力データの次元の説明。次のいずれかの値として指定します。

  • "auto" — 出力データと入力データの次元の数が同じ場合、関数 forwardInputDataFormats で指定された形式を使用します。出力データと入力データの次元数が異なる場合、forward 関数は、出力データの次元をネットワーク入力層または InputDataFormats 値と一致するように自動的に並べ替えます。

  • string、文字ベクトル、または文字ベクトルの cell 配列 — forward 関数は指定されたデータ形式を使用します。

データ形式は文字列で、各文字は対応するデータ次元のタイプを表します。

各文字は以下のとおりです。

  • "S" — 空間

  • "C" — チャネル

  • "B" — バッチ

  • "T" — 時間

  • "U" — 指定なし

たとえば、シーケンスのバッチを表し、1 番目、2 番目、および 3 番目の次元がそれぞれチャネル、観測値、およびタイム ステップに対応する配列があるとします。データは "CBT" (チャネル、バッチ、時間) の形式で記述できます。

"S" または "U" のラベルが付いた次元については、複数回指定できます。ラベル "C""B"、および "T" はそれぞれ 1 回まで使用できます。ソフトウェアは、2 番目の次元の後ろにある大きさが 1 の "U" 次元を無視します。

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

データ型: char | string | cell

出力引数

すべて折りたたむ

複数の出力をもつネットワークの出力データ。次のいずれかの値として返されます。

  • 形式を整えた dlarray オブジェクト

  • 形式を整えていない dlarray オブジェクト (R2025a 以降)

  • 数値配列 (R2025a 以降)

データ型は入力データのデータ型と同じです。

出力 Y1, …, YN の順序は、Outputs 引数で指定された出力の順序と一致します。

分類ニューラル ネットワークの場合、出力の要素は各クラスのスコアに対応します。スコアの順序は、学習データ内のカテゴリの順序と一致します。たとえば、カテゴリカル ラベル TTrain を使用してニューラル ネットワークに学習させた場合、スコアの順序は、categories(TTrain) によって指定されたカテゴリの順序と一致します。

更新されたネットワークの状態。table として返されます。

ネットワークの状態は、次の 3 つの列をもつ table です。

  • Layer – 層の名前。string スカラーとして指定します。

  • Parameter – 状態パラメーターの名前。string スカラーとして指定します。

  • Value – 状態パラメーターの値。dlarray オブジェクトとして指定します。

層の状態には、層の処理中に計算された情報が格納されます。この情報は、層の後続のフォワード パスで使用するために保持されます。たとえば、LSTM 層にはセル状態と隠れ状態が格納され、バッチ正規化層によって実行中の統計が計算されます。

LSTM 層などの再帰層の場合、HasStateInputs プロパティを 1 (true) に設定すると、その層の状態に関するエントリはステート テーブルに格納されません。

State プロパティを使用して dlnetwork の状態を更新します。

枝刈り層の活性化の cell 配列 (入力ネットワークが TaylorPrunableNetwork オブジェクトの場合)。

拡張機能

すべて展開する

バージョン履歴

R2019b で導入

すべて展開する