ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

新しいイメージを分類するための深層学習ネットワークの学習

この例では、転移学習を使用して、畳み込みニューラル ネットワークの再学習を行い、新しい一連のイメージを分類する方法を説明します。

事前学習済みのイメージ分類ネットワークは、100 万枚を超えるイメージで学習しており、イメージを 1000 個のオブジェクト カテゴリ (キーボード、マグ カップ、鉛筆、多くの動物など) に分類できます。このネットワークは広範囲にわたるイメージについての豊富な特徴表現を学習しています。このネットワークは入力としてイメージを取り、イメージ内のオブジェクトのラベルを各オブジェクト カテゴリの確率と共に出力します。

転移学習は、深層学習アプリケーションでよく使用されています。事前学習済みのネットワークを取得して、新しいタスクの学習の開始点として使用できます。通常は、転移学習によってネットワークを微調整する方が、ランダムに初期化された重みでゼロからネットワークに学習させるよりもはるかに簡単で時間がかかりません。少ない数の学習イメージを使用して、新しいタスクに学習済みの特徴を高速に転移できます。

データの読み込み

新しいイメージを解凍してイメージ データストアとして読み込みます。この非常に小さいデータセットには 75 枚のイメージのみが含まれています。データを学習データセットと検証データセットに分割します。イメージの 70% を学習に使用し、30% を検証に使用します。

unzip('MerchData.zip');
imds = imageDatastore('MerchData', ...
    'IncludeSubfolders',true, ...
    'LabelSource','foldernames'); 
[imdsTrain,imdsValidation] = splitEachLabel(imds,0.7);

事前学習済みのネットワークの読み込み

事前学習済みの GoogLeNet ネットワークを読み込みます。Deep Learning Toolbox™ Model for GoogLeNet Network サポート パッケージがインストールされていない場合、ダウンロード用リンクが表示されます。

別の事前学習済みネットワークを試すには、この例を MATLAB® で開き、別のネットワークを選択します。たとえば、googlenet よりも高速なネットワークである squeezenet を試すことができます。この例は、他の事前学習済みネットワークを使用して実行することもできます。使用可能なすべてのネットワークについては、事前学習済みのネットワークの読み込みを参照してください。

net = googlenet;

analyzeNetwork を使用して、ネットワーク アーキテクチャを対話的に可視化し、ネットワーク層についての詳細情報を表示します。

analyzeNetwork(net)

ネットワークの Layers プロパティの最初の要素はイメージ入力層です。この層にはサイズが 224 x 224 x 3 の入力イメージが必要です。ここで、3 はカラー チャネルの数です。

net.Layers(1)
ans = 
  ImageInputLayer with properties:

                Name: 'data'
           InputSize: [224 224 3]

   Hyperparameters
    DataAugmentation: 'none'
       Normalization: 'zerocenter'
        AverageImage: [224x224x3 single]

inputSize = net.Layers(1).InputSize;

最後の層の置き換え

ネットワークの畳み込み層は、入力イメージを分類するために、最後の学習可能な層と最終分類層が使用するイメージの特徴を抽出します。GoogLeNet のこれらの 2 つの層 'loss3-classifier' および 'output' は、ネットワークによって抽出された特徴を組み合わせてクラス確率、損失値、および予測ラベルにまとめる方法に関する情報を含んでいます。新しいイメージを分類するために事前学習済みのネットワークを再学習させるには、これら 2 つの層を新しいデータセットに適応させた新しい層に置き換えます。

学習済みのネットワークから層グラフを抽出します。ネットワークが AlexNet、VGG-16、VGG-19 などの SeriesNetwork オブジェクトである場合、net.Layers の層のリストを層グラフに変換します。

if isa(net,'SeriesNetwork') 
  lgraph = layerGraph(net.Layers); 
else
  lgraph = layerGraph(net);
end 

置き換える 2 つの層の名前を見つけます。これは手動で行うことも、サポート関数 findLayersToReplace を使用してこれらの層を自動的に見つけることもできます。

[learnableLayer,classLayer] = findLayersToReplace(lgraph);
[learnableLayer,classLayer] 
ans = 
  1x2 Layer array with layers:

     1   'loss3-classifier'   Fully Connected         1000 fully connected layer
     2   'output'             Classification Output   crossentropyex with 'tench' and 999 other classes

ほとんどのネットワークでは、学習可能な重みを持つ最後の層は全結合層です。この全結合層を、新しいデータセットのクラスの数 (この例では 5) と同じ数の出力を持つ新しい全結合層に置き換えます。SqueezeNet などの一部のネットワークでは、その代わりに最後の学習可能な層が 1 x 1 畳み込み層となっています。この場合は、その畳み込み層を、クラスの数と同じ数のフィルターを持つ新しい畳み込み層に置き換えます。新しい層での学習速度を転移された層より速くするには、層の学習率係数を大きくします。

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

if isa(learnableLayer,'nnet.cnn.layer.FullyConnectedLayer')
    newLearnableLayer = fullyConnectedLayer(numClasses, ...
        'Name','new_fc', ...
        'WeightLearnRateFactor',10, ...
        'BiasLearnRateFactor',10);
    
