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

squeezenet

SqueezeNet 畳み込みニューラル ネットワーク

説明

SqueezeNet は、深さが 18 層の畳み込みニューラル ネットワークです。100 万枚を超えるイメージで学習させた事前学習済みのネットワークを、ImageNet データベース [1] から読み込むことができます。この事前学習済みのネットワークは、イメージを 1000 個のオブジェクト カテゴリ (キーボード、マウス、鉛筆、多くの動物など) に分類できます。結果として、このネットワークは広範囲のイメージに対する豊富な特徴表現を学習しています。この関数は SqueezeNet v1.1 ネットワークを返します。このネットワークの精度は SqueezeNet v1.0 と同様ですが、予測あたりに必要な浮動小数点演算回数は少なくなります [3]。ネットワークのイメージ入力サイズは 227 x 227 です。MATLAB® の他の事前学習済みのネットワークについては、事前学習済みの深層ニューラル ネットワークを参照してください。

classify を使用すると、SqueezeNet ネットワークを使用して新しいイメージを分類できます。例については、SqueezeNet を使用したイメージの分類 を参照してください。

SqueezeNet ネットワークの再学習を行って、転移学習を使用して新しいタスクを実行できます。例については、SqueezeNet を使用した対話型の転移学習 を参照してください。

net = squeezenet は、ImageNet データセットで学習させた SqueezeNet ネットワークを返します。

net = squeezenet('Weights','imagenet') は、ImageNet データセットで学習させた SqueezeNet ネットワークを返します。この構文は、net = squeezenet と等価です。

lgraph = squeezenet('Weights','none')は、未学習の SqueezeNet ネットワーク アーキテクチャを返します。

すべて折りたたむ

事前学習済みの SqueezeNet ネットワークを読み込みます。

net = squeezenet
net = 

  DAGNetwork with properties:

         Layers: [68×1 nnet.cnn.layer.Layer]
    Connections: [75×2 table]

この関数は、DAGNetwork オブジェクトを返します。

SqueezeNet は Deep Learning Toolbox™ に含まれています。その他のネットワークを読み込むには、googlenet などの関数を使用して、アドオン エクスプローラーから事前学習済みのネットワークをダウンロードするためのリンクを取得します。

この例では、事前学習済みの SqueezeNet ネットワークを微調整して、新しいイメージ コレクションを分類する方法を説明します。このプロセスは転移学習と呼ばれ、通常、新しいネットワークに学習させるよりもはるかに簡単で時間がかかりません。これは、少ない数の学習イメージを使用して、新しいタスクに学習済みの特徴を適用できるためです。転移学習用のネットワークを対話形式で準備するには、ディープ ネットワーク デザイナーを使用します。

データの解凍

ワークスペースで、MathWorks Merch データセットを解凍します。このデータセットは MathWorks の商品イメージ 75 個から成る小さなデータセットで、5 つの異なるクラス (capcubeplaying cardsscrewdrivertorch) に属します。

unzip("MerchData.zip");

ディープ ネットワーク デザイナーで SqueezeNet を開く

ディープ ネットワーク デザイナーを開きます。

deepNetworkDesigner

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

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

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

データのインポート

ディープ ネットワーク デザイナーにデータを読み込むには、[データ] タブにある [データのインポート] をクリックします。[データのインポート] ダイアログ ボックスが開きます。

[データ ソース] リストの [フォルダー] を選択します。[参照] をクリックし、解凍した MerchData フォルダーを選択します。

データを 70% の学習データと 30% の検証データに分割します。

学習イメージに対して実行する拡張演算を指定します。この例では、X 軸方向のランダムな反転、[-90,90] 度の範囲のランダムな回転、[1,2] の範囲のランダムな再スケーリングを実行します。データ拡張は、ネットワークで過適合が発生したり、学習イメージの正確な詳細が記憶されたりすることを防止するのに役立ちます。

