食料品店のレジ係向けのヒントシステムでした。クライアントの食料品チェーンでは野菜、果物、駄菓子がバーコードなしで売られました。レジ係はレジUIで該当な食材を選び、秤で重さを測り値段を付けました。でもこの食材類が数多く、UIで適切なものを選ぶには5秒以上かかりました。クライアントはこの5秒間をできる限り短くしたかった。その問題を改善するために組み込み機器で食材の写真を取って区別してレジでヒントを見せることになりました。
初めてのIT仕事の初めてのプロジェクトでした。チームはTeamLead/ProductManagerの一人、ハードウェア担当の一人、そしてコーディング担当の私ともう一人のJuniorMLEngineerでした。ですがどんあ問題があっても、私が解決しましたので、プロジェクト開始から半年後そのJuniorMLEngineerが解雇されました。結果的にコードベースの100%を一人で作りました。
当時の私はまだ経験が浅く、タスクはチームリードから与えられましたが、どう解決するかについては自由でした。何も分からない時には、概ねの助言だけもらいました。
開発中に直面した問題の中で、特に興味深かったものをいくつか挙げたいと思います。
1.レジとの通信
組み込み機器はクライアントのローカルネットワーク内で個別のデバイスです。問題は、クライアントのネットワークへの影響を最小限に抑えながら、それを複数のレジにどのように接続するかでした。この問題を解決するために、チームリードはRNDIS(Ethernet―Over―USBプロトコル)を使用して、レジとのUSB直結接続を提案しました。
それを実行するうちに私は二つの問題に直面しました:レジを通じてのインターネット接続と、RNDIS自体を動作させることです。インターネット接続の問題は、レジと組み込み機器の間でMasqueradeを設定することで比較的簡単に解決できました。しかし、RNDISの設定は簡単ではありませんでした。古いドライバーや、プロトコル、Linuxドライバー、Rockpi4Bのドキュメント不足が問題でした。最終的には試行錯誤を繰り返し、Rockpi4BのUSBポートには'host'、'device'、'otg'などの異なる動作モードがあり、それらはブートローダー設定で指定されたDeviceTreeFileを編集して再コンパイルすることで再設定できることが分かり、この問題を解決しました。
2.コスパ
レジの数が多く、Jetson並みの組み込み機器は高価で、レジ係を待たせるわけにはいきません。テスト用の様々な組み込み機器を貰って、適切なものを選んで欲しいと頼まれてしまいました。その組み込み機器はJetsonNano, Rockpi4b、Rockpi3、NanopcM4、そして無名な組み込み機器がありました。決めるためにどんあ推論フレームワークを使うべきか調べるようになりました。
結果的に推論フレームワークとしてTVMを使いました。TVMは推論バックエンドにOpenCLを使えるのでRK3399CPUのRockpi4,NanopcM4はMaliGPUを利用してMobilenetV2(あの頃V3がまだ広まれていませんでした)の推論を100ms以内で行うことができました。
3.その他
- 250-350クラス分類問題でした。Torch + MobilenetV2 + ApexMixedPresicion + Albumentations使って全クラスの精度90%以上達成しました
- クライアントのネットワークは40Kb/s以下で、CICDやMlOpsは毎夜Crontab+BashScript以外は不可能でした
- 350+組み込み機器のモニタリング。監視にはGrafana+Prometheus+BlackboxExporter+VictoriaMetricsを使いました
- データベースに関しては、各デバイスでSqlite3の臨時データベースとグローバルデータベースとしてPostgreSQLを使いました