Main Content

ディープ ネットワーク デザイナーを使用した転移学習用のネットワークの準備

この例では、ディープ ネットワーク デザイナー アプリを使用して転移学習用のネットワークを対話形式で準備する方法を示します。

転移学習は、事前学習済みの深層学習ネットワークを利用して、新しいタスクを学習するように微調整するプロセスです。通常は、転移学習を使用する方が、ネットワークにゼロから学習させるよりも簡単で時間もかかりません。少量のデータを使用して、新しいタスクに学習済みの特徴を高速に転移できます。

データの解凍

MathWorks Merch データセットを抽出します。これは、75 個の MathWorks の商品イメージから成る小さなデータセットであり、5 つの異なるクラス (cap、cube、playing cards、screwdriver、torch) に属します。データは、これら 5 つのクラスに対応するサブフォルダーにイメージが置かれる配置になっています。

folderName = "MerchData";
unzip("MerchData.zip",folderName);

イメージ データストアを作成します。イメージ データストアを使用すると、イメージ データの大規模なコレクション (メモリに収まらないデータなど) を格納し、ニューラル ネットワークの学習中にイメージをバッチ単位で効率的に読み取ることができます。抽出したイメージがあるフォルダーを指定し、サブフォルダー名がイメージ ラベルに対応していることを示します。

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

いくつかのサンプル イメージを表示します。

numImages = numel(imds.Labels);
idx = randperm(numImages,16);
I = imtile(imds,Frames=idx);
figure
imshow(I)

クラス名とクラス数を抽出します。

classNames = categories(imds.Labels);
numClasses = numel(classNames)
numClasses = 5

データを学習データセット、検証データセット、テスト データセットに分割します。イメージの 70% は学習に使用し、15% は検証に使用し、15% はテストに使用します。関数 splitEachLabel は、イメージ データストアを 2 つの新しいデータストアに分割します。

[imdsTrain,imdsValidation,imdsTest] = splitEachLabel(imds,0.7,0.15,0.15,"randomized");

事前学習済みのネットワークの選択

ディープ ネットワーク デザイナーを開くには、[アプリ] タブの [機械学習および深層学習] でアプリのアイコンをクリックします。あるいは、コマンド ラインからアプリを開くこともできます。

deepNetworkDesigner

ディープ ネットワーク デザイナーには、広範囲のイメージに適した豊富な特徴表現を学習している、さまざまな事前学習済みのイメージ分類ネットワークが用意されています。転移学習は、使用するイメージが、ネットワークの学習時にもともと使用されたイメージに類似している場合に特に効果を発揮します。使用する学習イメージが ImageNet データベースに含まれるような自然イメージの場合、どの事前学習済みネットワークも適しています。使用可能なネットワークの一覧、およびネットワークを比較する方法については、事前学習済みの深層ニューラル ネットワークを参照してください。

使用するデータが ImageNet のデータと大きく異なる場合 (たとえば、非常に小さいイメージ、スペクトログラム、またはイメージ以外のデータを使用する場合) は、新しいネットワークに学習させる方が良いこともあります。ネットワークにゼロから学習させる方法を示す例については、Get Started with Time Series Forecastingを参照してください。

SqueezeNet では追加のサポート パッケージが必要ありません。その他の事前学習済みネットワークでは、必要なサポート パッケージがインストールされていない場合、[インストール] オプションがアプリに表示されます。

事前学習済みネットワークの一覧から [SqueezeNet] を選択し、[開く] をクリックします。

ネットワークの調査

ディープ ネットワーク デザイナーの [デザイナー] ペインにネットワーク全体が縮小表示されます。

ネットワークのプロットを確認します。マウスでズームインするには、Ctrl キーを押しながらスクロール ホイールを使用します。移動するには、方向キーを使用するか、スクロール ホイールを押したままでマウスをドラッグします。プロパティを表示する層を選択します。すべての層の選択を解除すると、[プロパティ] ペインにネットワークの概要が表示されます。

イメージ入力層 'input' を選択します。このネットワークの入力サイズが 227×227×3 ピクセルであることがわかります。

入力サイズを変数 inputSize に保存します。

inputSize = [227 227 3];

学習用のネットワークの準備

