レコメンド/検索の大規模展開に関する課題と解決策

藤井亮太 氏(以下、藤井):「レコメンド/検索の大規模展開に関する課題と解決策」ということで発表させていただきます。

まず自己紹介です。先ほどの石垣と同じプラットフォーム事業本部に所属しており、カスタマーエンゲージメント部でレコメンドチームと検索チームのプロダクトオーナーをやっております。

入社してからやったこととしては、2016年にDMMに入社した後に、はじめはビッグデータ部のエンジニアとしてセグメンテーションエンジンの開発をやったり、ワークフローエンジン、あとはBIツールの導入を行っていました。2018年より、レコメンドと検索のPOを行っています。

本日のアジェンダなんですが、まず、レコメンドと検索の利用状況を説明したあとに、レコメンドにおける課題としてABテストの効率化がありましたのでそのご紹介と、検索については、ログを活用した大規模リファクタリングについてお話ししたいと思います。

はじめにレコメンドと検索の利用状況についてです。

DMMでは幅広いサービスを展開しています、という資料です。レコメンドがどれくらい使われているかというと、DMMの全40以上のサービスのうち10サービス、レコメンドの種類として167種類。埋め込まれている箇所としては400ヵ所以上と、幅広いところで使われております。

一方、検索は14サービスで利用されていて「検索+各種リスト」ということで、リストってなんだ? というと、例えばこういった電子書籍サービスは、トップページにある人気の作品や2019年春アニメなど、こういったところがリストになってます。

そういったような大規模展開をしている中で、データ活用によってそれぞれのプロダクトを改善しました、という話をします。

ABテストの効率化

まずレコメンドなんですが、レコメンドのABテストの効率化ということで、レコメンドの課題としては、先ほど紹介した通り導入は着実に進んでいるんですが、1個1個のレコメンドを見たときに、KPIが伸び悩んでいました。

それに対していくつか施策をABテストで効率的に実施して、どんな方向で改善すればいいのかを探索するのが課題でした。その中で効率的に実施するために行ったことは3つあります。

「オフラインでの評価で品質を担保」する。次に「alias機能を用いたABテストの展開」。最後に「効率的なABテストの比較」です。

その前に、レコメンドについて本当に簡単に仕組みについてご紹介します。

レコメンドの仕組みなんですが、特定の対象のアイテムと呼び出しのレコメンド種類を指定してAPIをコールします。そうするとレスポンスをしてレコメンドのアイテム群と、効果測定を行うためのトラッキングIDを付与して返却するかたちになっています。

レコメンドについて大々的に登壇をしておりまして、いくつか資料もありますので、こちらもあとでご参照ください。

オフライン検証

実際にABテストの効率化のためにやったことなんですが、1個目がオフライン検証です。

「オフライン検証とはなんだ?」というと、ユーザの商品に対するレーティングや、購買などの利用履歴を用いた評価方法になります。これをすると何がいいかと言うと、リリース前にそのレコメンドを評価できます。

DMMではどんなオフライン評価を用いてるかというと、大きく3つあります。

1個目が「リコール/プレジション」ユーザーの過去の行動を正解と仮定した場合に、そのレコメンドがどれくらいの再現率を持っているか、適合率を持っているかです。

こちらも詳しい資料はありますが、本日は時間がないので割愛させていただきます。

次が「顔ぶれ一致率」ということで、レコメンドのABテストをやる際に、既存のレコメンドに対して新しいレコメンドはどれくらい候補が変わっているかを一致率として、評価軸に入れています。

最後が「カバレッジ」で、そのレコメンドを扱っているサービスの全商品に対して、今から打とうとしているレコメンドがどれくらいのカバレッジを持っているのかを評価しています。

この3つを評価することによって、リリース前に一定の品質を担保するってことを行っていました。

alias機能とABテスト

次にalias機能とABテストです。aliasというレコメンドでの機能がありまして、同一のインプットに対して同一のアイテム群を返して、異なるトラッキングIDで返却する仕組みです。

どういうことかと言いますと、例えば商品の詳細画面と購入画面があったときに、そこに対して同じレコメンドを表示したいということがあったりします。

そのときに同一のアイテムIDが与えられたら同一のレコメンデーションアイテム群を返却して、それぞれを個別にトラッキングできるように異なるtracking_idを送るということになります。

これによって何を得られるかというと、同一のレコメンドを複数箇所で利用する際に、それぞれ個別で効果測定を行える仕組みになってます。

次にABテストです。

こちらについては同一のインプットの呼び出しに対して、異なるロジックで生成したアイテム群を異なるトラッキングIDで返却する仕組みになっています。

こちらが図になっているのですが、レコメンドのABテストにおいて、例えばロジックAは80パーセント、BとCは10パーセントずつといったかたちで実施する際、同一のインプットに対して異なるロジックで生成してアイテム群を返却して、その際に異なるトラッキングIDを付与するという仕組みがABテストになっています。

まとめると、異なるロジックで生成したレコメンドを設定した割合で出し分けて、それぞれの効果測定をする仕組みとなっています。

この2つを組み合わせるとどうなるかというと、こうなります。

