Kitで自作のカスタムモデルを使って料理・非料理画像を判定できるようにした会員事業部の山下(@farmanlab)です。Androidエンジニアとしてクックパッドアプリの開発を担当しています。Kitをクックパッドのデータで学習したモデルを使って検証した話をします。機械学習モデルの利用にあたって、研究開発部の菊田(@yohei_kikuta)の協力の元で検証を行いました。クックパッドの料理・非料理を判別するモデルを動かした実機デモをお見せします。これは料理と判定された確率がfood、料理ではないと判定された確率がnon-foodというラベルのスコアで表示されているデモです。(非)料理画像において(non-)foodのラベルのスコアが大きくなり正しく判別できていることが分かります。Kitとはモバイルアプリ向けに機械学習機能を組み込むことができるSDKです。Firebaseの機能の一つとして提供されており、Android/iOSに簡単に導入することができます。大まかに以下のような特徴があります。ラベリングバーコードスキャン顔検出ランドマーク認識オンデバイスモードとクラウドモードで利用可能オンデバイスモードでは端末にモデルをダウンロードすることでオフラインで動作し、無料で使うことができます。Firebaseの課金プランをBlazeにする必要があり、一定回数以上の利用は有料です。独自のカスタムモデルを利用可能デフォルトで提供される機能以外に独自の機械学習モデルを利用することができます。ちなみにカスタムモデルの利用にあたってはFirebaseの課金プランをBlazeにする必要はありません。開発者がNNAPIに関するコードを書く必要がありません。LiteのモデルをホストするアプリでFirebaseのモデルをバンドルするバンドルしたモデルを利用して推論する1と3については公式に詳しいので、説明はそちらに譲ります。ここでは2と4と5について掘り下げていきましょう。このサンプルに元にしつつ、自分たちのモデルを動かす上で必要になるポイントも加えて説明していきます。Liteのモデルに変換するサンプルを動かす場合はGitHubのレポジトリにmobilenet_quant_v1_224.tfliteが用意されているので、特に準備をする必要はありません。Liteのモデルに変換するツールを使えばいいのですが、自分で学習したモデルを使うには注意を要します。ここではその部分を詳しく解説します。今回はクックパッドで使われている料理・非料理判別モデルを実装します。モデルはサンプルに倣って基本的にはMobileNetV1を使います。冒頭で示したようにMobileNetV2でも実装ができていますが、これはV1の実装ができれば(モデルアーキテクチャ以外)全く同様にできるため、ここでは試行錯誤の過程を紹介する意味でもV1の話をします。それぞれのモデルの詳細はこの記事では解説しませんが、学習済みのモデルはV1はこちらとV2はこちらにあります。自分たちが準備したデータでモデルを学習する部分には新しいことはなく、tensor-for-poets-2のコードやtensorflow/hubのコードがそのまま使えます。今回は料理・非料理の二値分類を対象としました。Liteのモデルを作るところで苦戦したので、気をつけるべき点と共に手順を紹介します。ファイルへ変換することを考えます。model_graph.pbをmodel.tfliteファイルに変換するコマンドは以下のようになるイメージです。--output_arrays=final_resultこのように、TensorFlowでモデルの学習をする場合はそのままTOCOを使えば.tfliteを作れるため、変換それ自体に困難はありません。TensorFlowのバージョン依存性が強いので注意が必要です。この記事における我々の結果は全てtensorflow-gpu==1.7.1で実行したものとなります。他のフレームワークでモデルを学習する場合は一旦TensorFlowのモデルに変換する必要がありますが、変換用のライブラリは色々出てるので、標準的なoperationのみを使っていれば可能だと思います。Lite側の実装をする必要があります。quantizationという、重みはuint8で扱うが出力はfloat32として扱う機能が提供されています)。単純に考えれば、サンプルで動いているモデルに基づき、自分たちのデータを使って再学習したモデルをTOCOを使って.tfliteファイルに変換するだけで上手くいくはずです。Kitのサンプルではmobilenet_quant_v1_224.tfliteという重みが量子化されたMobileNetV1が使われているので、とりあえずMobileNetV1の量子化バージョンMobilenet_1.0_224_quantから再学習したretrained_graph.pbを使いfood-non-food.tfliteを作成します。変換コマンドは以下のものを使用しました。--output_arrays=final_result先程の例と比べると入力のshape指定や値の標準化なども入っています。opがないというエラーが出るのでつけています。「それでは動かないのでは?」という自然な疑問が湧きますが、一方でサンプルで動いているモデルと同じだ(と思われる)ので動くだろうという期待もそれほど悪くないものに思えます。Dequantizeなどというエラーを吐きます。Lite側で計算グラフのoperationが実装されていないことを意味しています。operationが無いということで、選択肢は自分で頑張って実装するかサポートされているoperationだけでモデルを作るかです。そもそもちゃんと動くか分からない状況なので、試すまでのスピードや余計なバグの原因を混入させないという意図で、後者の方法で進めることにしました。以降では重みをfloatで扱うモデル(以下floatモデル)をどのようにすれば動かせるかを紹介しますが、そもそもサンプルにおいて量子化されたモデルがどのように動いているかに関してはよく分かっていません。quantizationして扱うという方法です。Kitのサンプルが量子化されたモデルを扱っているのでこれが既存のスクリプトを書き換えずに実行する近道に思えます。Mobilenet_1.0_224を元に再学習したretrained_graph.pbを以下のコマンドで量子化されたfood-non-food.tfliteに変換します。quantizationに必要な情報で、活性化レイヤーでの値の取りうる範囲を指定して量子化の際の情報として使います。理想的には学習時の結果を保持して使うものですが、MobileNetV1はReLU6を使っているためこのように指定できます。これで作ったモデルはエラーは吐きませんが、予測のスコアが[0.7,0.3]辺りをうろついてあまり変化しないという結果になりました。この結果から推察するに入力の画像の取り扱いや重みがちゃんと入ってるかなどが怪しいところですが、いくつか調べてみても解決法は見つかりませんでした。Kitの世界に行ってしまうとどこに問題があるか(モデル変換にバグがあるのかアプリ側にバグがあるのか)のデバッグが難しいということもあります。いうことで残りは素直にfloatモデルを作ってアプリ側でもfloatモデルを扱うように変更するという方法です。モデル変換は以下で実施しました。bytesというエラーに遭遇します。モデル的にはfloat32で扱うところを入力としてはuint8を想定しているために不整合が起こっているように見えます。これは元々アプリ側では量子化されたものを扱おうとしていたのだから自然なエラーだと思われ、アプリ側を適切に変更すれば動くことが期待できます。いずれにせよ、モデルを作る側にできるのはここまでなので、以降でこのモデルのアプリへの取り込みとアプリ側でどのように扱えば正しく動かせるのかを説明していきます。Kitに取り込んでみましょう。ここでの手順は他のカスタムモデルを取り込む手順と違いはありません。Kitでカスタムモデルを使う際の大まかな構成は以下のようになっています。アプリにモデルをバンドルするときにはFirebaseModelManagerを利用します。registerLocalModelSourceとregisterCloudModelSourceメソッドを使って利用するモデルのバンドルを行います。ローカルモデルのみ、クラウドモデルのみを利用することも可能です。.build()Builderのコンストラクタにはモデルを識別するための任意の文字列を渡します。Assetsフォルダ内のtffileを参照する場合にはsetAssetFilePathを、それ以外のフォルダを参照する場合はsetFilePathでファイルを指定します。.build()FirebaseModelDownloadConditionクラスでCloudモデルをダウンロードするための条件を設定することができます。FirebaseCloudModelSource.Builderのコンストラクタにはステップ3でFirebaseにホストしたモデルの名前を指定します。enableModelUpdatesをtrueにするとFirebaseにホストしたモデルに更新があった場合にモデルをFirebaseから更新するようになります。この仕組みのおかげでアプリをアップデートすることなく最新の学習モデルを利用することが可能です。registerCloudModelSource(attractivenessCloudSource)}FirebaseModelManagerのインスタンスを取得して、登録メソッドで渡します。Kitの構成にもあるように複数の機械学習モデルを利用することも可能です。ここでは料理・非料理の判別モデルと料理の魅力度推定モデルを登録しています。FirebaseModelInterpreter.getInstance(options)FirebaseModelOptionsクラスで推定を行う機械学習モデルの指定を行います。FirebaseModelManagerに登録した機械学習モデルを使用することができます。このFirebaseModelOptionsを使って、実際に推定を行うFirebaseModelInterpreterのインスタンスを取得します。5.モデルを使って推定するいよいよ、カスタムモデルを使って推定を行います。入出力のデータを指定するFirebaseModelInputOutputOptionsを使って、学習モデルのinputとoutputのデータを指定します。今回利用する学習モデルはfloat値を扱うように作成しているので、floatの多次元配列がinputデータになります。outputデータは画像がモデルによって予測されるカテゴリのいずれかの確率であるfloat値の多次元配列(softmaxの出力)です。カテゴリ一覧を表すテキストファイルをassetsフォルダなどに配置して読み込みます。モデルのカテゴリを表すfoodnon-foodという内容のテキストをlabel.txtというファイル名でassetsフォルダに配置したと仮定します。.build()Bitmapからinputデータを作成するまずはinputデータを格納するための多次元配列を作成します。KitはByteBufferには対応していますが、FloatBufferには対応していませんでした。合わせて224×224サイズにリサイズし、リサイズしたBitmapからpixel値を取り出します。ここで重要なのが、pixelの各RGB値に対して、IMAGE_MEANとIMAGE_STDを使って演算をしている点です。...とMEANとSTDの値を指定しているので、モデル推論時にいい感じにやってくれるように思います。実際には予め計算した値をinputとして与える必要があります。FirebaseModelInputs.Builderのaddメソッドに渡してやります。FirebaseModelInterpreterのrunメソッドに渡すと推論が実行されます。}}addOnSuccessListenerが受け取るTaskからgetOutputすることで推論結果を得ることができます。今回はfloatのモデルを使ったのでgetOutputで得られる型はfloatの多次元配列です。ここではlabel.txtで指定したカテゴリのインデックスと出力値をマッピングしています。実際に実機で動かしたデモをお見せします。一つ目は冒頭でもお見せした料理・非料理判別です。MobilenetV1とMovileNetV2の両方で実装しましたが、大きく変わるところはないので後者の結果のみを改めてお見せします。餃子やグラタンやパスタといった料理画像ではfoodのスコアが高くなり、ゴリラや紫陽花などの非料理画像ではnon-foodのスコアが高くなっていることが確認できます。二つ目は魅力度推定です。これは学習データとして料理の見栄えを5段階評価(数字が高いほど見栄えが良い)したものを準備し、回帰モデルを学習したものになります。こちらはMobileNetV1のみで実装しましたのでその結果をお見せします。数枚でかつ主観的な評価とはなりますが相対的に見栄えの良いと思われる画像に高いスコアが付与されており、モデルが期待通りに動いていることが確認できます。今回は動かすことが目的であったため正答率や処理速度などの各種指標はまだ詳細には調べていませんが、これは単なるアプリのプロファイリングの話なので難しいところはありません。Kitの現状をクックパッドの機械学習モデルを使って検証した話をしました。量子化されたモデルを上手く動かす情報が不足していたり、発展途上であることは確かです。一度モデルを構築してしまえばオンデバイスで動作させることができますし、Firebase経由でモデルのアップデートも簡単にできます。設計する上で注意しなければなりません。Kitは機械学習機能をモバイルに組み込むための有効な手段の一つであると感じました。Kitのような最新技術を利用したモバイルアプリ開発や研究開発がしたい!というエンジニアを募集しています。機械学習チームの林田(@chie8842)です。モデルを学習...研究開発部の菊田(@yohei_kikuta)です。開催しました研究開発部の菊田(@yohei_kikuta)です。20180824...2018-04-06ディープラーニングによるホットドッグ検出器のレシピ研究開発部の画像解析担当のレシェックです。使ったセキュリティログ検索基盤の構築サービス特性にあった検索システムの設計戦略クックパッド採用説明会「クックパッドはサービスの作り手を採用したいんです。/*}*/スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。