ARINEのパーソナライズシステムについて

ARINEのパーソナライズシステムについて

美容メディアのARINEでサーバーサイドの開発を行なっているエンジニアのたばたです。
今回はARINEのNativeアプリのファーストビューに表示されるコンテンツにパーソナライズロジックを導入したので、そのシステム紹介をしたいと思います。

背景

ARINEは女性が「憧れ」により近くための美容メディアで、日々役にたつ美容情報の記事や写真などを掲載してます。

当たり前ですが、ユーザーがアプリを開いて最初に見る画面(以下ファーストビュー)が一番目に触れてもらえる場所なので、どのようなコンテンツを出すかは非常に大事です。今までは、ARINEの編集部が日々良さそうな記事をコツコツ手動で入稿していました。
しかし、一番見られる場所だからこそ、自動でそれぞれのユーザーに最適なコンテンツを届けたい(また、手動で毎日入稿するのも大変なの)ので、今回パーソナライズ機能を導入しました。

システム構成

まずはARINEのシステムの全体像について説明します。ARINEのサービスはAWS上で動いています。
今回導入したパーソナライズ機能は以下の図のように、既存のサービスとは別にPythonで書かれたサーバーとして提供しています。分けた理由としては、機械学習ライブラリが豊富なので、パーソナライズロジックをPythonで記述したかったからです。(WebサーバーではRailsを使用しています。)
パーソナライズ化されたファーストビューのコンテンツをユーザーが取得しようとした時の流れは以下のようになっています。
  • クライアントからファーストビューのコンテンツ取得APIをWebサーバーに対して投げる
  • Webサーバーが後ろにあるパーソナライズサーバーから表示すべきコンテンツのIDを取得
  • コンテンツIDからコンテンツを組み立ててクライアントへ返却

パーソナライズシステム

パーソナライズサーバーは、WebサーバーからユーザーIDを受け取ると、そのユーザーが好むであろうコンテンツのIDを返します。この際にパーソナライズサーバーは事前に学習したモデルを使って計算を行い、コンテンツを決定します。
このモデルを作成するには、様々なデータソースからデータを集めて複数の前処理等が必要です。依存のある複数の処理を管理するためにはワークフローツールを使うのが一般的です。ARINEでは定期的に実行するJobのワークフローはAirflowを使って運用しています。Airflowを導入した時の話は以前に書かせていただいたので、もしよければみてください。
必要な処理を繋げてワークフローを作り、パーソナライズで使うためのモデルを作っていきます。
1時間おきにワークフローを実行して、新しいモデルを作り、新しいモデルを反映したサーバーをデプロイするまでをAirflowで管理しています。

前処理のワークフローの一部

モデルを作るまでの処理が終わると、作成したモデルをS3に書き出して、パーソナライズサーバーを起動します。S3に書き出されたモデルには実行ごとに一意なパスで保存されていて、サーバー起動時にパラメータストア経由でこのパスを渡しています。パーソナライズサーバーはECSで管理されていて、デプロイが行われサーバーが起動すると事前に必要なモデルをS3からロードしてからリクエストを処理し始めます。
Webサーバーはパーソナライズサーバーのエンドポイントを叩いて、コンテンツのIDを受け取り、そのコンテンツを生成してクライアントにレスポンスを返しています。もしもパーソナライズサーバーに障害が発生して落ちてしまったとしても、ユーザーが何もコンテンツを見ることができない、といったことが無いように、パーソナライズサーバーへのリクエストがタイムアウトしたり、エラーが返ってきた場合は、特定の決まりに基づき別途コンテンツを表示するようにしています。
このようなシステムを構築して大きなトラブルもなく、無事パーソナライズシステムをリリースできました。しかし、今のシステムだとA/Bテストなどを行い、ロジックのアップデート繰り返していくときに、変更しないといけない箇所が多くミスが発生しやすいです。これを解消するのが今後の課題だと思ってます。

まとめ

ARINEでパーソナライズに使用しているシステムについて紹介させていただきました。
機械学習のシステムはシステムを構築してサービスにのせてからが本番だと思っていて、そこからどう改善を回して、より効果的なロジックを模索していくのが、大変でもあり面白くもあるなーと日々感じています。また、このサイクルを速く回すためには、デプロイシステムなどのパイプラインをしっかり整備することが大事だと痛感しました。
この記事が誰かの役に立てたら幸いです。最後までみてくださってありがとうございました。