同じレコメンドやABテストのレコメンドを同時に実行している際に、商品の詳細画面や購入完了画面で、それぞれ個別に「このレコメンドがどのような効果を出しているか」みたいなことが一発でトラッキングできる仕組みになっています。

まとめると、それぞれのロジックのレコメンドを異なるコンテキストで実施したときに同時に効果を検証する仕組みとなっています。

効率的なABテスト比較

次に効率的なABテストの比較についてですが、先ほど紹介した通り、aliasとABテストによって短期間でレコメンドのログを取得可能になりました。ですがこれを効果検証するにはABテスト数×aliasとなってしまって、手作業で集計を行うのは非常に非効率です。

それに関して、関連するレコメンド、先ほどのABテストやaliasといったものを一括で比較可能なダッシュボードを作成して分析を効率化しました。

こちらはイメージなのでわかりずらいですが、大元のレコメンドがこのあたりにあって、それに対してどんなABテストをやっていたり、aliasを発行しているパターンみたいなときに、それぞれを横串で比較できるようなダッシュボードになっています。

こういったABテストの効率化を行うことで、短期間で複数のレコメンド施策を実施可能になりました。

もともとは月に1本ぐらいしかABテストが打てなかったんですが、2週間で5本ほど打てるようになったり、効果の薄い施策の早期発見と停止もできるようになりました。「リリースして1週間でこの効果は悪いよね」ということでABテストを停止することも可能になりました。こちらがレコメンドのABテストの効率化になります。

ログを活用した大規模リファクタリング

続きまして、ログを活用した大規模リファクタリングについて説明したいと思います。

これはざっくりとした検索システムの概要です。

検索エンジンとしてSolrを利用してまして、それに対して参照するものが2つ。検索ライブラリと検索のAPIですね。検索のライブラリはいろいろなサービスで使われていて、検索APIについては新しめのサービスで利用している状況です。

この中で課題だったのが、主要なコンポーネントのSolrのバージョンが4.10ということで、現在の最新のバージョンが8.1なのでだいぶ遅れている状態になっていました。これを何とかバージョンをあげて新機能を利用したり、性能の改善を行いたいという課題がありました。

あとはSolrが複数箇所から参照されてしまっていて、無停止でのバージョンアップや置き換えが困難であるという状況でした。

そこを打破するために参照元を集約して、Solrの切り替えなど、コントロールを容易に行えるようにしたいというのが、本来やりたいことです。

1つ目の方針として、検索ライブラリを使わずに検索APIの向き先を変えればいいのではないかと考えましたが、こちらは実施できませんでした。

なぜかというと、検索ライブラリは多くのサービスから利用されているために参照先を切り替えることが困難であるということがありました。

その次に取った方法なんですが、このライブラリを活かしつつ、ライブラリから検索APIを参照するかたちに組み替えました。検索ライブラリからサーチAPIを参照するかたちに組み替えて、Solrの参照元を集約すると。

これを行うことにあたってまた課題が発生していました。この検索ライブラリはどういった構成かというと、1ファイルで4,000行から6,000行ぐらいあるようなファイルが24ファイルで、中にはメンバ変数が30から40個、メソッドが100個みたいな。

けっこうやばい感じのファイルを含むライブラリでした。

これをそのまま何も考えずにリファクタリングするわけにはいかないので、ログベーステストを利用して検索ライブラリのリファクタリングを実施しました。

ログベーステストの流れとメリット

ログベーステストの流れなんですが、全体像としてこのようになっていて、初めにユーザからログインか検索システムが呼ばれたときにコールされたメソッドやその引数、あとはそのメソッドによって変数がどう変わったかをすべてロギングしておきます。

それをビッグデータ基盤に蓄積して、ログデータをテストケースに変換するスクリプトを作って、テストケースを作りました。それによってその挙動がテストケースによって担保されるので、振る舞いを変えることなくリファクタリングを実施しました。

このログベーステストのメリットなんですが、自動生成した大量のケースにより網羅性の高いテストを実施できるというメリットと、ユーザの利用が多いコードがテストできることです。ユーザがよく使っているということは重要なコードなので、そういった部分がたくさんテストできます。

あとはこれも大きなメリットなのですが、仕様がわからないコードをテストできます。先ほど紹介した通り、かなり巨大で複雑なライブラリになっていたので、仕様をすべて厳密には把握できない状態でもユーザの挙動から、あるべき姿をコードとして落とし込むことでテストが実施できます。

こういったログベーステスティングを取り入れたことによって、だいたい2名の担当者で他に割り込み作業も行いつつ、4ヵ月でリファクタリングを完了させることができました。また、リリースしたあとに大きなトラブルも発生していません。

まとめです。

レコメンドのほうなんですが、ユーザのログデータを効率よく収集できる仕組みを構築して、ABテストのプロセス全体を効率化しました。検索は、ユーザーの操作をトリガーにしたシステムログを活用して、大規模なリファクタリングを効率的に実施することができました。

最後に、DMMは大規模プロダクトの価値向上とかリプレースなど、さまざまな課題にチャレンジできる環境になっています。興味ある方は、ぜひこの後の懇親会で細かい部分までお話できればと思いますので、奮ってご参加くださいませ。

以上になります。

(会場拍手)