イメージ分類用の学習済み残差ネットワークの量子化と CUDA コードの生成
この例では、残差結合をもち、イメージ分類用に CIFAR-10 データで学習させた深層学習ニューラル ネットワークの畳み込み層で、学習可能パラメーターを量子化する方法を示します。
ニューラル ネットワークでは、入力がネットワーク経由で伝播するときに、各層からの入力データ、パラメーター (重み)、および活性化を保存するためにメモリが使用されます。Deep Learning Toolbox™ を使用して作成と学習を行うほとんどのニューラル ネットワークは、単精度浮動小数点データ型を使用します。小規模なネットワークでさえ、これらの浮動小数点算術演算を実行するために、大量のメモリとハードウェアを必要とします。このような制限は、計算能力が低く、メモリ リソースが少ない場合にデバイスへの深層学習モデルの展開を妨げる可能性があります。重みと活性化を保存するための精度を下げることによって、ネットワークのメモリ要件を緩和させることができます。
この例では、Deep Learning Toolbox と Deep Learning Toolbox Model Quantization Library サポート パッケージを併用して、畳み込み層の重み、バイアス、および活性化を 8 ビットにスケーリングされた整数データ型に量子化することによって、深層ニューラル ネットワークのメモリ フットプリントを削減します。
この例のネットワークは、イメージ分類用に CIFAR-10 データで学習させています。
残差結合は畳み込みニューラル ネットワーク アーキテクチャでよく使用される要素です。残差ネットワークは、メイン ネットワーク層をバイパスする残差 (またはショートカット) 結合のある DAG ネットワークの一種です。残差結合では、パラメーターの勾配がネットワークの出力層からより初期の層へとよりスムーズに伝播するため、更に深いネットワークに学習させることができます。このようにネットワークが深くなると、より難しいタスクで高い精度を実現できます。ネットワーク アーキテクチャと学習の詳細については、イメージ分類用の残差ネットワークの学習を参照してください。
この例を実行するには、深層学習ネットワークを量子化して GPU 環境に展開するために必要な製品を所有していなければなりません。これらの製品の詳細については、量子化ワークフローの必要条件を参照してください。
事前学習済みのネットワークの読み込み
事前学習済みのネットワークを読み込みます。残差結合をもつイメージ分類用ネットワークの作成と学習の詳細については、「イメージ分類用の残差ネットワークの学習」の例を参照してください。
load('CIFARNet-20-16.mat','trainedNet'); net = trainedNet;
analyzeNetwork
を使用して、深層学習ネットワーク アーキテクチャを解析できます。
analyzeNetwork(net)
データの読み込み
以下のコードを実行して、CIFAR-10 データ セット [1] をダウンロードします。このデータセットには 60,000 個のイメージが格納されています。各イメージのサイズは 32 x 32 で 3 つのカラー チャネル (RGB) があります。データセットのサイズは 175 MB です。インターネット接続の速度によっては、ダウンロード プロセスに時間がかかることがあります。
datadir = tempdir; downloadCIFARData(datadir);
Downloading CIFAR-10 dataset (175 MB). This can take a while...done.
キャリブレーションと検証のためのデータの準備
CIFAR-10 学習イメージとテスト イメージを 4 次元配列として読み込みます。学習セットには 50,000 個のイメージが格納されていて、テスト セットには 10,000 個のイメージが格納されています。CIFAR-10 テスト イメージをネットワークの検証用に使用します。
[XTrain,YTrain,XValidation,YValidation] = loadCIFARData(datadir);
次のコードを使用して、ランダムにサンプリングされた学習イメージを表示できます。
figure;
idx = randperm(size(XTrain,4),20);
im = imtile(XTrain(:,:,:,idx),'ThumbnailSize',[96,96]);
imshow(im)
キャリブレーションと検証に使用する augmentedImageDatastore
オブジェクトを作成します。キャリブレーションには 200 個のランダムなイメージを使用し、検証には 50 個のランダムなイメージを使用します。
inputSize = net.Layers(1).InputSize; augimdsTrain = augmentedImageDatastore(inputSize,XTrain,YTrain); augimdsCalibration = shuffle(augimdsTrain).subset(1:200); augimdsValidation = augmentedImageDatastore(inputSize,XValidation,YValidation); augimdsValidation = shuffle(augimdsValidation).subset(1:50);
ディープ ネットワーク量子化器アプリを使用した GPU 展開のためのネットワークの量子化
この例では、GPU 実行環境を使用します。深層学習ネットワークを量子化して GPU 環境に展開するために必要な製品の詳細については、量子化ワークフローの必要条件を参照してください。
MATLAB® コマンド ウィンドウで、ディープ ネットワーク量子化器アプリを開きます。
deepNetworkQuantizer
[New]、[Quantize a network] を選択します。アプリが自動的に実行環境を確認します。
ダイアログで、実行環境と量子化するネットワークをベース ワークスペースから選択します。この例では、GPU 実行環境と DAG ネットワーク net
を選択します。
ツールストリップの [Calibrate] セクションの [Calibration Data] で、キャリブレーション データ augimdsCalibration
を含むベース ワークスペースから augmentedImageDatastore
オブジェクトを選択します。
[Calibrate] をクリックします。
ディープ ネットワーク量子化器は、キャリブレーション データを使用してネットワークを実行し、ネットワーク層の学習可能パラメーターの範囲情報を収集します。
キャリブレーションが完了すると、アプリは、畳み込みの重みとバイアスに加え、ネットワークの全結合層、およびキャリブレーション時の最小値と最大値を含むネットワークのすべての層での活性化のダイナミック レンジが格納されたテーブルを表示します。テーブルの右側では、アプリがパラメーターのダイナミック レンジのヒストグラムを表示します。ヒストグラムの灰色の領域は、量子化された表現では表せないデータを示しています。これらのヒストグラムを解釈する方法の詳細については、深層ニューラル ネットワークの量子化を参照してください。
テーブルの [Quantize Layer] 列は、層内の学習可能パラメーターを量子化するかどうかを示します。畳み込み層以外の層は、量子化できないため、選択できません。量子化されていない層は、量子化後も単精度のままです。
ツールストリップの [Validate] セクションの [Validation Data] で、検証データ augimdsValidation
を含むベース ワークスペースから augmentedImageDatastore
オブジェクトを選択します。
ツールストリップの [Validate] セクションの [Quantization Options] で、検証に使用するメトリクス関数を選択します。アプリは、量子化するネットワークのタイプに基づいて、検証に使用する既定のメトリクス関数を決定します。カスタム メトリクス関数を追加して検証に使用することもできます。この例では、カスタム メトリクス関数 hComputeAccuracy
の名前を入力します。[Add] を選択して、アプリで使用できるメトリクス関数のリストに hComputeAccuracy
を追加します。検証に使用するメトリクス関数として hComputeAccuracy
を選択します。このカスタム メトリクス関数は、予測されたラベルをグラウンド トゥルースと比較し、最上位の精度を返します。カスタム メトリクス関数はパス上になければなりません。
[Quantize and Validate] をクリックします。
アプリがネットワークを量子化し、検証結果の概要を表示します。このキャリブレーション イメージと検証イメージのセットでは、検証イメージ 50 個のセットについて、ネットワークの量子化により精度が 2% 低下し、学習可能パラメーター メモリが 73% 減少しています。
ネットワークを量子化して検証した後、ネットワークをエクスポートするか、コードを生成できます。ネットワークをエクスポートするには、[Export]、[Export Quantizer] を選択して、ベース ワークスペースに dlquantizer
オブジェクトを作成します。GPU Coder アプリを開いて、最適化されたニューラル ネットワークから GPU コードを生成するには、[Export]、[Generate Code] を選択します。GPU Coder を使用して最適化された深層畳み込みニューラル ネットワークの CUDA コードを生成する方法については、深層学習ネットワーク用の INT8 コードの生成 (GPU Coder)を参照してください。
複数のメトリクス関数を使用したネットワークのパフォーマンスの検証
関数 dlquantizer
を使用すると、複数のメトリクス関数を使用して、ネットワークのパフォーマンスを同時に評価できます。
まず、事前学習済みのネットワークとデータを読み込み、前述のとおりにキャリブレーションと検証用のデータを準備します。
dlquantizer
オブジェクトを作成します。量子化するネットワークと使用する実行環境を指定します。関数 calibrate
を使用し、augimdsCalibration
からのサンプル入力を使用してネットワークを実行し、範囲情報を収集します。
dq = dlquantizer(net,'ExecutionEnvironment','GPU'); calResults = calibrate(dq,augimdsCalibration)
dlquantizationOptions
オブジェクトのメトリクス関数を指定します。関数 validate
を使用して、ネットワークの畳み込み層内の学習可能パラメーターを量子化し、ネットワークを実行します。この関数 validate
は、量子化前後のネットワークの結果を比較するために dlquantizationOptions
オブジェクトで定義されたメトリクス関数を使用します。この例では、最上位の精度と上位 5 つの精度のメトリクスを使用してネットワークのパフォーマンスを評価します。
dqOpts = dlquantizationOptions('MetricFcn',... {@(x)hComputeAccuracy(x,net,augimdsValidation), ... @(x)hComputeTop_5(x,net,augimdsValidation)}); validationResults = validate(dq,augimdsValidation,dqOpts)
validationResults = struct with fields:
NumSamples: 50
MetricResults: [1×2 struct]
Statistics: [2×2 table]
検証出力の MetricResults.Result
フィールドを調べ、使用された各メトリクス関数によって測定された最適化ネットワークのパフォーマンスを確認します。
validationResults.MetricResults.Result validationResults.Statistics
キャリブレーション統計を可視化するには、最初に dlquantizer
オブジェクト dq.
を保存します。
save('dlquantObj.mat','dq')
次に、[New]、[Import dlquantizer
object] を選択して、ディープ ネットワーク量子化器アプリに dlquantizer
オブジェクト dq
をインポートします。
CUDA コードの生成
最適化された畳み込み深層ニューラル ネットワークの CUDA® コードを生成します。
エントリポイント関数の作成
以下のようにして、エントリポイント関数を MATLAB® で記述します。
関数
coder.loadDeepLearningNetwork
(GPU Coder)を使用して深層学習モデルを読み込み、CNN クラスを作成して設定します。詳細については、コード生成用の事前学習済みのネットワークの読み込み (GPU Coder)を参照してください。predict
を呼び出して応答を予測します。
type('mynet_predict.m');
function out = mynet_predict(netFile, im) persistent net; if isempty(net) net = coder.loadDeepLearningNetwork(netFile); end out = net.predict(im); end
永続オブジェクト mynet
は DAGNetwork
オブジェクトを読み込みます。エントリポイント関数への最初の呼び出しで、永続オブジェクトの構成と設定を行います。後続の関数の呼び出しでは、入力に対して predict
を呼び出すために同じオブジェクトを再利用し、ネットワーク オブジェクトの再構成と再読み込みを回避するようにします。
codegen
を使用したコード生成
出力ファイル名、場所、型などのビルド設定を構成するには、コーダー構成オブジェクトを作成します。このオブジェクトを作成するには、関数 coder.gpuConfig
を使用します。たとえば、codegen コマンドを使用して CUDA MEX を生成する場合、cfg = coder.gpuConfig('mex')
を使用します。
cuDNN のコード生成パラメーターを指定するには、DeepLearningConfig
プロパティを、coder.DeepLearningConfig
を使用して作成した coder.CuDNNConfig
オブジェクトに設定します。
キャリブレーション データを含む MAT ファイルの場所を指定します。
DataType
プロパティを使用することによって、サポートされている層での推論計算の精度を指定します。8 ビット整数には、'int8'
を使用します。int8 の精度では、Compute Capability 6.1、6.3、またはそれ以上の CUDA GPU が必要です。GPU コード構成オブジェクトの ComputeCapability
プロパティを使用して、適切な Compute Capability 値に設定します。
cfg = coder.gpuConfig('mex'); cfg.TargetLang = 'C++'; cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn'); cfg.DeepLearningConfig.DataType = 'int8'; cfg.DeepLearningConfig.CalibrationResultFile = 'dlquantObj.mat'; netFile = 'mynet.mat'; save(netFile,'net');
codegen
コマンドを実行します。codegen
コマンドは、エントリポイント関数 mynet_predict.m
から CUDA コードを生成します。
codegen -config cfg mynet_predict -args {coder.Constant(netFile), ones(inputSize, 'single')} -report
コード生成に成功したら、MATLAB コマンド ウィンドウで [レポートの表示] をクリックすることで、結果のコード生成レポートを表示できます。レポートがレポート ビューアー ウィンドウに表示されます。コード生成時にコード ジェネレーターによりエラーまたは警告が検出されると、レポートでは問題が説明され、問題のある MATLAB コードへのリンクが提供されます。コード生成レポート (MATLAB Coder)を参照してください。
参考文献
[1] Krizhevsky, Alex. 2009."Learning Multiple Layers of Features from Tiny Images." https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf