Main Content

量子化れ深层学习ネットワークの生成生成

深層学習では、畳み込み層などのさまざまな処理層を含むニューラル ネットワーク アーキテクチャが使用されます。深層学習モデルは通常、ラベル付きデータの大量のセットに対して動作します。これらのモデルの学習や推論の実行には多くの計算量が必要になるので、大量のメモリが消費されます。ニューラル ネットワークでは、入力がネットワーク経由で伝播するときに、各層からの入力データ、パラメーター (重み)、および活性化を保存するためにメモリが使用されます。事前学習済みのニューラル ネットワークと Deep Learning Toolbox™ を使用して学習されたニューラル ネットワークのほとんどで、単精度浮動小数点データ型が使用されます。小規模なネットワークでも、これらの浮動小数点算術演算を実行するには大量のメモリとハードウェアが必要です。このような制限は、計算能力が低く、メモリ リソースが少ない場合にデバイスへの深層学習モデルの展開を妨げる可能性があります。重みと活性化を保存するための精度を下げることによって、ネットワークのメモリ要件を緩和させることができます。

深度学习工具箱と深度学习工具箱模型量化库サポートサポートをし,层层,,バイアス,,およびおよび化をををビットビットビットにされた整数整数データ化にに化化するするするするするするするすることによってによってメモリGPU Coder™ををを使用ししてて,,量子量子化化されれたたたネットワークネットワークにに最适®コードをでき。生成されたコードは,®CUDA Deep Neural Network library (cuDNN) または TensorRT™ の高性能な推論ライブラリを利用します。また、生成されたコードは、ソース コード、スタティック ライブラリ、またはダイナミック ライブラリ、あるいは、さまざまな NVIDIA GPU プラットフォームに展開できる実行可能ファイルとしてプロジェクトに統合できます。

量子化ネットワークを使用した GPU での画像分類

この例では、GPU Coder を使用して量子化された深層畳み込みニューラル ネットワークの CUDA コードを生成し、イメージを分類します。この例では、事前学習済みのsqueezenet(深度学习工具箱)畳み込みニューラル ネットワークを使用して、量子化されたネットワークの転送学習、量子化、および CUDA コード生成を行う方法を示します。

Squeezenetは100万枚超えるイメージで学习ておりをををををををををを个个のカテゴリカテゴリカテゴリカテゴリカテゴリカテゴリカテゴリカテゴリ(特徴表现ています。ネットワークはイメージを取り,イメージイメージ内内ののオブジェクトのラベルをを各オブジェクトオブジェクトオブジェクトカテゴリカテゴリのの

サードパーティの必要条件

必須

  • CUDA 対応 NVIDIA® GPU および互換性のあるドライバー。

オプション

スタティック ライブラリ、ダイナミック ライブラリ、または実行可能ファイルなどの MEX 以外のビルドについて、この例では以下の要件も適用されます。

Squeezenetを使用し学习学习

新しいのに対してを実行するには,転移学习学习ののののののののののののの畳み込み畳み込み畳み込み畳み込み畳み込み畳み込みネットワークを微调整微调整ししますます。。転移学习学习でははは,开始としてでき。通常,転移学习によってネットワークを方方がが,,ランダムランダムランダムにに初期化さされれたた重み重みででゼロゼロからからネットワークネットワークにににに学习さよりもももも学习イメージし,新しいタスク学习済み特徴高速に転移転移ます。

学習データの読み込み

新しいイメージを解凍してイメージ データストアとして読み込みます。関数imageDatastoreは,にてイメージに自动ラベルを付け,このをImageDatastoreとして格纳。イメージデータストア使用使用と,メモリメモリないデータデータなどなどののの大きな大きなイメージをを格纳格纳しし,,畳み込みニューラルニューラルネットワークのの学习中にイメージイメージバッチ70%をををのの。分割にを学习学习しししししししししししし30%ををにににsplitEachLabelは、imdsデータストアを 2 つの新しいデータストアに分割します。

解压缩('MerchData.zip');imds = imageDatastore('MerchData',...“包括橡皮folders”,真的,...“ Labelsource”,“折叠式”);[imdsTrain,imdsValidation] = splitEachLabel(imds,0.7,“随机”);numTrainImages = numel(imdsTrain.Labels); idx = randperm(numTrainImages,4); img = imtile(imds,'Frames', idx); figure imshow(img) title('Random Images from Training Dataset');

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

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

网= squeezenet;

オブジェクトにはdagnetworkオブジェクトが格納されています。最初の層であるイメージ入力層には、サイズが 227 x 227 x 3 の入力イメージが必要です。ここで、3 はカラー チャネルの数です。関数analyzeNetwork(深度学习工具箱)を使用てネットワークアーキテクチャ的に可视てて表示し,,ネットワークネットワーク关するエラーや问题问题を検出してて,ネットワークネットワークに详细详细情报情报情报情报情报情报ををを,层と学习可能パラメーターパラメーター学习ななパラメーターの総数,および再再帰层の状态状态パラメーターのののサイズサイズ

inputSize = net.Layers(1).InputSize;

最後の層の置き換え

の畳み込み,入力イメージを分类ために最后最后最后可能ななとと最终最终最终最终分类分类分类分类分类分类分类层层层层层がが使用使用するするするするイメージイメージイメージイメージイメージののの特徴特徴をを'conv10'および'ClassificationLayer_predictions'は、ネットワークによって抽出された特徴を組み合わせてクラス確率、損失値、および予測ラベルにまとめる方法に関する情報を含んでいます。

新しいイメージを分類するために事前学習済みのネットワークを再学習させるには、これら 2 つの層を新しいデータセットに適応させた新しい層に置き換えます。これは手動で行うことも、補助関数Findlayerstoreplaceを使用してこれらの層を自動的に見つけることもできます。

lgraph = layerGraph(net); [learnableLayer,classLayer] = findLayersToReplace(lgraph); numClasses = numel(categories(imdsTrain.Labels)); newConvLayer = convolution2dLayer([1, 1],numClasses,'WeightLearnRateFactor',...10,'biaslearnrateFactor',10,"Name",'new_conv');lgraph = replaceLayer(lgraph,'conv10',newConvLayer); newClassificatonLayer = classificationLayer(' Name','new_classoutput');lgraph = replaceLayer(lgraph,'ClassificationLayer_predictions',new Classificatonlayer);

ネットワークの学習

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

PixelRange = [-30 30];ImageAugmenter = Imagedataaugmenter(...'RandXReflection',真的,...'RandXTranslation',PixelRange,...'RandYTranslation',pixelRange); augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain,...'DataAugmentation',imageAugmenter);

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

