Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

squeezenet

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

  • SqueezeNet network architecture

説明

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 データセットを解凍します。これは、75 個の MathWorks の商品イメージから成る小さなデータセットであり、5 つの異なるクラス ("cap"、"cube"、"playing cards"、"screwdriver"、"torch") に属します。

unzip("MerchData.zip");

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

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

deepNetworkDesigner(squeezenet);

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

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

データのインポート

ディープ ネットワーク デザイナーにデータを読み込むには、[データ] タブで、[データのインポート][イメージ分類データのインポート] をクリックします。

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

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

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

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

データの可視化

ディープ ネットワーク デザイナーを使用すると、[データ] タブにある学習データと検証データの分布を視覚的に検査できます。学習前の簡単なチェックとして、ランダムな観測値とそのラベルを表示することもできます。この例では、データセットにクラスが 5 つあることが確認できます。

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

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

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

R2023b より前: 層のプロパティを編集するには、層のロックを解除するのではなく、層を置き換えなければなりません。新しい 2 次元畳み込み層で、FilterSize を [1 1] に設定します。

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

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

次に、出力層を構成します。最終分類層 ClassificationLayer_predictions を選択し、[層のロックを解除] をクリックしてから、[ロックの強制解除] をクリックします。ロックが解除された出力層に対して OutputSize を設定する必要はありません。学習時に、ディープ ネットワーク デザイナーによって層の出力クラスがデータから自動的に設定されます。

ネットワークの確認

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

ネットワークの学習

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

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

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

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

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

この例では、[InitialLearnRate]0.0001[MaxEpochs]8[ValidationFrequency]5 に設定します。観測値が 55 個あるため、MiniBatchSize11 に設定します。

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

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

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

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

使用するネットワークと学習オプションを再作成する 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)

Figure contains an axes object. The axes object contains an object of type image.

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

事前学習済みの 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'                            2-D 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™ とサポートされている GPU デバイスが必要です。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。そうでない場合、trainNetwork は CPU を使用します。trainingOptions の名前と値のペアの引数 'ExecutionEnvironment' を使用して、実行環境を指定することもできます。

netTransfer = trainNetwork(augimdsTrain,lgraph,options);

Figure Training Progress (29-Aug-2023 21:19:44) contains 2 axes objects and another object of type uigridlayout. Axes object 1 with xlabel Iteration, ylabel Loss contains 14 objects of type patch, text, line. Axes object 2 with xlabel Iteration, ylabel Accuracy (%) contains 14 objects of type patch, text, line.

検証イメージの分類

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

[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

Figure contains 4 axes objects. Axes object 1 with title MathWorks Playing Cards contains an object of type image. Axes object 2 with title MathWorks Playing Cards contains an object of type image. Axes object 3 with title MathWorks Cube contains an object of type image. Axes object 4 with title MathWorks Cube contains an object of type image.

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

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

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

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

まず、事前学習済みの SqueezeNet モデルを読み込みます。

net = squeezenet;

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

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

Figure contains an axes object. The axes object contains an object of type image.

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

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

   227   227     3

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

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

Figure contains an axes object. The axes object contains an object of type image.

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

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

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

figure
imshow(I)
title(label)

Figure contains an axes object. The axes object with title bell pepper contains an object of type image.

この例では、事前学習済みの畳み込みニューラル ネットワークから学習済みのイメージの特徴を抽出し、これらの特徴を使用してイメージ分類器に学習させる方法を説明します。

特徴抽出は、事前学習済みの深いネットワークの表現能力を活用できる最も簡単で時間のかからない方法です。たとえば、抽出した特徴に対して 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)

2022-01-07_16-31-30.png

最初の層であるイメージ入力層には、サイズが 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");

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

TTrain = imdsTrain.Labels;
TTest = imdsTest.Labels;

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

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

mdl = fitcecoc(featuresTrain,TTrain);

テスト イメージの分類

学習済みの 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 == TTest)
accuracy = 0.9500

この 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 で導入