elseif isa(learnableLayer,'nnet.cnn.layer.Convolution2DLayer')
    newLearnableLayer = convolution2dLayer(1,numClasses, ...
        'Name','new_conv', ...
        'WeightLearnRateFactor',10, ...
        'BiasLearnRateFactor',10);
end

lgraph = replaceLayer(lgraph,learnableLayer.Name,newLearnableLayer);

分類層はネットワークの出力クラスを指定します。分類層をクラス ラベルがない新しい分類層に置き換えます。trainNetwork は、学習時に層の出力クラスを自動的に設定します。

newClassLayer = classificationLayer('Name','new_classoutput');
lgraph = replaceLayer(lgraph,classLayer.Name,newClassLayer);

新しい層が正しく結合されていることを確認するには、新しい層グラフをプロットして、ネットワークの最後の方の層を拡大します。

figure('Units','normalized','Position',[0.3 0.3 0.4 0.4]);
plot(lgraph)
ylim([0,10])

初期の層の凍結

これで、新しい一連のイメージでネットワークに再学習させる準備が整いました。オプションで、ネットワークの初期の層について学習率を 0 に設定すると、それらの層の重みを "凍結" できます。学習中に trainNetwork は凍結された層のパラメーターを更新しません。凍結された層の勾配は計算する必要がないため、多数の初期の層について重みを凍結すると、ネットワーク学習を大幅に高速化できます。新しいデータセットが小さい場合、初期のネットワーク層を凍結すると、新しいデータセットに対するこれらの層の過適合を防止することもできます。

層グラフの層および結合を抽出し、凍結する層を選択します。GoogLeNet では、最初の 10 個の層がネットワークの初期 'ステム' を作ります。サポート関数 freezeWeights を使用して、最初の 10 個の層について学習率を 0 に設定します。サポート関数 createLgraphUsingConnections を使用して、すべての層を元の順序で再結合します。新しい層グラフに含まれる層は元と同じですが、初期の層の学習率は 0 に設定されています。

layers = lgraph.Layers;
connections = lgraph.Connections;

layers(1:10) = freezeWeights(layers(1:10));
lgraph = createLgraphUsingConnections(layers,connections);

ネットワークの学習

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

pixelRange = [-30 30];
scaleRange = [0.9 1.1];
imageAugmenter = imageDataAugmenter( ...
    'RandXReflection',true, ...
    'RandXTranslation',pixelRange, ...
    'RandYTranslation',pixelRange, ...
    'RandXScale',scaleRange, ...
    'RandYScale',scaleRange);
augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain, ...
    'DataAugmentation',imageAugmenter);

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

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

学習オプションを指定します。InitialLearnRate を小さい値に設定して、まだ凍結されていない転移層での学習速度を下げます。上記の手順では、最後の学習可能な層の学習率係数を大きくして、新しい最後の層での学習時間を短縮しています。この学習率設定の組み合わせによって、新しい層では高速に学習が行われ、中間層では学習速度が低下し、凍結された初期の層では学習が行われません。

学習するエポック数を指定します。転移学習の実行時には、同じエポック数の学習を行う必要はありません。エポックとは、学習データセット全体の完全な学習サイクルのことです。ミニバッチのサイズと検証データを指定します。エポックごとに 1 回、検定精度を計算します。

miniBatchSize = 10;
valFrequency = floor(numel(augimdsTrain.Files)/miniBatchSize);
options = trainingOptions('sgdm', ...
    'MiniBatchSize',miniBatchSize, ...
    'MaxEpochs',6, ...
    'InitialLearnRate',3e-4, ...
    'Shuffle','every-epoch', ...
    'ValidationData',augimdsValidation, ...
    'ValidationFrequency',valFrequency, ...
    'Verbose',false, ...
    'Plots','training-progress');

学習データを使用してネットワークに学習させます。既定では、利用可能な GPU がある場合、trainNetwork は GPU を使用します (Parallel Computing Toolbox™、および Compute Capability 3.0 以上の CUDA® 対応 GPU が必要)。そうでない場合、trainNetwork は CPU を使用します。trainingOptions の名前と値のペアの引数 'ExecutionEnvironment' を使用して、実行環境を指定することもできます。データセットのサイズが非常に小さいため、学習は短時間で終了します。

net = trainNetwork(augimdsTrain,lgraph,options);

検証イメージの分類

微調整したネットワークを使用して検証イメージを分類し、分類精度を計算します。

[YPred,probs] = classify(net,augimdsValidation);
accuracy = mean(YPred == imdsValidation.Labels)
accuracy = 0.9000

4 枚のサンプル検証イメージを、予測ラベルとイメージがそれらのラベルを持つ予測確率と共に表示します。

idx = randperm(numel(imdsValidation.Files),4);
figure
for i = 1:4
    subplot(2,2,i)
    I = readimage(imdsValidation,idx(i));
    imshow(I)
    label = YPred(idx(i));
    title(string(label) + ", " + num2str(100*max(probs(idx(i),:)),3) + "%");
end

参照

[1] Szegedy, Christian, Wei Liu, Yangqing Jia, Pierre Sermanet, Scott Reed, Dragomir Anguelov, Dumitru Erhan, Vincent Vanhoucke, and Andrew Rabinovich. "Going deeper with convolutions." In Proceedings of the IEEE conference on computer vision and pattern recognition, pp. 1-9. 2015.

参考

| | | | | | | | | |

関連するトピック