for WPF developers
Home Profile Tips 全記事一覧

Keras による学習モデルを変換して Raspberry Pi 3 Model B+ 上で .NET Core アプリから共有ライブラリ経由で TensorFlow Lite の学習モデルによる推論を実行する (2)

(2020/02/07 9:16:20 created.)

(2020/02/07 9:26:52 modified.)

ここでは、タイトルの通り Keras の学習モデルを Raspberry Pi 上で動作させるまでのプロセスをまとめています。第 2 回の今回は TensorFlow Lite の静的ライブラリをビルドしたいと思います。

目次

  • 予告
  • Ubuntu with VMWare Player で環境を準備する
  • libtensorflow-lite.a 静的ライブラリをビルドする <-- 今ココ!
  • Keras in Python でサンプル用の学習モデルを構築する
  • Keras で構築した学習モデルを TensorFlow Lite のモデルに変換する
  • 静的ライブラリで TensorFlow Lite のモデルを使用する C アプリケーションを Ubuntu 上で動かす
  • TensorFlow Lite のモデルで推論する機能を提供する ARM 向け共有ライブラリをクロスコンパイルする
  • 作成した共有ライブラリを使用する C アプリケーションを Raspberry Pi 上で動かす
  • .NET Core コンソールアプリケーションを Raspberry Pi 上で動かす
  • .NET Core コンソールアプリケーションから共有ライブラリを参照して TensorFlow Lite のモデルを使用した推論をおこなう

TensorFlow の公式ページはこちらになりますが、そのソースコードは GitHub で公開されています。このソースコードを自分でコンパイルすることで静的ライブラリを生成しようという試みです。「自分でコンパイル」とは言っても、既に用意されているスクリプトを実行するだけの簡単なお仕事です。

TensorFlow のリポジトリをクローンする

それでは早速 TensorFlow のリポジトリをクローンします。

terminal
  1. cd ~/Documents
  2. git clone https://github.com/tensorflow/tensorflow.git
  3. cd tensrflow
  4. git checkout v2.0.0
  5. git checkout -b cross_build

v2.0.0 というタグで TensorFlow 2.0.0 リリース時の状態になるので、いったんそのコミットをチェックアウトします。さらにそこから独自の cross_build ブランチを切っておくことで、元の状態にいつでも戻ってこれるように準備しておきます。何事も準備は大切です。

ビルドのための準備

依存関係のあるパッケージをいろいろ用意する必要がありますが、これを自動的におこなってくれる便利なスクリプトが既に用意されているのでこれを実行します。

terminal
  1. ./tensorflow/lite/tools/make/download_dependencies.sh

タグ v2.0.0 をチェックアウトしておけば特にエラーが起こることもないと思いますが、中途半端なコミットで実行するとたまにこのスクリプトでエラーが発生してしまいます。半端なコミットは公式でも動作保証できないものですので、できるだけリリースビルドされているコミットで実行しましょう。

さらに、Makefile の一部を編集します。

terminal
  1. gedit tensorflow/lite/tools/make/Makefile
  2. # original)
  3. # BUILD_WITH_NNAPI ?= true
  4. # change)
  5. # BUILD_WITH_NNAPI = false

「BUILD_WITH_NNAPI」で検索すると該当の行へすぐにジャンプできます。Android の NNAPI を使用するかどうかを設定する部分のようですが、false にしておいたほうが無難なようです。

最後にビルドに必要な Bazel をインストールします。まずは cat .bazelversion で必要な Bazel のバージョンを確認しておきましょう。v2.0.0 のコミットをチェックアウトしたのであれば「1.2.1」と表示されるはずです。

terminal
  1. cat .bazelversion
  2. # 1.2.1

というわけで Bazel 1.2.1 をインストールしましょう。Ubuntu へのインストール方法は公式ページにも掲載されており、ここでもその通りの手順でインストールします。

公式ページにも記載がありますが、ここでは Ubuntu 16.04.3 を使用しているので openjdk-8-jdk をインストールしています。もし Ubuntu 18.04.3 を使用している場合は openjdk-11-jdk をインストールしてください。

terminal
  1. sudo apt-get install g++ unzip zip
  2. sudo apt-get install openjdk-8-jdk(ちょっと時間かかる)
  3. cd ~/Downloads
  4. curl -LO https://github.com/bazelbuild/bazel/releases/download/1.2.1/bazel-1.2.1-installer-linux-x86_64.sh
  5. chmod +x bazel*
  6. ./bazel-1.2.1-installer-linux-x86_64.sh --user
  7. bazel --version
  8. # bazel 1.2.1

最後に「bazel --version」でインストールされた Bazel のバージョンを確認しています。もし間違ったバージョンをインストールしてしまった場合は、関連ファイルを削除することでアンインストールしてから再度インストール作業をおこなってください。関連ファイルの削除は以下の通りです。

terminal
  1. # Bazel をアンインストールする場合に実行
  2. rm -fr ~/.bazel
  3. rm -fr ~/.cache/bazel

TensorFlow Lite のビルド

それではいよいよビルドです。とは言ってもビルド用のシェルスクリプトを実行するだけです。私の環境では、このスクリプト実行完了におよそ 5 分ほどかかりました。

terminal
  1. cd ~/Documents/tensorflow
  2. ./tensorflow/lite/tools/make/build_rpi_lib.sh(5 分かかった)
  3. cp tensorflow/lite/tools/make/gen/rpi_armv7l/lib/libtensorflow-lite.a .

完了後に生成される libtensorflow-lite.a というファイルが TensorFlow Lite の静的ライブラリになります。これを使用すると、Linux 上で C/C++ によるプログラムに TensorFlow Lite の機能を組み込むことができるようになります。今後のためにカレントディレクトリにコピーしています。

もしビルドが途中で失敗するなどしてもう一度ビルドする場合は、下記ディレクトリを削除してからおこなうと良いでしょう。

terminal
  1. # ビルドをやり直すときに実行
  2. rm -fr tensorflow/lite/tools/make/gen

まとめ

今回は TensorFlow Lite の静的ライブラリである libtensorflow-lite.a ファイルを生成するところまでを掲載しました。このビルド方法を調べているときは中々正常にビルドできず、非常に苦労していましたが、こうやってまとめると迷うようなところがないように見えて不思議です。また、調査している段階では TensorFlow のリポジトリはハッシュ 2cbbe2ae0d4ab61d8f08f1eb31417e4a163395c7 の中途半端なコミットでビルドしていました。一応ビルドはできましたが、できあがったライブラリの信頼性を考えたとき、リリースビルドされているコミットにチェックアウトすべき、ということに気が付きました。

せっかく git を使っているので、生成した libtensorflow-lite.a を含めてコミットしておいても良いかもしれません。バイナリファイルなので git としてはあまりよろしくありませんが、後でもう一度 Bazel でビルドし直すのも面倒ですし。私の場合は余計なディレクトリなどは .gitignore に登録して無視するように設定し、編集した Makefile や生成した libtensorflow-lite.a ファイルを含めていったんコミットしました。

さて、作成したライブラリはしばらく寝かせておくとして、次回は Python でサンプル用の学習モデルを作成します。