ESP32は深い学習の夢を見るか?[1](ESP32で軽量DeepLearning)


目的

 現在の生活では家電品の操作にはリモコンが必要であり、我が家でもそこら中に氾濫している。
 近未来では、見つめるだけでエアコンの電源が入る、テレビのチャンネルが変えられるようになる(かも知れない)。
 これを取り合えず実現するには次のような技術が必要だ。
   ■操作対象の認識 → ■動作の選択 → ■対象へのアクション
   (カメラ+画像認識)  (加速度センサー)  (赤外線信号)
 うむ、現状技術でも到達可能な気がする。でも体に付けたいから小さくないとね。
 ◆◆◆ そうだ、ESP32へDeepLearningを実装したら実現出来るかも。 ◆◆◆
 まずは手始めに「アヤメの分類」からでも手を付けてみるか。(今回は画像処理まで行きついていません)

経緯

 (1)ESP32のカメラ接続に技術的な問題が無いので、画像認識方法を考えたい。
 (2)ど定番のTensorFlowを乗せるのは、ESP32ではメモリ容量的に無理なのは明らか。
 (3)Cで書かれたライブラリを見つけたが、コンパイル結果は16MB程度になったのでちょっと無理と判断。
 (4)neural_network_consoleのマイコンへの応用事例が見つかった。小容量でも使えるみたい。
 (5)CQ出版 Interface 2019年 1月号及びQiita等の事例では、インプリメント部分の説明不十分(私的には)。
 (6)ESP32の事例も有ったが、前提とする条件が複雑であり、うまく追試をやれる自信なし。
 (7)仕方が無いので、事例から情報を読み取り、いろいろ試してみたら、「アヤメ」は案外うまくいった。

neural_network_consoleとは

 天下のSONYが無償で公開している(よ、太っ腹)、GUIで操作できる機械学習用ソフト。
 今までは、Pythonを入れ手間をかけて環境を整えてやる必要があり、設定同士がぶつかり動作しないことも。
 おっとびっくり、これを入れればあっという間に動くものが出来上がり。
  Neural Network Console - Sony
 ※処理速度が遅いという噂も有るが、構築のお手軽さを評価すべきで、本質的な部分により力を注げる。
 ※GPUを搭載しているほうが幸せになれる。
 おまけなのか、evaluation(評価)用のCのソースプロクラムを吐き出してくれる。
 (マイコン化への貴重なインターフェースだが、説明が少なくSONYとしては力を入れてないのかな)

前提条件

 以下のソフトを予め導入の事。
 (1)neural_network_console (当たり前、for Windows 8.1/10_64bit 1.4.0にて検証)
 (2)ESP-IDF         (ESP32の開発環境)
 (3)VisualStudio(2017)   (パソコン上で動作確認したい場合に必要、無くても可)

neural_network_consoleでの操作(アヤメの分類)

 (1)下記を実施し、正しくEVALUATIONが行えることを確認する。
  SonnyのNNC(Neural Network Console)でのアヤメの分類の実装
 (2)EVALUATION画面で、ACTION → Export → NNB と選択していく。
 (3)c_source(マイコン用プログラム)が存在する画面が表示されるので、必要なフォルダにコピーする。
 ※c_source内のプログラムの機能について(推測)
  MainRuntime_example.c   mainプログラム、入力、評価、出力を実施。
  MainRuntime_inference.c  GUIで設定した構成を反映、下位モジュールでDeepLearning処理を行う。
  MainRuntime_parameters.c 学習結果を配列として保持。