augimdsValidation = augmentedImagedatastore(inputsize(1:2),imdsvalidation);

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

选项=训练('sgdm',...“ MINIBATCHSIZE”,11,...“ maxepochs”7...'InitialLearnRate',2e-4,...'Shuffle',“每个段”,...'验证data',augimdsValidation,...“验证频率”,3,...'Verbose',错误的,...“阴谋”,“训练过程”);

転移層と新しい層とで構成されるネットワークに学習させます。

NetTransfer = Trainnetwork(AugimdsTrain,Lgraph,选项);

classNames = netTransfer.Layers(end).Classes; save('mySqueezenet.mat','netTransfer');

ネットワークの量子化

dlquantizerオブジェクトを,量子するネットワークをし。。。

QUANTOBJ = dlQuantizer(NetTransfer);

量子ののの动作比较するに使用れるメトリクス关数を定义定义。。。

类型('hcomputemodelaccuracy.m');
函数精度= hComputeModelAccuracy(预测法onScores, net, dataStore) %% Computes model-level accuracy statistics % Load ground truth tmp = readall(dataStore); groundTruth = tmp.response; % Compare with predicted label with actual ground truth predictionError = {}; for idx=1:numel(groundTruth) [~, idy] = max(predictionScores(idx,:)); yActual = net.Layers(end).Classes(idy); predictionError{end+1} = (yActual == groundTruth(idx)); %#ok end % Sum all prediction errors. predictionError = [predictionError{:}]; accuracy = sum(predictionError)/numel(predictionError); end

dlquantizationOptionsオブジェクトのメトリクス関数を指定します。

量子='MetricFcn',...{@(x)hComputeModelAccuracy(x,netTransfer,augimdsValidation)});

関数校准を使用して、サンプル入力でネットワークを実行し、範囲情報を収集します。関数校准は、ネットワークを実行し、ネットワークの畳み込み層と全結合層の重みとバイアスのダイナミック レンジ、およびネットワークのすべての層内の活性化のダイナミック レンジを収集します。この関数はテーブルを返します。テーブルの各行に、最適化されたネットワークの学習可能パラメーターの範囲情報が含まれています。

calResults = calibrate(quantObj,augimdsTrain); save('squeezenetCalResults.mat','calResults');save('squeezenetquantobj.mat','quantObj');

関数证实を使用して、ネットワークの畳み込み層内の学習可能パラメーターを量子化し、ネットワークを実行することができます。この関数は、量子化の前後のネットワークの結果を比較するためにdlquantizationOptionsオブジェクトで定義されたメトリクス関数を使用します。

valresults = validate(QuantObj,AugimdSvalidation,Quantopts);

エントリポイント関数の作成

MATLAB で次を行うエントリポイント関数を記述します。

类型('precadive_int8.m');
功能out = predict_int8(netFile, in) persistent mynet; if isempty(mynet) mynet = coder.loadDeepLearningNetwork(netFile); end out = predict(mynet,in); end

永続オブジェクトmynetdagnetworkオブジェクトを。ポイント关数への呼び出しで永続オブジェクトオブジェクトが作成作成さされれててささますますます。。。后続后続后続预测に同じオブジェクトが再利用され、ネットワーク オブジェクトの再構成と再読み込みが回避されます。

メモ

キャリブレーション ステップと検証ステップで実行されたすべての前処理演算が設計ファイルに必ず含まれるようにしてください。

代码根を使用したコード生成

