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

ARM Compute Library を使用した、深層学習ネットワークのためのコード生成

MATLAB® Coder™ を使用して、NEON 拡張子をサポートする ARM® プロセッサを使用する組み込みプラットフォームをターゲットとする、既に学習済みの畳み込みニューラル ネットワーク (CNN) からの予測のためのコードを生成できます。コード ジェネレーターは、コンピューター ビジョンおよび機械学習に ARM Compute Library を利用します。生成されたコードは、入力 SeriesNetwork または DAGNetwork ネットワーク オブジェクトで指定されるアーキテクチャ、レイヤーおよびパラメーターをもつ CNN を実装します。

次のいずれかの方法を使用してコードを生成します。

codegen または MATLAB Coder アプリを使用してニューラル ネットワークのコードを生成する場合、生成されたコードでは配列データに列優先のレイアウトが使用されます。深層学習ライブラリが使用する行優先のレイアウトを一致させるには、コード ジェネレーターは、列優先のレイアウトを行優先のレイアウトに変換する操作を挿入しなければなりません。これらの変換操作により、生成されたコードのパフォーマンスが低下する可能性があります。深層学習ニューラル ネットワークのコード生成では、RowMajor 構成パラメーターなどの MATLAB Coder の行優先オプションはサポートされていません。

必要条件

  • MATLAB Coder Interface for Deep Learning Libraries。サポート パッケージをインストールするには、これを MATLAB の [アドオン] メニューから選択します。

  • コンピューター ビジョンと機械学習用の ARM Compute Library をターゲット ハードウェアにインストールしなければなりません。

  • Deep Learning Toolbox™。

  • コンパイラおよびライブラリの環境変数。

サポートされているライブラリのバージョンと、環境変数の設定に関する詳細については、MATLAB Coder を使用した深層学習の前提条件を参照してください。

codegen を使用したコード生成

codegen を使用して ARM ターゲットで深層学習のコードを生成するには、次を行います。

  • 事前学習済みの CNN を読み込んで、predict を呼び出すエントリポイント関数を作成します。以下に例を示します。

    function out = squeezenet_predict(in)
    %#codegen
    
    persistent net;
    opencv_linkflags = '`pkg-config --cflags --libs opencv`';
    coder.updateBuildInfo('addLinkFlags',opencv_linkflags);
    if isempty(net)
        net = coder.loadDeepLearningNetwork('squeezenet', 'squeezenet');
    end
    
    out = net.predict(in);
    end
    

  • ターゲット ハードウェアが Raspberry Pi™ である場合、MATLAB Support Package for Raspberry Pi Hardware を活用することができます。サポート パッケージを使用すると、codegen は生成コードを Raspberry Pi に移動させて、Raspberry Pi で実行可能プログラムをビルドします。ハードウェア サポート パッケージをもっていないターゲット用にコードを生成する場合、コマンドを実行して、生成されたファイルを移動させ、実行可能プログラムを作成しなければなりません。

  • ARM ターゲットでは、MEX 生成による深層学習用のコード生成はサポートされていません。

  • ARM については、複数のイメージまたは観測値 (N > 1) をもつ predict への入力について、1 より大きい MiniBatchSize はサポートされません。1 の MiniBatchSize を指定します。

Raspberry Pi での深層学習用のコード生成

MATLAB Support Package for Raspberry Pi Hardware がある場合、Raspberry Pi で深層学習用のコードを生成するには、次を行います。

  1. Raspberry Pi に接続するには、raspi を使用します。以下に例を示します。

    r = raspi('raspiname','username','password');
    

  2. coder.config を使用して、ライブラリまたは実行可能ファイル用のコード生成構成オブジェクトを作成します。TargetLang プロパティを 'C++' に設定します。

    cfg = coder.config('exe');
    cfg.TargetLang = 'C++';
    

  3. coder.DeepLearningConfig を使用して、深層学習構成オブジェクトを作成します。ArmComputeVersion および ArmArchitecture プロパティを設定します。コード生成構成オブジェクトの DeepLearningConfig プロパティを coder.ARMNEONConfig オブジェクトに設定します。以下に例を示します。

    dlcfg = coder.DeepLearningConfig('arm-compute');
    dlcfg.ArmArchitecture = 'armv7';
    dlcfg.ArmComputeVersion = '19.02';
    cfg.DeepLearningConfig = dlcfg;
    

  4. Raspberry Pi のコード生成ハードウェア設定を構成するには、coder.hardware を使用して coder.Hardware オブジェクトを作成します。コード生成構成オブジェクトの Hardware プロパティを coder.Hardware オブジェクトに設定します。

    hw = coder.hardware('Raspberry Pi');
    cfg.Hardware = hw;
    

  5. 実行可能プログラムを生成している場合は、C++ メイン プログラムを指定します。以下に例を示します。

    cfg.CustomSource = 'main.cpp';

  6. コードを生成するには、codegen を使用します。-config オプションを使用して、コード生成構成オブジェクトを指定します。以下に例を示します。

    codegen -config cfg squeezenet_raspi_predict -args {ones(227, 227, 3,'single')} -report

