はじめに
こんにちは。データシステム部/推薦基盤ブロックの佐藤 (@rayuron) です。私たちはZOZOTOWNのパーソナライズを実現する推薦システムを開発・運用しています。推薦システムごとにKPIを策定していますが、データの欠損やリリース時の不具合によってKPIが意図しない値を取ることがあるため定常的に確認する必要があり、これをKPIのモニタリングと呼んでいます。
先日、推薦システムの実績をLookerでモニタリングするというテックブログで推薦システムのKPIをモニタリングする方法を紹介しましたが、運用していく中でいくつかの課題が見えてきました。本記事では、より効率的かつ効果的なKPIのモニタリングを実現するための取り組みについて詳しくご紹介します。
改善の背景と課題
背景
推薦基盤ブロックでは、ZOZOTOWNのトップページやメール配信などにおいて、ユーザーに最適なアイテムを推薦するシステムを開発・運用しています。弊チームで運用している推薦システムの具体例は以下の記事を参照してください。
techblog.zozo.com cloud.google.com techblog.zozo.com
元々、KPIのモニタリングはLookerを用いて各指標の変化を確認するか、Looker Studioで作成されたダッシュボードはあるが定常的にモニタリングされていない、というどちらかの状態でした。
課題
冒頭で紹介した推薦システムの実績をLookerでモニタリングするで挙げた様に、既存のモニタリングシステムには以下のような課題がありました。
- トレンドを考慮した異常検知が不可能
- モニタリングの設定が面倒
- アラート対応フローが不明確
- サマリの定期配信が形骸化
トレンドを考慮した異常検知が不可能
これまで運用されていた異常検知は、固定の閾値でKPIの異常を判定していました。固定の閾値では、時系列のトレンドを捉えきれず、KPIの異常値を正しく検知できませんでした。例えばZOZOTOWNではZOZOWEEKなどのセールイベントが定期的に開催されているため、こういったイベントによるKPIの変化を考慮した異常検知が必要でした。
モニタリングの設定が面倒
以下で示す様にモニタリングのための設定はYAMLファイルを使って管理していましたが、指標ごとに閾値を設定する必要があり非常に手間がかかっていました。閾値設定は担当者の主観的な判断に基づいて行われることが多く、客観的な根拠に基づいた設定が難しいという問題もありました。
- lookml_dashboard_id: kpi_monitoring_shoes::shoes_recommendation alerts: - lookml_link_id: visit/open cron: "0 10 * * *" name: mail_result.visit_per_open # <- 指標ごとの設定が面倒 lower: 0.1 # <- 下限閾値の設定が面倒 upper: 0.5 # <- 上限閾値の設定が面倒 - lookml_link_id: recommend_generation cron: "0 10 * * *" name: generation # <- 指標ごとの設定が面倒 lower: 0.01 # <- 下限閾値の設定が面倒 upper: 0.1 # <- 上限閾値の設定が面倒 field_name: member.age_tier field_value: "19 to 22" ...
アラート対応フローが不明確
KPIの異常値を検知するアラートが発生した場合、担当者はアラートがなぜ引き起こされたのかを確認し適切な対応をする必要があります。しかし明確な手順が定まっていないため、対応者がシステムを作った人に限られてしまうという属人化の問題がありました。
サマリの定期配信が形骸化
メール配信数やクリック率などの数値が羅列されたサマリをSlackで定期配信していましたが、次第に形骸化し最終的にはほとんど誰も目を通さなくなってしまいました。
課題解決のアプローチ
これらの課題を解決するため、以下のアプローチを採用しました。
- 異常検知の自動化
- アラート対応フローの整備
- ダッシュボードを見る会の運用
それぞれのアプローチについて詳しく説明します。
異常検知の自動化
KPI集計パイプラインの構築
これまでKPIの集計はスプレッドシートやBigQueryのスケジュール実行で行っていましたが、Vertex AI Pipelinesへ移行しました。弊社ではVertex AI Pipelinesの実行・スケジュール登録・CI/CD・実行監視等をテンプレート化した、GitHubのテンプレートリポジトリを運用しているため、このリポジトリを利用することで簡単にVertex AI Pipelinesの実行環境を導入できます。KPI集計のジョブは以下のように構成されています。
パイプラインではKPIの集計に加えて、後続のモニタリングのジョブのためにデータを整形します。集計されたKPIは以下の形式でBigQueryに保存されます。
日付 | CTR | CVR |
---|---|---|
2024-01-01 | 0.2 | 0.3 |
2024-01-02 | 0.3 | 0.4 |
2024-01-03 | 0.4 | 0.3 |
モニタリングパイプラインの構築
KPI集計と同じくVertex AI Pipelinesを使用して異常検知システムを構築しました。KPIをモニタリングするパイプラインは1日1回、KPI集計が完了した後に実行されます。以下のようなパイプラインが構築されています。
異常検知には、次のセクションで説明するProphetと呼ばれるライブラリを使用し、検知した指標名やグラフと一緒にSlackメッセージを通知します。
Prophetの採用
私たちは、異常検知を自動化するためにProphetを採用しました。Prophetは単一の時系列データでトレンドを考慮した予測と不確定区間の計算ができるため、これを異常検知に利用します。具体的にはKPI集計パイプラインで保存されたBigQueryのテーブルにおいて、最新の日付の不確定区間を計算し、測定された値が不確定区間の外側にある場合、異常値として検知します。
キャンペーンやセールなどのイベント情報をモデルに組み込むことで、イベントの影響を考慮した上で異常検知ができます。また、イベント情報をProphetに与えることで、イベントを考慮した異常検知が可能になります。以下はイベント情報をProphetに与える例です。
playoffs = pd.DataFrame({ 'holiday': 'playoff', 'ds': pd.to_datetime(['2008-01-13', '2009-01-03', '2010-01-16', '2010-01-24', '2010-02-07', '2011-01-08', '2013-01-12', '2014-01-12', '2014-01-19', '2014-02-02', '2015-01-11', '2016-01-17', '2016-01-24', '2016-02-07']), 'lower_window': 0, 'upper_window': 1, }) superbowls = pd.DataFrame({ 'holiday': 'superbowl', 'ds': pd.to_datetime(['2010-02-07', '2014-02-02', '2016-02-07']), 'lower_window': 0, 'upper_window': 1, }) holidays = pd.concat((playoffs, superbowls)) m = Prophet(holidays=holidays)
設定の簡素化
Prophetを使用することで動的な閾値を設定できるようになります。さらに、これまでは指標単位でモニタリングの設定を記述していましたが、テーブル単位で記述することによって設定が簡素化されました。具体的には以下のようなYAMLファイルで記述される設定を使用します。
kpi_monitoring_ma_personalize_shoes_parameters: monitor_table_id: 'project_id.dataset_id.table_id' date_field: send_date freq: D expected_interval_days: 2 plot_periods: 7 start_date: '2023-01-01' exclusion_dates: - '2024-06-26' exclusion_fields: - campaign_id dashboard_link: https://lookerstudio.google.com/dashboard interval_width: 0.99
各項目の説明は以下の通りです。
パラメータ | 説明 |
---|---|
monitor_table_id | モニタリング対象のBigQueryのテーブルID |
date_field | 日付列名 |
freq | モニタリングを実施する頻度 |
expected_interval_days | 意図した集計間隔 |
plot_periods | 通知時にx軸にプロットする期間 |
start_date | モニタリングを開始する日付 |
exclusion_dates | モニタリング対象から除外する日付のリスト |
exclusion_fields | モニタリング対象から除外する列名のリスト |
dashboard_link | ダッシュボードのリンク |
interval_width | 不確定区間の幅 |
アラート対応フローの整備
アラート対応フローを整備することで、対応の属人化を解消しました。このワークフローはアラートが発生した場合、担当者がどのような手順で対応すればいいのかを明確に示すものです。以下のようなアラート対応のワークフローを設定しました。以下で具体的に説明します。
アラートが発生した時、パイプラインは以下のような画像を含むSlackメッセージを通知します。
通知を受け取った後は具体的な原因を調査します。以下の表に示す3つの原因に分類し、それぞれの原因に対する対応方針を明確にしました。
原因 | 対応 |
---|---|
データ | データの欠損や品質の低下が原因と考えられる場合、データ連携の確認やデータ品質の改善を試みます。 |
モデル | モデルの誤動作やパフォーマンスの低下が原因と考えられる場合、モデルのチューニングを行います。 |
アラートの設定 | アラートの設定に誤りがある場合や指標の分散が大きく予測が不確実な場合は、アラート設定の見直しを行います。 |
異常値をProphetの学習データから除外するため、異常値として捉えた日付をexclusion_dates
として設定に追加します。これまでのアラートの対応内容はドキュメント化し次回同様のアラートが発生した際、参照できるようにします。
ダッシュボードを見る会の運用
これまでご紹介した異常値の自動検知の取りこぼしを防ぐため、チーム全員でダッシュボードを定期的に確認するミーティングを運用しています。先述の通り、元々行っていたサマリの定期配信は強制力のある方法ではなかったため形骸化しました。そこでSlackでのサマリの定期配信は廃止し、週1回ダッシュボードを見る会を開催することで積極的にKPIの状況を把握する体制を構築しました。
ダッシュボードを見る会の進め方
ダッシュボードを見る会は毎週1回20分のミーティングで以下の手順に従って進行します。
- ファシリテーターを中心にダッシュボードを見て、先週から ±N% 以上の変化率か、グラフの形状が大きく変わったかを確認
- 大きな変化がある場合、祝日、イベント、障害が発生していないか等原因を調査
- 時間内に原因解明が出来なかった場合は、ファシリテーターが問題をチケット化し調査タスクをバックログへ積む
具体的には以下のようなダッシュボードをモニタリングしています。
効果
今回の取り組みによって、以下の効果が得られました。
動的な閾値で異常値を検知できるようになった
Prophetを用いることで季節変動やイベントの影響を考慮した動的な閾値を設定できるようになりました。これにより誤検知を減らし、真の異常値を検知できるようになりました。
モニタリングの設定が簡単になった
これまで指標ごとに閾値を設けモニタリングを行っていましたが、閾値を自動で決めることやテーブル単位で設定項目をまとめることで設定が簡素化されました。
アラート対応の属人化の解消
アラート対応フローを整備しワークフローに従って対応することで、担当者の知識や経験に依存せず誰でも対応できるようになりました。
異常値の取りこぼしの削減
ダッシュボードを見る会を通してKPIのトレンドや全体的な傾向を把握できるようになりました。これにより自動検知での異常値の取りこぼしを削減しました。6月中旬から9月中旬まで運用した中で、データの欠損や集計定義の異常等に関する5つの異常値を検知しました。
課題と展望
偽陰性の防止
現在どこまでを異常値として捉えるかをinterval_widthというパラメータで調整しています。KPIモニタリングシステムを運用してみるまでどこまでを異常値として捉えるかは運用者であっても不明な場合が多いためこのパラメータには一定の初期値を設定します。一方でKPIモニタリングシステムは異常値でないと判定したが、実際には異常値であった場合を検知できないというシステム特有の問題があります。定期的にinterval_widthを調整することやダッシュボードを見る会での議論を通じて偽陰性を防止する取り組みを行うつもりです。
異常検知モデルの精度のモニタリング
KPIをモニタリングする異常検知モデルの精度が低下していることに気づくためには、異常検知モデルのメトリクスをモニタリングする必要があります。また、この際にはモニタリングの連鎖という問題に上手く対処する必要があると考えています。
アラートの原因分析の自動化
KPIのモニタリングシステムを運用していて一番時間がかかるのは、人によるアラートの原因分析です。データの欠損やメールの配信数制限には指標の変化にパターンが存在するので、アラートの変化に対応して原因の候補を自動で提案する仕組みを構築することで、アラートの原因分析の時間を短縮できると考えています。
おわりに
本記事では推薦システムのKPIのモニタリング自動化と運用体制の整備についてご紹介しました。今後もより効率的で効果的なモニタリングシステムの構築を目指して、改善を続けていきます。
ZOZOでは一緒にサービスを作り上げてくれる方を募集しています。ご興味がある方は以下のリンクから是非ご応募ください!