neural_network_consoleでのデータ入出力について

 c_sourceのMainRuntime_example.cは独自形式の画像入力にのみ対応している。
 特定の例題(10_deep_mlp)以外では、別途プログラムによる対応が必要となる。
 この部分はかなり曖昧に書かれており、詳細は不明。(説明書が何処かにあるのかも知れないが)
 下記のような考えを想定してプログラムしたらうまく動作した。
 (1)入出力は単精度実数(float)
 ※neural_network_consoleではcsvで入力しているが、MainRuntime_example.cではfloatに変換して与える必要有り。
 (2)入力する値はinput_bufferがポインタする位置に数値を必要数書込む。
  float *idbf = nnablart_mainruntime_input_buffer(context, 0); // Input.Data.Buffer
  sscanf(buf, "%f,%f,%f,%f,%f", &idbf[0], &idbf[1], &idbf[2], &idbf[3], &label);
  ※neural_network_consoleのEVALUATION画面での、x_0,X_1,X_2,X_3に対応するデータを与える。
 (3)出力された値はoutput_bufferがポインタする位置に書き込まれている。
  float *odbf = nnablart_mainruntime_output_buffer(context, 0); // Output>data.buffer
  for (int j = 0; j < 3; j++) printf(" %+.3f", odbf[j]);
  ※neural_network_consoleのEVALUATION画面での、y_0,y_1,y_2に対応するデータを読みだす。
   EDITで、出力に必要とするy_0,y_1,y_2等がEVALUATION画面に表示されるように構成する必要有り。

ESP32による「アヤメの分類」のEVALUATION(データーファイル不使用バージョン)

 ※esp32はファイルシステムを使用可能だが、登録処理に多少手間が必要。
 そこでデーターをプログラム(**.h)に埋め込み入力データとする。
 (1)ライブラリ(nnabla-c-runtime)を取得する。
   nnabla-c-runtime
 (2)ESP32でコンパイル可能なエリアにフォルダ(例:esp-nnc)を作成。
 (3)必要なライブラリ(src functions下のimplementsとutilities)をesp-nnc(のcomponents下)に格納
 (4)c_sourceの内容をフォルダにコピーする(例ではmain下)。
 (5)esp-idfがコンパイルしてくれるように、各フォルダにcomponent.mkを作成、配置。
  ※esp-idfをバージョンアップしたらコンパイルが通らなくなりました。
   component.mkの適用範囲が変わったと思われるので、(バグだと思うが)
   component以下のディレクトリをすべて書き込みました。(前のはimplements utilitiesのみ記載)
 (6)MainRuntime_example.cを処理内容に合わせて書き換え。
  ※MainRuntime_example.cの19行目「//#define FINP」はコメント(//)に設定の事。
 (7)ESP32メイン(app_main)からMainRuntime_example.cのmain()を呼びだすようにプログラムを作成。
 ※上記説明だけでは判り難いとおもわれるので、説明も兼ねて(1)-(7)を実施した結果を下記にアップしている。
  ダウンロードすればesp32開発環境下でコンパイル可能(なはず)。
   ESP32による「アヤメの分類」
 (7)make flash monitor を実行。(ctrl+]で終了)
  下記が表示されるので、neural_network_consoleの表示と比較する。
  ※シリアルをCOM6に設定しているので、異なる場合はmake menuconfigで変更するか、COM番号を変更の事。

    * Start *
     5.0 3.5 1.3 0.3 ( 0 )  +6.443 +2.331 -7.357 ( 0 )
     4.5 2.3 1.3 0.3 ( 0 )  +5.065 +2.398 -6.332 ( 0 )
       :
     6.2 3.4 5.4 2.3 ( 2 )  -4.329 +1.268 +2.976 ( 2 )
     5.9 3.0 5.1 1.8 ( 2 )  -3.711 +1.436 +2.227 ( 2 )
    * Stop  *