例については、Raspberry Pi での深層学習用のコード生成を参照してください。

ハードウェア サポート パッケージがない場合のコード生成

ターゲット用のハードウェア サポート パッケージがない場合に深層学習用のコードを生成するには、次を行います。

  1. Linux® ホストでのみコードを生成します。

  2. ライブラリ用の構成オブジェクトを作成します。以下に例を示します。

    cfg = coder.config('lib');

    実行可能プログラムに対して構成オブジェクトを使用しないでください。

  3. C++ コードおよびソース コードのみを生成するように、コード生成を設定します。

    cfg.GenCodeOnly = true;
    cfg.TargetLang = 'C++';

  4. ARM Compute Library を使用したコード生成を指定するには、coder.DeepLearningConfig を使用して coder.ARMNEONConfig オブジェクトを作成します。ArmComputeVersion および ArmArchitecture プロパティを設定します。コード生成構成オブジェクトの DeepLearningConfig プロパティを coder.ARMNEONConfig オブジェクトに設定します。

    dlcfg = coder.DeepLearningConfig('arm-compute');
    dlcfg.ArmArchitecture = 'armv7';
    dlcfg.ArmComputeVersion = '19.02';
    cfg.DeepLearningConfig = dlcfg;
    

  5. ターゲット ハードウェアに固有のコード生成パラメーターを設定するには、HardwareImplementation オブジェクトの ProdHWDeviceType プロパティを設定します。

    • ARMv7 アーキテクチャの場合、'ARM Compatible->ARM Cortex' を使用します。

    • ARMv8 アーキテクチャの場合、'ARM Compatible->ARM 64-bit (LP64)' を使用します。

    以下に例を示します。

    cfg.HardwareImplementation.ProdHWDeviceType = 'ARM Compatible->ARM 64-bit (LP64)';

  6. コードを生成するには、codegen を使用します。-config オプションを使用して、コード生成構成オブジェクトを指定します。以下に例を示します。

    codegen -config cfg squeezenet_predict -args {ones(227, 227, 3, 'single')} -d arm_compute

例については、ARM ターゲットでの深層学習用のコード生成を参照してください。

生成コード

系列ネットワークは、層のクラスの配列を含む C++ クラスとして生成されます。

class b_squeezenet_0
{
 public:
  int32_T batchSize;
  int32_T numLayers;
  real32_T *inputData;
  real32_T *outputData;
  MWCNNLayer *layers[68];
 private:
  MWTargetNetworkImpl *targetImpl;
 public:
  b_squeezenet_0();
  void presetup();
  void postsetup();
  void setup();
  void predict();
  void cleanup();
  real32_T *getLayerOutput(int32_T layerIndex, int32_T portIndex);
  ~b_squeezenet_0();
};

このクラスの setup() メソッドは、ハンドルを設定し、ネットワーク オブジェクトの各層にメモリを割り当てます。predict() メソッドは、ネットワークの各層の予測を呼び出します。エントリポイント関数 squeezenet_predict のコードを生成するとします。生成された "ユーザー用" のファイル squeezenet_predict.cpp では、エントリポイント関数 squeeznet_predict() によって b_squeezenet_0 クラス タイプのスタティック オブジェクトが作成され、ネットワーク オブジェクトに対して setup および predict が呼び出されます。

static b_squeezenet_0 net;
static boolean_T net_not_empty;

// Function Definitions
//
// A persistent object net is used to load the DAGNetwork object.
//  At the first call to this function, the persistent object is constructed and
//  set up. When the function is called subsequent times, the same object is reused
//  to call predict on inputs, avoiding reconstructing and reloading the
//  network object.
// Arguments    : const real32_T in[154587]
//                real32_T out[1000]
// Return Type  : void
//
void squeezenet_predict(const real32_T in[154587], real32_T out[1000])
{
  //  Copyright 2018 The MathWorks, Inc.
  if (!net_not_empty) {
    DeepLearningNetwork_setup(&net);
    net_not_empty = true;
  }

  DeepLearningNetwork_predict(&net, in, out);
}

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