[インポート] をクリックして、ディープ ネットワーク デザイナーにデータをインポートします。

データの可視化

ディープ ネットワーク デザイナーを使用すると、[データ] ペインにある学習データと検証データの分布を視覚的に検証できます。この例では、データセットにクラスが 5 つあることが確認できます。

転移学習用のネットワークの編集

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

ほとんどのネットワークでは、学習可能な重みを持つ最後の層は全結合層です。SqueezeNet などの一部のネットワークでは、その代わりに最後の学習可能な層が最終畳み込み層となっています。この場合は、その畳み込み層を、クラスの数と同じ数のフィルターを持つ新しい畳み込み層に置き換えます。

[デザイナー] ペインで、新しい convolutional2dLayer をキャンバスにドラッグします。元の畳み込み層と一致させるために、FilterSize1,1 に設定します。NumFilters を新しいデータのクラス数 (この例では 5) に変更します。

WeightLearnRateFactor および BiasLearnRateFactor を 10 に設定して学習率を変更し、新しい層での学習速度を転移層より速くします。最後の 2 次元畳み込み層を削除して、代わりに新しい層を結合します。

出力層を置き換えます。[層のライブラリ] の最後までスクロールして、新しい classificationLayer をキャンバスにドラッグします。元の出力層を削除して、代わりに新しい層を結合します。

ネットワークの確認

編集したネットワークの学習の準備が整っていることを確認するには、[解析] をクリックし、深層学習ネットワーク アナライザーによって誤差 0 が報告されていることを確認します。

ネットワークの学習

学習オプションの指定。[学習] タブを選択し、[学習オプション] をクリックします。

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

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

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

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

この例では、InitialLearnRate0.0001 に、ValidationFrequency5 に、MaxEpochs8 に設定します。観測値が 55 個あるため、MiniBatchSize を 11 に設定します。

指定した学習オプションでネットワークを学習させるために、[閉じる] をクリックしてから [学習] をクリックします。

ディープ ネットワーク デザイナーでは、学習の進行状況の可視化と監視が行えます。必要に応じて、学習オプションを編集してネットワークを再学習させることができます。

結果のエクスポートと MATLAB コードの生成

学習された重みを含むネットワーク アーキテクチャをエクスポートするには、[学習] タブの [エクスポート]、[学習済みネットワークと結果のエクスポート] を選択します。ディープ ネットワーク デザイナーによって、学習済みネットワークが変数 trainedNetwork_1 に、学習情報が変数 trainInfoStruct_1 にエクスポートされます。

trainInfoStruct_1
trainInfoStruct_1 = struct with fields:
               TrainingLoss: [1×40 double]
           TrainingAccuracy: [1×40 double]
             ValidationLoss: [4.8267 NaN NaN NaN 2.1034 NaN NaN NaN NaN 1.2332 NaN NaN NaN NaN 0.6614 NaN NaN NaN NaN 0.4312 NaN NaN NaN NaN 0.2878 NaN NaN NaN NaN 0.2472 NaN NaN NaN NaN 0.2647 NaN NaN NaN NaN 0.2893]
         ValidationAccuracy: [10 NaN NaN NaN 10 NaN NaN NaN NaN 40 NaN NaN NaN NaN 80 NaN NaN NaN NaN 90 NaN NaN NaN NaN 95 NaN NaN NaN NaN 95 NaN NaN NaN NaN 95 NaN NaN NaN NaN 95]
              BaseLearnRate: [1×40 double]
        FinalValidationLoss: 0.2893
    FinalValidationAccuracy: 95

使用するネットワークと学習オプションを再作成する MATLAB コードを生成することもできます。[学習] タブの [エクスポート]、[学習用コードの生成] を選択します。MATLAB コードを確認して、学習データの準備、ネットワーク アーキテクチャの作成、ネットワークの学習をプログラムで行う方法を学びます。

新しいイメージの分類