ESP32による「アヤメの分類」のEVALUATION(データーファイル使用バージョン)

 ESP32でデーターファイルを使用する場合、spiffsライブラリを使用することになる。
 また、予めデータを用意する場合は、エリアの確保、データイメージの作成とアップロード機能が必要となる。
 なお、データー格納エリアはpartitions_example.csvに書いており、flashの0x300000から0x3fffff(1MB)を使用している。

 <データファイルの作成と格納>
 (1)下記をダウンロードし、ESP32でコンパイル可能なフォルダに配置する。
   ESP32_spiffs_example
 (2)esp-nnc内のpartitions_example.csvをESP32_spiffs_exampleにコピー。
 (2)mingwを起動し、配置したフォルダ内で ./build_mkspiffs を実行。
  components mkspiffs 内に mkspiffs.exe が生成される。
  ※当方の環境では424行でエラーとなったので、「_mkdir」を「mkdir」に変更することで回避。
 (3)components spiffs_image image にアップロードするデータファイルを格納。
  ※samples sample_dataset iris_flower_dataset iris_flower_dataset_validation_delo.csv は iris_flower.csv としている。
 (4)make makefsの実行で、イメージファイル(1MB)が作成される。
   make flashfsの実行では、イメージファイルの作成後にESP32への転送が行われる。
 (5)make flash の実行で、テストプログラムのコンパイルと実行が行われるので、ESP32への格納の確認が可能。
  ※上記を実施したものを下記に圧縮して格納しているので、必要なら利用の事。
   データファイルの作成と格納用プログラム

 <実行>
 「データーファイル不要バージョン」と操作は同一。
 但し、MainRuntime_example.cの19行目「//#define FINP」のコメント(//)は取っておく。
 実行時に下記(格納ファイル情報)が追加表示される。
 「iris_flower.csv」が表示されない場合は、データファイルの作成と格納に失敗している。

    Spiffs.Dir.Info
      :
     iris_flower.csv
      :
    Partition size: total: 956561, used: 211091

VisualStudio(2017)による「アヤメの分類」のEVALUATION

 neural_network_consoleで表示されるものをVisualStudioで表示してもあまりメリットを感じないが、、
 パソコン上でのプログラムのデバッグには非常に役に立った。
 ※入出力の確認などは全てVisualStudio上で行った。これをESP32上で行ったら多大の時間を要したはず。
 (1)ライブラリ(nnabla-c-runtime)を持ってくる。
   nnabla-c-runtime
 (2)nnabla-c-runtimeフォルダで cmake CMakeLists.txt を実行。
  ※当方の環境ではesp-idf用に構築したmingw上にcmakeを登録して実行。
   複数の前提ソフトが必要となったがなかなか登録できず、一寸大変であった。
 (3)nnabla-c-runtime src functions に c_source をフォルダごとコピー
 (4)MainRuntime_example.cの書き換えを行う。
 (5)nnabla-c-runtime src functions に dataフォルダを作成し、必要とされるデータを入れておく。
 (6)nnabla-c-runtime src functions に nnablart_functions.sln が出来ているので起動する。
  ※visualstudio2017が登録されていたら起動する。(ない場合はどうなるだろう)
 (7)nnablart_functions 以外のソリューションは(とりあえず)要らないので削除しておく。
 (8)nnablart_functions を右クリック、プロパティ 全般 構成の種類 で アプリケーション (.exe)に変更する。
 (9)nnablart_functions を右クリック、スタートアッププロジェクトに設定する。
  ※上記を実施したものを下記に圧縮して格納しているので、必要なら利用の事。
   visualstudioによる「アヤメの分類」
 解凍後は「C:\」に設置し、c:\nnabla-c-runtime src functions の nnablart_functions.sln を起動する。
   (visualstudioのslnは絶対ディレクトリとなるため、必ず存在するディレクトリで作成した)
 (10)デバッグを開始すればESP32の時と同様な表示が出る。(はず)

 なるたけ再現性を確保したつもりですが、ごてごて書くのも何なんで、説明が不十分だと思います。
 後はアップロードしているプログラムで内容を確認願います。
 次はMNIST(画像による数字認識)に迫りたいと思っている。
 上記記載内容は無保証であり、各自の責任においてご利用願います。