cnn_squeezenet_conv10_b            
cnn_squeezenet_conv10_w            
cnn_squeezenet_conv1_b             
cnn_squeezenet_conv1_w             
cnn_squeezenet_fire2-expand1x1_b   
cnn_squeezenet_fire2-expand1x1_w   
cnn_squeezenet_fire2-expand3x3_b   
cnn_squeezenet_fire2-expand3x3_w   
cnn_squeezenet_fire2-squeeze1x1_b  
cnn_squeezenet_fire2-squeeze1x1_w 
...

MATLAB Coder アプリを使用したコード生成

  1. [ソース ファイルの選択] ステップと [入力の型を定義] ステップを完了します。

  2. [コード生成] ステップに進みます (ARM Compute Library を使用したコード生成では MEX 生成はサポートされていないため、[実行時の問題の確認] ステップはスキップします)。

  3. [言語][C++] に設定します。

  4. ターゲット ARM ハードウェアを指定します。

    ターゲット ハードウェアが Raspberry Pi で、MATLAB Support Package for Raspberry Pi Hardware をインストールしている場合は、次を行います。

    • [ハードウェア ボード] に対して [Raspberry Pi] を選択します。

    • Raspberry Pi 設定にアクセスするには、[詳細設定] をクリックします。次に、[ハードウェア] をクリックします。[Device Address][ユーザー名][パスワード]、および [ビルド ディレクトリ] を指定します。

    ARM ターゲットのサポート パッケージがない場合は、次を行います。

    • [ビルド タイプ][スタティック ライブラリ] または [ダイナミック ライブラリ] であることを確認し、[コード生成のみ] チェック ボックスをオンにします。

    • [ハードウェア ボード] では [なし - 以下のデバイスを選択] を選択します。

    • [デバイス ベンダー] では [ARM Compatible] を選択します。

    • [デバイス タイプ] に対しては、次のとおりです。

      • ARMv7 アーキテクチャの場合、[ARM Cortex] を選択します。

      • ARMv8 アーキテクチャの場合、[ARM 64-bit (LP64)] を選択します。

    メモ

    ARM ターゲットで深層学習用のコードを生成して、ハードウェア サポート パッケージを使用しない場合は、コードを Linux ホスト上でのみ生成します。

  5. [深層学習] ペインで、[ターゲット ライブラリ][ARM Compute] に設定します。[ARM Compute Library のバージョン] および [ARM Compute アーキテクチャ] を指定します。

  6. コードを生成します。

cnncodegen を使用したコード生成

  • MATLAB に事前学習済みのネットワークを読み込みます。以下に例を示します。

    net = alexnet;
    

  • 'targetlib''arm-compute' と指定した関数 cnncodegen を使用して、CNN のコードを生成します。

    targetparams 引数を使用して、ARM Compute Library のバージョンと ARM アーキテクチャを指定します。

    以下に例を示します。

    cnncodegen(net,'targetlib','arm-compute','targetparams',struct('ArmComputeVersion','19.02','ArmArchitecture','armv8'));

    v19.02 よりも新しいバージョンの ARM Compute Library を指定した場合、コード ジェネレーターは v19.02 用のコードを生成します。ARM ターゲットでは、より新しいバージョンのライブラリを使用して生成コードをビルドできます。

  • predict を呼び出す C++ main 関数を記述します。

  • ファイルを ARM ハードウェアに移動させて、実行可能プログラムを作成します。

例については、ARM Compute Library を使用した、深層学習ネットワークのためのコード生成を参照してください。

生成コード

cnncodegen コマンドは、C++ コードおよび makefile cnnbuild_rtw.mk を生成します。生成されたファイルは codegen フォルダーにあります。MATLAB ホストで生成されたコードをコンパイルしないでください。コンパイルのために、生成されたコードを ARM ターゲット プラットフォームに移動します。

系列ネットワークは、層のクラスの配列を含む C++ クラスとして生成されます。

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

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

void CnnMain::predict()
{
    int32_T idx;
    for (idx = 0; idx < 25; idx++) {
        this->layers[idx]->predict();
    }
}

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

cnn_CnnMain_avg         cnn_CnnMain_conv5_w     
cnn_CnnMain_conv1_b     cnn_CnnMain_fc6_b       
cnn_CnnMain_conv1_w     cnn_CnnMain_fc6_w       
cnn_CnnMain_conv2_b     cnn_CnnMain_fc7_b       
cnn_CnnMain_conv2_w     cnn_CnnMain_fc7_w       
cnn_CnnMain_conv3_b     cnn_CnnMain_fc8_b       
cnn_CnnMain_conv3_w     cnn_CnnMain_fc8_w       
cnn_CnnMain_conv4_b     cnn_CnnMain_labels.txt  
cnn_CnnMain_conv4_w     
cnn_CnnMain_conv5_b      

参考

| | |

関連するトピック