学習済みネットワークを使用して分類する新しいイメージを読み込みます。

I = imread("MerchDataTest.jpg");

イメージ サイズは学習の間、ネットワークの入力サイズに合うようにディープ ネットワーク デザイナーにより変更されます。ネットワークの入力サイズを確認するには、[デザイナー] ペインに移動して imageInputLayer (最初のレイヤー) を選択します。このネットワークの入力サイズは 227 x 227 です。

ネットワークの入力サイズに合うようにテスト イメージをサイズ変更します。

I = imresize(I, [227 227]);

学習済みネットワークを使用してテスト イメージを分類します。

[YPred,probs] = classify(trainedNetwork_1,I);
imshow(I)
label = YPred;
title(string(label) + ", " + num2str(100*max(probs),3) + "%");

この例では、事前学習済みの SqueezeNet 畳み込みニューラル ネットワークを微調整して、新しいイメージ コレクションを分類する方法を説明します。

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

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

データの読み込み

新しいイメージを解凍してイメージ データストアとして読み込みます。imageDatastore は、フォルダー名に基づいてイメージに自動的にラベルを付け、データを ImageDatastore オブジェクトとして格納します。イメージ データストアを使用すると、メモリに収まらないデータなどの大きなイメージ データを格納し、畳み込みニューラル ネットワークの学習中にイメージをバッチ単位で効率的に読み取ることができます。

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

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

[imdsTrain,imdsValidation] = splitEachLabel(imds,0.7,'randomized');

このとき、この非常に小さなデータセットには、55 個の学習イメージと 20 個の検証イメージが格納されています。いくつかのサンプル イメージを表示します。

numTrainImages = numel(imdsTrain.Labels);
idx = randperm(numTrainImages,16);

I = imtile(imds, 'Frames', idx);

figure
imshow(I)

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

事前学習済みの SqueezeNet ニューラル ネットワークを読み込みます。

net = squeezenet;

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

analyzeNetwork(net)

最初の層であるイメージ入力層には、サイズが 227 x 227 x 3 の入力イメージが必要です。ここで、3 はカラー チャネルの数です。

inputSize = net.Layers(1).InputSize
inputSize = 1×3

   227   227     3

最後の層の置き換え

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

学習済みのネットワークから層グラフを抽出します。

lgraph = layerGraph(net); 

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

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

     1   'conv10'                            Convolution             1000 1x1x512 convolutions with stride [1  1] and padding [0  0  0  0]
     2   'ClassificationLayer_predictions'   Classification Output   crossentropyex with 'tench' and 999 other classes

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

numClasses = numel(categories(imdsTrain.Labels))
numClasses = 5
newConvLayer =  convolution2dLayer([1, 1],numClasses,'WeightLearnRateFactor',10,'BiasLearnRateFactor',10,"Name",'new_conv');
lgraph = replaceLayer(lgraph,'conv10',newConvLayer);

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

newClassificatonLayer = classificationLayer('Name','new_classoutput');
lgraph = replaceLayer(lgraph,'ClassificationLayer_predictions',newClassificatonLayer);

ネットワークの学習

ネットワークにはサイズが 227 x 227 x 3 の入力イメージが必要ですが、イメージ データストアにあるイメージのサイズは異なります。拡張イメージ データストアを使用して学習イメージのサイズを自動的に変更します。学習イメージに対して実行する追加の拡張演算として、学習イメージを縦軸に沿ってランダムに反転させる演算や、水平方向および垂直方向に最大 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);

学習オプションを指定します。転移学習の場合、事前学習済みのネットワークの初期の層からの特徴 (転移された層の重み) を保持します。転移層での学習速度を下げるため、初期学習率を小さい値に設定します。上記の手順では、畳み込み層の学習率係数を大きくして、新しい最後の層での学習時間を短縮しています。この学習率設定の組み合わせによって、新しい層でのみ学習が急速に進み、他の層での学習速度は低下します。転移学習の実行時には、同じエポック数の学習を行う必要はありません。エポックとは、学習データセット全体の完全な学習サイクルのことです。エポックごとにすべてのデータが検証されるように、ミニバッチのサイズを 11 に指定します。学習中は ValidationFrequency 回の反復ごとにネットワークが検証されます。

