ドキュメンテーション

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

深層学習ネットワークのコード生成

この例では、深層学習を使用するイメージ分類用途のコード生成について説明します。codegen コマンドを使用し、AlexNet、ResNet、GoogLeNet などのよく知られたイメージ分類ネットワークで予測を実行する MEX 関数を生成します。

必要条件

  • Compute Capability 3.2 以上の CUDA® 対応 NVIDIA® GPU。

  • NVIDIA CUDA ツールキットおよびドライバー。

  • NVIDIA cuDNN ライブラリ (v7) 以上。

  • コンパイラおよびライブラリの環境変数。サポートされているコンパイラおよびライブラリのバージョンの詳細は、サードパーティ製品を参照してください。環境変数の設定は、前提条件となる製品の設定を参照してください。

  • Computer Vision Toolbox™ (この例で使用するビデオ リーダーとビューアー用)。

  • Deep Learning Toolbox™ (SeriesNetwork または DAGNetwork オブジェクトを使用するため)。

  • Image Processing Toolbox™ (イメージを読み取って表示するため)。

  • GPU Coder™ (CUDA コードを生成するため)。

  • GPU Coder Interface for Deep Learning Libraries サポート パッケージ。このサポート パッケージをインストールするには、アドオン エクスプローラーを使用します。

GPU 環境の検証

関数 coder.checkGpuInstall を使用し、この例を実行するのに必要なコンパイラおよびライブラリが正しく設定されていることを検証します。

coder.checkGpuInstall('gpu','codegen','cudnn','quiet');

関数 'alexnet_predict' について

関数 alexnet_predict.m は、イメージ入力を受け取り、alexnet.mat ファイルに保存されている深層学習ネットワークを使用して、イメージについて予測を実行します。この関数は、alexnet.mat からネットワーク オブジェクトを永続変数 mynet に読み込みます。それ以降、この関数を呼び出すと、予測のためにこの永続オブジェクトが再利用されます。

type('alexnet_predict.m')
% Copyright 2017 The MathWorks, Inc.

function out = alexnet_predict(in) 
%#codegen

% A persistent object mynet is used to load the series network object.
% At the first call to this function, the persistent object is constructed and
% setup. When the function is called subsequent times, the same object is reused 
% to call predict on inputs, thus avoiding reconstructing and reloading the
% network object.

persistent mynet;

if isempty(mynet)
    mynet = coder.loadDeepLearningNetwork('alexnet.mat','alexnet');
end

% pass in input   
out = mynet.predict(in);

事前学習済みの SeriesNetwork の取得

AlexNet ネットワークが存在しない場合、ダウンロードして alexnet.mat に保存します。

net = getAlexnet();

このネットワークには、畳み込み層、全結合層、分類出力層など、25 個の層が含まれています。

net.Layers
ans = 

  25x1 Layer array with layers:

     1   'data'     Image Input                   227x227x3 images with 'zerocenter' normalization
     2   'conv1'    Convolution                   96 11x11x3 convolutions with stride [4  4] and padding [0  0  0  0]
     3   'relu1'    ReLU                          ReLU
     4   'norm1'    Cross Channel Normalization   cross channel normalization with 5 channels per element
     5   'pool1'    Max Pooling                   3x3 max pooling with stride [2  2] and padding [0  0  0  0]
     6   'conv2'    Convolution                   256 5x5x48 convolutions with stride [1  1] and padding [2  2  2  2]
     7   'relu2'    ReLU                          ReLU
     8   'norm2'    Cross Channel Normalization   cross channel normalization with 5 channels per element
     9   'pool2'    Max Pooling                   3x3 max pooling with stride [2  2] and padding [0  0  0  0]
    10   'conv3'    Convolution                   384 3x3x256 convolutions with stride [1  1] and padding [1  1  1  1]
    11   'relu3'    ReLU                          ReLU
    12   'conv4'    Convolution                   384 3x3x192 convolutions with stride [1  1] and padding [1  1  1  1]
    13   'relu4'    ReLU                          ReLU
    14   'conv5'    Convolution                   256 3x3x192 convolutions with stride [1  1] and padding [1  1  1  1]
    15   'relu5'    ReLU                          ReLU
    16   'pool5'    Max Pooling                   3x3 max pooling with stride [2  2] and padding [0  0  0  0]
    17   'fc6'      Fully Connected               4096 fully connected layer
    18   'relu6'    ReLU                          ReLU
    19   'drop6'    Dropout                       50% dropout
    20   'fc7'      Fully Connected               4096 fully connected layer
    21   'relu7'    ReLU                          ReLU
    22   'drop7'    Dropout                       50% dropout
    23   'fc8'      Fully Connected               1000 fully connected layer
    24   'prob'     Softmax                       softmax
    25   'output'   Classification Output         crossentropyex with 'tench' and 999 other classes

