E AndroidRuntime: DeadSystemException: The system died; earlier logs will point to the root cause
W System.err: java.lang.Throwable: tname=main - android.os.DeadSystemException
W System.err: at adgh.a(PG:17)
W System.err: at adgh.uncaughtException(PG:20)
W System.err: at java.lang.Thread.dispatchUncaughtException(Thread.java:1955)
W System.err: Caused by: java.lang.RuntimeException: android.os.DeadSystemException
W System.err: at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1442)
W System.err: at android.app.ContextImpl.registerReceiver(ContextImpl.java:1394)
W System.err: at android.app.ContextImpl.registerReceiver(ContextImpl.java:1382)
W System.err: at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:609)
W System.err: at ajmt.a(Unknown Source:10)
W System.err: at akmp.a(Unknown Source:117)
W System.err: at akma.a(Unknown Source:12)
W System.err: at akmu.a(Unknown Source:7)
W System.err: at aklm.a(Unknown Source:8)
W System.err: at ajqf.a(Unknown Source:2)
W System.err: at ajpo.handleMessage(Unknown Source:11)
W System.err: at android.os.Handler.dispatchMessage(Handler.java:106)
W System.err: at android.os.Looper.loop(Looper.java:164)
W System.err: at android.app.ActivityThread.main(ActivityThread.java:6494)
W System.err: at java.lang.reflect.Method.invoke(Native Method)
W System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
W System.err: Caused by: android.os.DeadSystemException
W System.err: ... 17 more
I Process : Sending signal. PID: 3501 SIG: 9
解決策を試行錯誤している中で、最終的にSwiftRenderが助けてくれました。no-windowオプションと合わせてエミュレータを起動した結果、正しくエミュレータが起動し、Espressoのテスト実行も完了することができました。 Configuring graphics acceleration on the command line にも書かれている通り、これは swiftshader_indirect モードによるエミュレータ起動で利用することができるものでした。このライブラリはOpenGL ESをCPU処理を使い実現するものです。
単純に考えれば、サンプルで動いているモデルに基づき、自分たちのデータを使って再学習したモデルをTOCOを使って.tfliteファイルに変換するだけで上手くいくはずです。
ML Kitのサンプルではmobilenet_quant_v1_224.tfliteという重みが量子化されたMobileNetV1が使われているので、とりあえずMobileNetV1の量子化バージョンMobilenet_1.0_224_quantから再学習したretrained_graph.pbを使いfood-non-food.tfliteを作成します。
変換コマンドは以下のものを使用しました。
しかしながら、結果はダメで、サンプルのモデルだけ置き換えると例えばDidn't find custom op for name Dequantizeなどというエラーを吐きます。
これはTensorFlow Lite側で計算グラフのoperationが実装されていないことを意味しています。
operationが無いということで、選択肢は自分で頑張って実装するかサポートされているoperationだけでモデルを作るかです。
そもそもちゃんと動くか分からない状況なので、試すまでのスピードや余計なバグの原因を混入させないという意図で、後者の方法で進めることにしました。
まず試したのは、floatモデルをfake quantizationして扱うという方法です。
ML Kitのサンプルが量子化されたモデルを扱っているのでこれが既存のスクリプトを書き換えずに実行する近道に思えます。
Mobilenet_1.0_224を元に再学習したretrained_graph.pbを以下のコマンドで量子化されたfood-non-food.tfliteに変換します。
これで作ったモデルはエラーは吐きませんが、予測のスコアが[0.7,0.3]辺りをうろついてあまり変化しないという結果になりました。
この結果から推察するに入力の画像の取り扱いや重みがちゃんと入ってるかなどが怪しいところですが、いくつか調べてみても解決法は見つかりませんでした。
ML Kitの世界に行ってしまうとどこに問題があるか(モデル変換にバグがあるのかアプリ側にバグがあるのか)のデバッグが難しいということもあります。
ML Kitはまだβ機能として提供されているので、対応しているモデルのオペレータが少なかったり、
量子化されたモデルを上手く動かす情報が不足していたり、発展途上であることは確かです。
しかし、一度モデルを構築してしまえばオンデバイスで動作させることができますし、Firebase経由でモデルのアップデートも簡単にできます。