options = trainingOptions('sgdm', ...
    'MiniBatchSize',11, ...
    'MaxEpochs',7, ...
    'InitialLearnRate',2e-4, ...
    'Shuffle','every-epoch', ...
    'ValidationData',augimdsValidation, ...
    'ValidationFrequency',3, ...
    'Verbose',false, ...
    'Plots','training-progress');

転移層と新しい層とで構成されるネットワークに学習させます。既定では、利用可能な GPU がある場合、trainNetwork は GPU を使用します (Parallel Computing Toolbox™、および Compute Capability 3.0 以上の CUDA® 対応 GPU が必要)。そうでない場合は CPU が使用されます。trainingOptions の名前と値のペアの引数 'ExecutionEnvironment' を使用して、実行環境を指定することもできます。

netTransfer = trainNetwork(augimdsTrain,lgraph,options);

検証イメージの分類

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

[YPred,scores] = classify(netTransfer,augimdsValidation);

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));
end

検証セットに対する分類精度を計算します。精度とは、ネットワークによって予測が正しく行われるラベルの割合です。

YValidation = imdsValidation.Labels;
accuracy = mean(YPred == YValidation)
accuracy = 1

分類精度の向上に関するヒントは、深層学習のヒントとコツを参照してください。

SqueezeNet を使用してイメージの読み取り、サイズ変更、および分類を行います。

まず、事前学習済みの SqueezeNet ネットワークを読み込みます。

net = squeezenet;

imread を使用してイメージを読み取ります。

I = imread('peppers.png');
figure
imshow(I)

事前学習済みのモデルは、イメージ サイズがネットワークの入力サイズと同じである必要があります。ネットワークの最初の層の InputSize プロパティを使用して、ネットワークの入力サイズを求めます。

sz = net.Layers(1).InputSize
sz = 1×3

   227   227     3

ネットワークの入力サイズに合わせてイメージをトリミングします。または、imresize を使用してイメージのサイズを変更できます。

I = I(1:sz(1),1:sz(2),1:sz(3));
figure
imshow(I)

classify を使用してイメージを分類します。

label = classify(net,I)
label = categorical
     bell pepper 

イメージと分類結果をまとめて表示します。

figure
imshow(I)
title(label)

この例では、事前学習済みの畳み込みニューラル ネットワークから学習済みのイメージの特徴を抽出し、これらの特徴を使用してイメージ分類器に学習させる方法を説明します。特徴抽出は、事前学習済みの深いネットワークの表現能力を活用できる最も簡単で時間のかからない方法です。たとえば、抽出した特徴に対して fitcecoc (Statistics and Machine Learning Toolbox™) を使用してサポート ベクター マシン (SVM) に学習させることができます。特徴抽出が必要とするものはデータを一巡する 1 つのパスのみであるため、ネットワークの学習を加速するための GPU がない場合、これは適切な開始点となります。

データの読み込み

サンプル イメージを解凍してイメージ データストアとして読み込みます。imageDatastore は、フォルダー名に基づいてイメージに自動的にラベルを付け、データを ImageDatastore オブジェクトとして格納します。イメージ データストアを使用すると、メモリに収まらないデータを含む大きなイメージ データを格納できます。データを 70% の学習データと 30% のテスト データに分割します。

unzip('MerchData.zip');

imds = imageDatastore('MerchData', ...
    'IncludeSubfolders',true, ...
    'LabelSource','foldernames');

[imdsTrain,imdsTest] = splitEachLabel(imds,0.7,'randomized');

このとき、この非常に小さなデータセットには、55 個の学習イメージと 20 個の検証イメージが格納されています。いくつかのサンプル イメージを表示します。