関数 'alexnet_predict' の MEX コード生成の実行

設計ファイル alexnet_predict.m から CUDA コードを生成するには、MEX ターゲットの GPU コード構成オブジェクトを作成し、ターゲット言語を C++ に設定します。関数 coder.DeepLearningConfig を使用して CuDNN 深層学習構成オブジェクトを作成し、それを GPU コード構成オブジェクトの DeepLearningConfig プロパティに割り当てます。サイズが [227,227,3] の入力を指定して codegen コマンドを実行します。この値は AlexNet ネットワークの入力層サイズに対応します。

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg alexnet_predict -args {ones(227,227,3)} -report
Code generation successful: To view the report, open('codegen/mex/alexnet_predict/html/report.mldatx').

生成されたコードの説明

系列ネットワークは、25 個の層クラスから成る配列と、ネットワークを設定、予測、クリーンアップする関数を含む C++ クラスとして生成されます。

class b_alexnet
{
   ....
   public:
     b_alexnet();
     void setup();
     void predict();
     void cleanup();
     ~b_alexnet();
};

このクラスの setup() メソッドは、ハンドルを設定し、ネットワーク オブジェクトの各層にメモリを割り当てます。predict() メソッドは、ネットワーク内の 25 個の層それぞれについて予測を呼び出します。

生成されたコード ファイル alexnet_predict.cu 内のエントリポイント関数 alexnet_predict() は、b_alexnet クラス型の静的オブジェクトを構築し、このネットワーク オブジェクトに対して setup や predict を呼び出します。

static b_alexnet mynet;
static boolean_T mynet_not_empty;
/* Function Definitions */
void alexnet_predict(alexnet_predictStackData *SD, const real_T in[154587],
                  real32_T out[1000])
{
   if (!mynet_not_empty) {
     DeepLearningNetwork_setup(&mynet);
     mynet_not_empty = true;
   }
    DeepLearningNetwork_predict(SD, &mynet, in, out);
 }

ネットワーク パラメーターのバイナリ ファイル

バイナリ ファイルは、ネットワーク内の全結合層や畳み込み層などのパラメーターを持つ層に対してエクスポートされます。たとえば、ファイル cnn_alexnet_conv*_w および cnn_alexnet_conv*_b は、ネットワーク内の畳み込み層の重みとバイアス パラメーターに対応します。

dir(fullfile(pwd, 'codegen', 'mex', 'alexnet_predict'))
.                              cnn_alexnet_avg                
..                             cnn_alexnet_conv1_b            
DeepLearningNetwork.cu         cnn_alexnet_conv1_w            
DeepLearningNetwork.h          cnn_alexnet_conv2_b            
MWCNNLayerImpl.cu              cnn_alexnet_conv2_w            
MWCNNLayerImpl.hpp             cnn_alexnet_conv3_b            
MWCudaDimUtility.cu            cnn_alexnet_conv3_w            
MWCudaDimUtility.h             cnn_alexnet_conv4_b            
MWFusedConvReLULayer.cpp       cnn_alexnet_conv4_w            
MWFusedConvReLULayer.hpp       cnn_alexnet_conv5_b            
MWFusedConvReLULayerImpl.cu    cnn_alexnet_conv5_w            
MWFusedConvReLULayerImpl.hpp   cnn_alexnet_fc6_b              
MWTargetNetworkImpl.cu         cnn_alexnet_fc6_w              
MWTargetNetworkImpl.hpp        cnn_alexnet_fc7_b              
alexnet_predict.cu             cnn_alexnet_fc7_w              
alexnet_predict.h              cnn_alexnet_fc8_b              
alexnet_predict_data.cu        cnn_alexnet_fc8_w              
alexnet_predict_data.h         cnn_alexnet_labels.txt         
alexnet_predict_initialize.cu  cnn_api.cpp                    
alexnet_predict_initialize.h   cnn_api.hpp                    
alexnet_predict_mex.map        cpp_mexapi_version.cpp         
alexnet_predict_mex.mexa64     gpu_codegen_info.mat           
alexnet_predict_mex.sh         html                           
alexnet_predict_terminate.cu   interface                      
alexnet_predict_terminate.h    predict.cu                     
alexnet_predict_types.h        predict.h                      
build                          rt_nonfinite.h                 
build.ninja                    rtwtypes.h                     
buildInfo.mat                  

生成された MEX の実行

入力イメージを読み込みます。

im = imread('peppers.png');
imshow(im);

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

im = imresize(im, [227,227]);
predict_scores = alexnet_predict_mex(double(im));

上位 5 つの予測スコアを synset ディクショナリの単語にマッピングします。

fid = fopen('synsetWords.txt');
synsetOut = textscan(fid,'%s', 'delimiter', '\n');
synsetOut = synsetOut{1};
fclose(fid);