出力ファイル名、場所、タイプなどのビルド設定を構成するには、コーダー構成オブジェクトを作成します。このオブジェクトを作成するには、関数coder.gpuconfigを使用ます。たとえば,代码根コマンドを使用して CUDA MEX を生成する場合、cfg = coder.gpuconfig('mex');を使用します。

cuDNN のコード生成パラメーターを指定するには、DeepLearningConfigプロパティを,coder.DeepLearningConfigを使用して作成したcoder.CuDNNConfigオブジェクトに设定ます。

cfg = coder.gpuConfig('mex');cfg.targetlang ='C ++';cfg.GpuConfig.ComputeCapability ='6.1';cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');cfg.deeplearningconfig.autuning = true;cfg.deeplearningconfig.calibrationResultFile ='squeezenetquantobj.mat';cfg.DeepLearningConfig.DataType ='int8';

キャリブレーション含む含む含むファイル场所を指定し。。。

DataTypeプロパティを使用することによって、サポートされている層での推論計算の精度を指定します。8 ビット整数には、'int8'を使用ます。コードのの计算能力プロパティを使用して、適切な Compute Capability 値に設定します。

代码根コマンドを実行ます。代码根コマンドは、MATLAB エントリポイント関数predive_int8.mから CUDA コードを生成します。

输入= {coder.constant('mySqueezenet.mat'),ones(inputSize,'uint8')}; codegen-configcfg-argsinputspredive_int8
代码生成成功。

コード生成に成功したら、MATLAB コマンド ウィンドウで[レポートの表示]をクリックすることで、結果のコード生成レポートを表示できます。レポートがレポート ビューアー ウィンドウに表示されます。コード生成時にコード ジェネレーターによりエラーまたは警告が検出されると、レポートでは問題が説明され、問題のある MATLAB コードへのリンクが提供されます。

生成された MEX の実行

分類するイメージのサイズは、ネットワークの入力サイズと同じでなければなりません。分類するイメージを読み取り、そのサイズをネットワークの入力サイズに変更します。このサイズ変更では、イメージの縦横比が多少変化します。

testImage = imread(“ merchdatatest.jpg”);testImage = imresize(testImage,inputSize(1:2));

入力イメージに対して SqueezeNet の predict を呼び出します。

predivectscores(::,1)= preditive(netTransfer,sistimage)';predivectscores(::,2)= predition_int8_mex('mySqueezenet.mat',证词);

予测ラベルそれら対応确率をヒストグラム表示します。

h = figure; h.Position(3) = 2*h.Position(3); ax1 = subplot(1,2,1); ax2 = subplot(1,2,2); image(ax1,testImage); barh(ax2,predictScores) xlabel(ax2,'Probability')yticklabels(ax2,classNames)ax2.xlim = [0 1.1];ax2.yaxislocation ='剩下';传奇('Matlab Single','Cudnn 8位整数');sgtitle('Predictions using Squeezenet')

補助関数

功能[learnableLayer,classLayer] = findLayersToReplace(lgraph)%FindlayerStore(Lgraph)找到单个分类层和%在该层的可学习(完全连接或卷积)层% graph lgraph.if〜Isa(lgraph,'nnet.cnn.LayerGraph') error(“参数必须是一个layergraph对象。”)end% Get source, destination, and layer names.src = string(lgraph.Connections.Source); dst = string(lgraph.Connections.Destination); layerNames = string({lgraph.Layers.Name}');%找到分类层。图层图必须有一个%分类层。isClassificationLayer = arrayfun(@(l)...(isa(l,'nnet.cnn.layer.ClassificationOutputLayer')...| isa(l,'nnet.layer.ClassificationLayer')),...lgraph.Layers);ifsum(isClassificationLayer)〜= 1错误('Layer graph must have a single classification layer.')endclassLayer = lgraph.Layers(isClassificationLayer);% Traverse the layer graph in reverse starting from the classification% layer. If the network branches, throw an error.CurrentLayerIdx = find(isClassificationLayer);尽管真的ifnumel(currentLayerIdx) ~= 1 msg = ['Layer graph must have a single learnable layer '...“在分类层之前。”]; error(msg)endcurrentLayerType = class(lgraph.Layers(currentLayerIdx)); isLearnableLayer = ismember(currentLayerType,...['nnet.cnn.layer.FullyConnectedLayer','nnet.cnn.layer.Convolution2DLayer');ifisLearnableLayer learnableLayer = lgraph.Layers(currentLayerIdx);returnendcurrentDstIdx = find(layerNames(currentLayerIdx) == dst); currentLayerIdx = find(src(currentDstIdx) == layerNames);endend

制限

  • cuDNN version 8.1.0 を使用してint8の精度で推論を実行する場合、NVIDIA ライブラリの問題により、パフォーマンスが大幅に低下する可能性があります。

  • NVIDIA CUDA Deep Neural Network library (cuDNN) ライブラリを対象にする場合は、8 ビット整数の量子化で以下の層がサポートされません。

    • leakyReluLayer

    • 剪辑器

    • globalaveragePooling2Dlayer

参考

アプリ

関数

オブジェクト

関連するトピック