MonotaROのMLOps〜バンディットアルゴリズムの効果を最大化するリアルタイムデータパイプライン〜

はじめに

 皆さん、こんにちは。MonotaROTechBlogをご覧いただきありがとうございます。データサイエンスグループ所属の植村です。今回の記事では、MonotaROで取り組んでいるバンディットアルゴリズムを用いた施策を支える、データパイプライン*1を紹介したいと思います。リアルタイムな情報を用いて最適化を行う基盤を提供する方々の参考になれば幸いです。

本記事でお伝えしたいこと

  • MonotaROの推論APIの裏で動くデータパイプラインの紹介。
  • バンディットをMonotaROのケースに適応する際に、データパイプライン構築に関して注意したこと。

MonotaROのデータサイエンスチームの環境について

 本題に入る前に、MonotaROのデータサイエンスチームの業務環境について紹介します。MonotaROではデータサイエンス系のプロジェクトではほぼ全てGCPのサービスを活用しています。例えば、データ解析にはBigQuery、VertexAIを用いることが多いです。バッチジョブ管理ツールはGKEの上に構築しています。今回作成したデータパイプラインもGCP上に構築しています。

MonotaROとバンディット

 バンディットアルゴリズムにMonotaROが着目した理由は、テスト時の損失の低減です。MonotaROで従来から行われていたABテストではテストの間、ユーザーを二分してしまいます。バンディットでは、ユーザーの行動を元に逐次的に最適化を実施していくため、ABテストに比べて損失の低減が期待されます。MonotaROにおけるバンディットアルゴリズムへの取り組みは、こちらの記事でも取り上げています。 tech-blog.monotaro.com

MonotaROにバンディットを導入する際の課題や必要な要件

 バンディットをMonotaROのビジネス環境で用いる場合、いくつか克服すべき課題や満たすべき要件があります。それらの要素とどのよう様にして実現したかを紹介します。

  • アルゴリズムにおける課題

    • 報酬を生成する報酬確率分布が一定でないことや、サンプルサイズが小さくなってしまうといった問題がありますが、それに関してはこちらで紹介しています。 tech-blog.monotaro.com
  • データパイプラインに求められる要件

    • リアルタイム性の担保
      • バンディットではユーザーの行動を反映した逐次的な最適化を行います。MonotaROでは、ほぼ絶え間なくそれらが生成されるため、できるだけ更新の頻度を高くすることが損失の低減の観点からも求められます。
      • 例えば1日1度の更新だと、1日の間はユーザーの行動は反映されず、すぐに更新した場合に比べ損失が増加することが想定されます。
  • ユーザーに対する意図しない影響の低減

    • 例えば、同じ商品ページのUIが訪問の度に変わると、意図せずユーザーの行動を変えてしまう可能性があります。
    • この要件に対しては、同日、同ユーザーが同商品を閲覧する場合は、(今回最適化する部分に関しては)同じUIを提供することで対応しました。
      UIの変更とユーザーの行動への影響のイメージ図

実際に構築したデータパイプラインの紹介

データパイプラインシステム図
 今回作成したデータパイプラインは上記の通りです。大きく分けて、モデルを用いた推論、ログの保存、モデルを更新する箇所に分かれます。それぞれ説明していきます。図中の矢印の色は各要素間の通信を表しています。

 それぞれ色ごとに通信するタイミングが異なっており、緑:ユーザーが最適化対象のページにアクセスした時に発生する。赤:バッチ更新のタイミングで発生する。紫:ユーザーのアクションを記録するが、利用できるまでには一定の遅れがある。

  • ページへのアクセスごとに推論をする箇所(2,3 <- 図中の番号に対応)
    • 役割
      • 最適化対象のページアクセス毎に事前に設定された確率分布からサンプリングを行い、その結果をWebページに提供する
      • ユーザーへの意図しない影響の低減のために、同一ユーザー、同一商品、同日は同じ結果を提供する。
    • 実装方法
      • モデルの情報は3のBigtableに保存しており、最適化対象のページアクセス毎に取得しています。
      • 同日、同ユーザーに一貫したUIを見せるために必要な情報を3のBigtableに書き込み、リクエスト毎に事前にアクセスがあったかチェックしています。
  • ログを保存する箇所(2,5)
    • 役割
      • APIの処理結果(どの最適化対象にどの結果を返したか)をリアルタイムに書き込む
      • データパイプラインの要件にある、リアルタイム性の担保のために作成しました。今回は、APIから学習バッチに必要な情報を即時書き出すことで対応しました。実際の更新頻度は、更新によるシステムの負荷と、最適化が遅れることによる損失を比較しました。さらに、モデルを更新するのに十分な情報が得られる期間を考慮し、1時間に1回の更新としました。
    • 実装方法
      • APIから、BigQueryに書き出すことで対応しました。書き込み先の変更に柔軟に対応するために、間にPub/Subを挟んでいます。
  • モデルの更新
    • 役割
      • 定期的にモデルの更新を行い、更新結果をAPIに提供する。
      • 上記の「ページへのアクセス毎に推論をする箇所」における、Bigtableは特定の条件では同じUIを表示し続けるためのログを保持するために利用しています。「モデルの更新箇所」では、推論に用いるモデルのパラメータを格納しています。
    • 実装方法
      • APIから書き出されたログを用いて、モデルを更新、その結果をBigtableに書き込むことで対応しました。

こぼれ話(負荷テストで驚いたお話)

 データパイプライン構築時には、ロジックテストの他に、実環境の負荷に耐えられるかを試す必要があります。一般の負荷テストツールなどを用いる方法もあったのですが、今回は実環境のログをミラーリングしてAPIに流すことで対応しました。個人的に驚いたのが、MonotaROでは実際のログをミラーリングをする仕組みが整備されており、数クリック(コマンド数回)で実現できます。今回はこの仕組みを用いて簡単に実際の負荷をシミュレーションすることができました。

データパイプラインによって変わったこと

 ユーザーへ与える悪影響(購買体験の低下など)を最小限にしつつ、リアルタイム性を担保することでバンディットの特徴である動的な最適化を可能にすることができました。

終わりに(まとめ)

 この記事では、バンディットアルゴリズムの推論結果を提供する際のデータパイプラインにおいて、リアルタイム性、ユーザーへの意図しない影響に関する課題があることを述べました。その課題に対して

  • 一定期間中に同じページを複数回参照した場合はアルゴリズムの結果ではなく同じUIを参照させること

  • 1時間ごとにバンディットアルゴリズムを用いて学習させる

という工夫をすることで、ABテストに比べ損失を抑えながらの最適化(バンディットアルゴリズムを用いた動的な最適化)を実現しました。

 今回の取り組みを機に、MonotaROでは様々なプロジェクトで施策を支えるデータパイプラインの開発を続けていく予定です。今回の記事を見て、MonotaROでの機械学習エンジニアリングに少しでも興味を持っていただけた方は、カジュアル面談や実際の選考へのご応募をご検討いただければ嬉しいです!よろしくお願いします!

hrmos.co

*1:このブログでは、モデルの学習、ログの収集解析、APIによる推論結果の提供までに必要なデータの移動、変換を実現するためのシステムとしています。