転移学習に事前学習済みネットワークを使用するには、新しいデータセットに一致するようにクラス数を変更しなければなりません。まず、ネットワークの最後の学習可能な層を見つけます。SqueezeNet の最後の学習可能な層は、最後の畳み込み層 'conv10' です。'conv10' 層を選択します。[プロパティ] ペインの下部で、[層のロックを解除] をクリックします。表示される警告ダイアログで、[ロックの強制解除] をクリックします。これにより層のプロパティのロックが解除され、それらを新しいタスクに適応できるようになります。

R2023b より前: ネットワークを新しいデータに適応させるには、層のロックを解除するのではなく、層を置き換えなければなりません。新しい 2 次元畳み込み層で、FilterSize を [1 1] に設定します。

NumFilters プロパティは、分類問題のクラス数を定義します。NumFilters を新しいデータのクラス数 (この例では 5) に変更します。

WeightLearnRateFactor および BiasLearnRateFactor10 に設定して学習率を変更し、新しい層での学習速度を転移層より速くします。

ネットワークの確認

ネットワークの学習の準備が整っていることを確認するには、[解析] をクリックします。深層学習ネットワーク アナライザーによってエラーや警告が報告されていないため、ネットワークの学習の準備は整っています。ネットワークをエクスポートするには、[エクスポート] をクリックします。アプリはネットワークを変数 net_1 に保存します。

学習用データの準備

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

pixelRange = [-30 30];

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

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

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

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

学習オプションの指定

学習オプションを指定します。オプションの中から選択するには、経験的解析が必要です。実験を実行してさまざまな学習オプションの構成を調べるには、Experiment Managerアプリを使用できます。

  • Adam オプティマイザーを使用して学習させます。

  • 初期学習率を小さい値に設定して、転移層での学習速度を下げます。

  • 小さい数のエポックを指定します。エポックとは、学習データ セット全体の完全な学習サイクルのことです。転移学習の場合、同じエポック数の学習を行う必要はありません。

  • 各エポックで 1 回、検証データに対する精度が計算されるように、検証データと検証頻度を指定します。

  • ミニバッチのサイズ、つまり各反復で使用するイメージの数を指定します。それぞれのエポックで必ずデータセット全体が使用されるように、学習サンプルの数を均等に分割するようミニバッチのサイズを設定します。

  • 学習の進行状況をプロットで表示し、精度メトリクスを監視します。

  • 詳細出力を無効にします。

options = trainingOptions("adam", ...
    InitialLearnRate=0.0001, ...
    MaxEpochs=8, ...
    ValidationData=imdsValidation, ...
    ValidationFrequency=5, ...
    MiniBatchSize=11, ...
    Plots="training-progress", ...
    Metrics="accuracy", ...
    Verbose=false);

ニューラル ネットワークの学習

関数trainnetを使用してニューラル ネットワークに学習させます。分類タスクには、クロスエントロピー損失を使用します。既定では、関数 trainnet は利用可能な GPU がある場合にそれを使用します。GPU を使用するには、Parallel Computing Toolbox™ ライセンスとサポートされている GPU デバイスが必要です。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。そうでない場合、関数 trainnet は CPU を使用します。実行環境を指定するには、ExecutionEnvironment 学習オプションを使用します。

net = trainnet(imdsTrain,net_1,"crossentropy",options);

ニューラル ネットワークのテスト

テスト イメージを分類します。複数の観測値を使用して予測を行うには、関数minibatchpredictを使用します。予測スコアをラベルに変換するには、関数 scores2label を使用します。関数 minibatchpredict は利用可能な GPU がある場合に自動的にそれを使用します。

YTest = minibatchpredict(net,augimdsTest);
YTest = scores2label(YTest,classNames);

混同チャートで分類精度を可視化します。

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

新しいデータでの予測の実行

イメージを分類します。JPEG ファイルからイメージを読み取り、サイズを変更し、single データ型に変換します。

im = imread("MerchDataTest.jpg");
im = imresize(im,inputSize(1:2));
X = single(im);

イメージを分類します。単一の観測値を使用して予測を行うには、関数 predict を使用します。GPU を使用するには、まずデータを gpuArray に変換します。

if canUseGPU
    X = gpuArray(X);
end
scores = predict(net,X);
[label,score] = scores2label(scores,classNames);

予測されたラベルと対応するスコアを含むイメージを表示します。

figure
imshow(im)
title(string(label) + " (Score: " + gather(score) + ")")

参考

関連するトピック