[val,indx] = sort(predict_scores, 'descend');
scores = val(1:5)*100;
labels = synsetOut(indx(1:5));

上位 5 つの分類ラベルを表示します。

imfull = zeros(227,400,3, 'uint8');
for k = 1:3
   imfull(:,174:end,k) = im(:,:,k);
end
h = imshow(imfull, 'InitialMagnification',200);
text(get(h, 'Parent'), 1, 20, 'Classification with AlexNet' , 'color', 'w','FontSize', 20);
scol = 1;
srow = 50;
for k = 1:5
   t = text(get(h, 'Parent'), scol, srow, labels{k}, 'color', 'w','FontSize', 15);
   pos = get(t, 'Extent');
   text(get(h, 'Parent'), pos(1)+pos(3)+5, srow, sprintf('%2.2f%%', scores(k)), 'color', 'w', 'FontSize', 15);
   srow = srow + 20;
end

ビデオに対する分類

用意されている例ファイル alexnet_live.m は、Web カメラからフレームを取得して予測を呼び出し、取得した各ビデオ フレームについて分類結果を表示します。メモ: この例では、MATLAB® Support Package for USB Webcams™ を通じてサポートされる関数 webcam を使用します。サポート パッケージはサポート パッケージ インストーラーからダウンロードしてインストールできます。

  camera = webcam;
  while true
     % Take a picture
     ipicture = camera.snapshot;
     % Resize and cast the picture to single
     picture = imresize(ipicture,[227,227]);
     % Call MEX function for AlexNet prediction
     tic;
     pout = alexnet_predict(single(picture));
     newt = toc;
     % fps
     fps = .9*fps + .1*(1/newt);
     % top 5 scores
     [top5labels, scores] = getTopFive(pout, synsetOut);
     % display
     dispResults(ax, imfull, picture, top5labels, scores, fps);
  end

メモリに読み込まれた静的ネットワーク オブジェクトをクリアします。

clear mex;

ResNet-50 ネットワークによる分類

よく知られた DAG ネットワーク ResNet-50 を使用してイメージを分類することもできます。MATLAB 用の事前学習済み ResNet-50 モデルは、Deep Learning Toolbox の ResNet-50 サポート パッケージに含まれています。このサポート パッケージをダウンロードしてインストールするには、アドオン エクスプローラーを使用します。アドオンの検索とインストールの詳細は、アドオンの入手 (MATLAB) を参照してください。

net = resnet50;
disp(net)
  DAGNetwork with properties:

         Layers: [177×1 nnet.cnn.layer.Layer]
    Connections: [192×2 table]

関数 'resnet_predict' の MEX コード生成の実行

設計ファイル resnet_predict.m から CUDA コードを生成します。この設計ファイルは関数 resnet50 を呼び出して、ネットワークを読み込み、入力イメージに対して predict を実行します。このファイルからコードを生成するには、前と同じように、MEX ターゲットの GPU 構成オブジェクトを作成します。

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg resnet_predict -args {ones(224,224,3)} -report
Code generation successful: To view the report, open('codegen/mex/resnet_predict/html/report.mldatx').

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

im = imresize(im, [224,224]);
predict_scores = resnet_predict_mex(double(im));
[val,indx] = sort(predict_scores, 'descend');
scores = val(1:5)*100;
labels = synsetOut(indx(1:5));

メモリに読み込まれた静的ネットワーク オブジェクトをクリアします。

clear mex;

GoogLeNet (Inception) ネットワークによる分類

MATLAB 用の事前学習済み GoogLeNet モデルは、Deep Learning Toolbox の GoogLeNet サポート パッケージに含まれています。このサポート パッケージをダウンロードしてインストールするには、アドオン エクスプローラーを使用します。アドオンの検索とインストールの詳細は、アドオンの入手 (MATLAB) を参照してください。

net = googlenet;
disp(net)
  DAGNetwork with properties:

         Layers: [144×1 nnet.cnn.layer.Layer]
    Connections: [170×2 table]

関数 'googlenet_predict' の MEX コード生成の実行

設計ファイル googlenet_predict.m から CUDA コードを生成します。この設計ファイルは関数 googlenet を呼び出して、ネットワークを読み込み、入力イメージに対して predict を実行します。このファイルからコードを生成するには、前と同じように、MEX ターゲットの GPU 構成オブジェクトを作成します。

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg googlenet_predict -args {ones(224,224,3)} -report
Code generation successful: To view the report, open('codegen/mex/googlenet_predict/html/report.mldatx').

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

im = imresize(im, [224,224]);
predict_scores = googlenet_predict_mex(double(im));
[val,indx] = sort(predict_scores, 'descend');
scores_googlenet = val(1:5)*100;
labels_googlenet = synsetOut(indx(1:5));

メモリに読み込まれた静的ネットワーク オブジェクトをクリアします。

clear mex;