numImagesTrain = numel(imdsTrain.Labels);
idx = randperm(numImagesTrain,16);

I = imtile(imds, 'Frames', idx);

figure
imshow(I)

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

事前学習済みの SqueezeNet ネットワークを読み込みます。SqueezeNet は、100 万枚を超えるイメージについて学習済みであり、イメージを 1,000 個のオブジェクト カテゴリ (キーボード、マウス、鉛筆、多くの動物など) に分類できます。結果として、このモデルは広範囲のイメージに対する豊富な特徴表現を学習しています。

net = squeezenet;

ネットワーク アーキテクチャを解析します。

analyzeNetwork(net)

最初の層であるイメージ入力層には、サイズが 227 x 227 x 3 の入力イメージが必要です。ここで、3 はカラー チャネルの数です。

inputSize = net.Layers(1).InputSize
inputSize = 1×3

   227   227     3

イメージの特徴の抽出

ネットワークは、入力イメージの階層表現を構築します。深い層には、初期の層の低レベルの特徴を使用して構築された、より高レベルの特徴が含まれます。学習イメージとテスト イメージの特徴表現を取得するには、グローバル平均プーリング層 'pool10'activations を使用します。イメージの低レベルの表現を取得するには、ネットワークの初期の層を使用します。

ネットワークにはサイズが 227 x 227 x 3 の入力イメージが必要ですが、イメージ データストアにあるイメージのサイズは異なります。学習およびテスト イメージのサイズをネットワークへの入力前に自動的に変更するには、拡張イメージ データストアを作成して、目的のイメージ サイズを指定し、これらのデータストアを activations の入力引数として使用します。

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

layer = 'pool10';
featuresTrain = activations(net,augimdsTrain,layer,'OutputAs','rows');
featuresTest = activations(net,augimdsTest,layer,'OutputAs','rows');

学習データおよびテスト データからクラス ラベルを抽出します。

YTrain = imdsTrain.Labels;
YTest = imdsTest.Labels;

イメージ分類器のあてはめ

学習イメージから抽出された特徴を予測子変数として使用し、fitcecoc (Statistics and Machine Learning Toolbox) を使用してマルチクラス サポート ベクター マシン (SVM) をあてはめます。

mdl = fitcecoc(featuresTrain,YTrain);

テスト イメージの分類

学習済みの SVM モデルとテスト イメージから抽出された特徴を使用して、テスト イメージを分類します。

YPred = predict(mdl,featuresTest);

4 個のサンプル テスト イメージと、その予測ラベルを表示します。

idx = [1 5 10 15];
figure
for i = 1:numel(idx)
    subplot(2,2,i)
    I = readimage(imdsTest,idx(i));
    label = YPred(idx(i));
    
    imshow(I)
    title(label)
end

テスト セットに対する分類精度を計算します。精度とは、ネットワークによって予測が正しく行われるラベルの割合です。

accuracy = mean(YPred == YTest)
accuracy = 1

この SVM は高い精度を示しています。特徴抽出を使用しても十分な精度が得られない場合、代わりに転移学習を試してください。

出力引数

すべて折りたたむ

事前学習済みの SqueezeNet 畳み込みニューラル ネットワーク。DAGNetwork オブジェクトとして返されます。

未学習の SqueezeNet 畳み込みニューラル ネットワーク アーキテクチャ。LayerGraph オブジェクトとして返されます。

参照

[1] ImageNet. http://www.image-net.org

[2] Iandola, Forrest N., Song Han, Matthew W. Moskewicz, Khalid Ashraf, William J. Dally, and Kurt Keutzer. "SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5 MB model size." Preprint, submitted November 4, 2016. https://arxiv.org/abs/1602.07360.

[3] Iandola, Forrest N. "SqueezeNet." https://github.com/forresti/SqueezeNet.

拡張機能

R2018a で導入