TensorFlow Lite 2.1 on STM32F

TensorFlow 2.1.0がリリースされていた。最近はなぜか組込み向けでDeep Learningをする話がやってくる事があって、TensorFlow Liteを使ったりしている。

TF Liteを使ってみたことがある人は分かるだろうけど、TensorFlowのHP・ドキュメントにある通りにやっても基本的にビルドできない、サンプルが動かない、ドキュメントのリンク先は404 not foundという「一体これは何だ?動くのか?」という思いが最初に来ると思う。さらにはLayerの制限で、このモデルを作ったはいいけど、TF Lite上で動かしたらエラーで動かん…とか罠が満載で快感すら覚えてしまう。
自分もバージョンが変わる事に起きるドラスティックな変更で、これはどうすれば動くんだ?というので頭を抱えてしまう。

サクサク動いてめちゃ便利なんだけど、動かすまでが大変な沼にハマる…ということで、自分用としてもTensorflow 2.1.0で動かす手順を残しておく。ターゲットとしては次のとおり。hello_worldのサンプルを動かす。
ちなみに、本家のドキュメントのとおりArduino MKRZERO向けのサンプルのビルドをやろうとしても現時点でビルドできないからねwww ちょっと色々と修正するとArduino IDEでもビルドできるけど、デフォのサンプルだと動かないw (Arduino IDE向けのサンプルコードはこちら、もしくはAdafruitのdiffを当てる)

■ 環境
Tensorflow 2.1.0
Nucleo STM32F446RE(手元にあったもの)
VScode (PlatformIO)

ソースコード一式はこちら。PlatformIO向けに持ってきてビルドすれば動く。学習モデルはGoogle Colabで公開されている物を使うとTensorFlow Lite向けの軽量・量子化されたデータをそのまま持ってきて使える。ソースコードはNucleo向けだけど、ソースコードはそのままでarm向けなら何でもOK。
この一式を使えば、TensorFlowで学習したモデルを持ってきて、arm向けにビルドしてすぐ組込める。もちろんarm Arduinoとかでもね。一旦作っちゃえばオールOKすね。

以下は、自分で頑張ってゼロから環境を作りたい人へのメモ。

■ TensorFlow 2.1.0 Liteのプロジェクトを作る

Tensorflow Liteでは組込で必要なプロジェクトを自動で生成してくれるmakeが用意されている。一旦、Ubuntu 18.04上で作る。

pip install six==1.12.0
wget https://github.com/tensorflow/tensorflow/archive/v2.1.0.tar.gz
tar -zxvf  v2.1.0.tar.gz
cd tensorflow-2.1.0
make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=arduino TAGS="" generate_hello_world_arduino_library_zip
# じっと待っているとtensorflow_lite.zipが出来る。これを持ってきて利用する。
cp tensorflow/lite/experimental/micro/tools/make/gen/arduino_x86_64/prj/hello_world/tensorflow_lite.zip  $HOME

tensorflow_lite.zipを展開するとArduino向けのプロジェクトとして使える一式が出来る。他にも画像・音声認識とかのプロジェクトを生成できたりもする。
このまま使えばOKじゃん!!と思うかも知れないけど、もちろん、このままArduion IDEで取り込んでもビルドできない(TF Liteマジでふざけんなよw)。ちょっと工夫するとArduino IDEでも動かすことが出来る。実際にトラ技で書いた内容では、TensorFlow & ARDUINO MKRZERO arm-cortex M0で自作モデルを動作させて性能も出せている。
ということで、tensorflow_lite.zipをWindows/Macどちらでも持ってきて、PlatformIO向けに展開していく。

■ PIOのプロジェクトを作る

FrameworkはArduinoで適当に作っておく。mbed向けになると、前述のTF Liteのスケルトンプロジェクトをmbedとして作り直し(がんば)。

■ TF LiteをPIOにぶち込む

tensorflow_lite.zipを展開すると次のような感じになる。

これをPlatformIOのフォルダに次のような感じで展開する。

■ 推論の性能どんなもん?

推論を実行しているのはmain.cppの次の部分。
TfLiteStatus invoke_status = interpreter->Invoke();
この単体性能を測定してみると、170回/sec でまぁ使える感じの速度ですな。モデルや設定次第で数千回/secは超える。sin波を推定しているだけだから軽めというのもあるけどね。動かしてみるとこんな感じ。

https://www.hirotakaster.com/wp-content/uploads/2020/01/movie.mp4

■ 自前のセンサー対応モデルを組込むには?

一旦動いてしまえばカンタンな訳だけど。Google Colab上で最後に量子化して生成されたコードをsine_model_data.cppの中の配列・配列長にコピペして終わり。推論の方はinputに値を渡してInvoke、結果はoutputのTfLiteTensorから取得できる。
問題は…DropoutとかFlattenとかー…使えないのよね。対応しているオペレータはこちら。これが地味にハマるというか辛いポイントだったりする。対応してあると書いてあるオペレーターが別の資料はで未実装と書いてあったり、動くと期待してモデルに組み込んだら見事にエラーとか、ビルドもだけどトラップがねw

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください