この記事は、Mercari Advent Calendar 2021 の22日目の記事です。
こんにちは、メルカリ EdgeAIチームの@tkatoです。私たちのチームでは、クライアントサイドでの機械学習応用について、アルゴリズム開発からプロダクション開発までを担当しています。
12月16日に、メルカリレンズβという新しいプロダクトが公開されました。この記事では、メルカリレンズβを開発するにあたり、Webブラウザ向けに機械学習を用いたUIを開発した経験から得た知見を紹介したいと思います。
メルカリレンズβ
メルカリレンズβは、スマホのカメラで商品をかざすだけでメルカリでの取引相場や類似商品などの情報を表示するWebアプリです。いくらで買えるか知りたいときや、出品する値段で迷ったときに、メルカリを使ったことのないお客様でも気軽に使えるアプリを目指しています。
技術的には、機械学習を利用した直感的なUIをクライアントサイドで実現し、画像検索をベースとした類似商品検索や価格推定を行うAPIを用いたWebアプリです。
ログインやアプリのインストール不要で、こちらのURLにアクセスするだけで体験できます。ぜひお試しください!
https://jp-news.mercari.com/mercari-lens/
なぜWebなのか?
今回私たちがWebをプラットフォームとして選択した大きな理由は、前述のようにアプリのインストールが不要な点です。SNS等でシェアされたURLからすぐに体験を開始できる点は、特にメルカリを使ったことのないお客様が試しやすいことが期待できます。
また、このような実験的な機能としてメルカリアプリから独立して開発する際にも、Webはホスティングが比較的楽でした。実際、2021年4月からプロジェクトがスタートし、2021年8月から11月までユーザーテストを実施しながら改善を繰り返し、12月にリリースすることができました。*1
スムーズなインタラクションをどう実現するか?
カメラでかざしたものを検出し、UIとしてユーザーにフィードバックするためには、リアルタイムに常に検出し続ける必要があります。
メルカリレンズβでは、カメラの入力をサーバーに送信せず、デバイス内で高速に機械学習に関連する処理を実行することで、スムーズなインタラクションを実現をしています。このようなデバイス上で機械学習を実行する技術をEdgeAI(あるいはOn-device MLやClient-side ML)と呼び、一般的にはdata privacyやlow latencyといった観点で注目されています。
メルカリレンズβでは、下図のようにObject Detectionと軽量なObject TrackingをWebWorkerを利用して並列動作させています。なぜなら、Object Detectionの処理時間は多くのデバイスで数十から数百ミリ秒かかるため、カメラの入力に対して常に大きな遅延が発生する上、連続して動かすとCPUの負荷が高くなる課題があるためです。
TensorFlow.jsによるObject Detection
Object DetectionはDNNベースのモデルをTensorFlowで構築し、それをTensorFlow.js向けに変換してブラウザで動かしています。
TensorFlow.jsでは、数値計算のバックエンドをWebGLやWebAssemblyなどから選択できます。GPUによる高速な並列演算ができるため、WebGLを使った場合がWebAssemblyと比較して高速なケースが多いのですが、WebGLバックエンドは最新のスマートフォンでも初期化に数秒かかるときもあり、かつその間はUIが固まってしまう課題がありました。
最終的には、ページを開いてから最初の結果を表示するまでの体験や、それ以降の体験のUXを評価*2し、WebAssemblyバックエンドに決めました。
MediaPipeによるObject Tracking
MediaPipeは、カメラやセンサなどのストリーミングデータに対して機械学習モデルやコンピュータビジョンのアルゴリズムから成るパイプラインを構成できるフレームワークです。公式に、WebAssemblyにビルドしてWebブラウザでも動くことが発表されました。
MediaPipeには、Object DetectionとTrackingを並列動作させるパイプラインがExampleとして含まれており、これをそのままWebAssemblyにビルドすることを試行しました。しかし、モバイル向けブラウザ側の制限で、MediaPipeの並列処理をそのままブラウザで動かすことができませんでした。*3
最終的には、MediaPipeのObject Trackngのパイプラインだけを利用し、前述のTensorFlow.jsのモデルを組み合わせることで、Object DetectionとTrackingを並列動作させています。さらには、Object Trackingのアルゴリズムを調整して、多くのモバイルブラウザで数ミリから数十ミリ秒で動作させることができました。
ユーザーフィードバックを受けたUIの変更
私たちが期待するUXを実現するためには、EdgeAIの要素技術だけではなく、UI側の取り組みも重要でした。例えば、ユーザーテスト当初は以下のようなシンプルなUIで、かざしている間だけその結果が下に表示されるUIでした。
これはチーム内では、「無駄のないUIで短時間で多くの商品を試しやすい」と好評だったのですが、実際のお客様からは以下のようなフィードバックが寄せられました。
- かざしていないと結果が消えてしまい見づらい
- なにも検出しないときに、どうしたらよいかわからない
そこで、現在のような1件づつ結果を止めて表示するUIに作り変え、下図のように検出できないときにはメッセージを表示し、ユーザーに期待する行動をわかりやすく伝える工夫を試みました。
UIの実装
メルカリレンズβはReactベースのSPAとして開発していますが、ページ内の状態遷移の管理はReduxを利用して下図のようなstate machineを実装*4しています。
このアプリでは、検出中、結果の表示中、といった複数の状態があり、また以下のような様々なイベントが順不同に発生します。
- 検出した物体の位置情報の更新
- ボタンタップなどのユーザーアクション
- 物体を見失ったことなどを示すイベント
- ネットワークエラー
これらをシンプルに扱うために、state machineは役に立ちました。
おわりに
この記事では、メルカリレンズβを開発するにあたり、Webブラウザ向けに機械学習を用いたUIを開発した経験から得た知見を紹介しました。クライアントサイドでの機械学習応用に興味がある方に、今回のブログが参考になれば幸いです。
明日のMercari Advent Calendar 2021 の記事は、greg.wengさんによるMigrating a monolithic service under the bedです。引き続きお楽しみください。最後まで読んでいただきありがとうございました。
メルカリレンズβ、ぜひ試してみてください。
https://jp-news.mercari.com/mercari-lens/
*1:技術的には、iOS版の「かざして売れるかチェック」を先行して開発しており、コアとなる技術要素が固まっていたことも大きな理由です。(Mediapipeを使ったARアプリ開発事例〜カメラをかざして家の中で売れるものを探そう by Chica Matsueda | トーク | iOSDC Japan 2021 #iosdc – fortee.jp)
*2:チームで内製しているUX評価基盤を利用しています。(JetFire – Validation Platform for ML models on mobile devices | Mercari Engineering、CCSE2021_UXを担保するMLOps基盤 – Google スライド)
*3:開発当時のモバイルブラウザでは、SharedArrayBufferの使用に制限があるため、メモリを共有したマルチスレッドの利用が簡単ではありませんでした。(モバイルブラウザにおけるClient-side MLアプリケーションのプロダクション開発事例 / JSConf JP 2021 – Google スライド)
*4:今回は単純にReduxだけ利用して、簡易的なstate machineを実装しましたが、XStateのような便利なライブラリもあります。(XState + Apollo Clientでフロントエンドのステート管理 | メルカリエンジニアリング)