論文読み:Monolith

元論文
https://arxiv.org/pdf/2209.07663.pdf

bytedance社のレコメンドエンジンに関する内容。
Deepなモデルをプロダクション環境で扱うためのモデルの学習・更新の方法やデータの管理方法の工夫などをまとめている。

全体のアーキテクチャ

特徴量のメモリ削減

モデルのパラメータはdenseとsparseの二つにカテゴライズされる。
dense:DNNの重みや変数
sparse:embedding tableなど

1. ハッシュ関数の工夫
新しいIDの増加に伴いパラメータの管理に対するコストが高くなる。
その問題を防ぐため、スパースなパラメータについてTensorflow Variableのような衝突がなく効率の高いハッシュテーブルを用意する。具体的にはカッコウハッシュを用いる。

2. ヒューリスティック
分析の結果、下記のことがわかっている。

  • 滅多に出現しないIDの情報はモデルの改善に寄与しない
  • 過去の情報はほとんどモデル改善に寄与しないし、そういったユーザーはもはや訪問しない。

こういった背景により、embedding tableに挿入する前に以下を実施

  • 出現頻度に応じたフィルター
  • 確率的なフィルター
  • IDのexpire timeの設定

オンライン上の学習

two stageで実現する。

  • batch training

ミニバッチ単位でパラメータ取得->更新->更新後パラメータ返却

  • online training

リアルタイムデータをon the flyで処理して更新。
train PSが serve PSに周期的にパラメータを同期する

  • ストリーミングエンジン

kafkaを利用。
ユーザーアクションとFeatureでパイプラインを分けておく。
Flinkを活用してユーザーアクションとfeatureをJoinするJobをかましておく。
最終的に学習データをkafkaキューに流し、オンライン学習の場合はそのデータをそのまま使い、バッチの場合はダンプしてHDFSに格納。

  • online joiner

ログが順不同で入ってくるので、それぞれのリクエストに対してユニークなキーを使うことでユーザーアクションとFeatureを正しくペアにすることができる。
ユーザーのアクションのラグ(提示したアイテムを購入するまでに数日を要するかもしれないなど)に対応するにはin-memory chacheだけでは対応できない。
この対応のためon-diskのKVSを設置してそちらに格納しておく。
最初にin-memory chacheを参照して、キャッシュに乗っていなかった場合にはKVSを参照するようにしている。
その後ネガティブサンプリングをして学習データとしてkafkaに流す。

  • パラメータ同期

リアルタイムログを使って更新したパラメータを同期するためのチャレンジ。

  • パラメータ更新を推論サーバーを止めることなく行うこと
  • 新しいモデルを推論に持っていく際のメモリサイズと帯域の問題

基本的には小さい範囲のタイムレンジが与えられた時に、小さな部分集合のみを対象にして学習とembeddingsの更新を行うようにする。
疎なembeddingsを頻繁に更新し、密なパラメータの更新頻度を下げる。

  • 耐障害性

一般的には、モデルのスナップショットを定期的に保存、失敗の際に最新のスナップショットから回復するのが考えられるが、トレードオフがある。
・モデルの品質
頻度が高いほど直近の情報を反映できる
・計算コスト
メモリ使用量、disk I/Oがかかる。
バランスとして、現状は全てのtraining PSでdailyでスナップショットを取る方針としている。

評価

  • HashTable

movie lensとプロダクション環境のデータセットを用意。
movie lensではuser,itemのIDそれぞれをMD5でハッシュ化し、より小さいスペースにマッピングしたものを用意する。
学習モデルはDeepFMを使い、評価はAUCで行う。
プロダクション環境では、baselineとしてembeddingテーブルサイズを半分程度に圧縮するように新しいテーブルを用意する。
実際に本番に入っているモデルを用いてAUCで評価する。
実際に比較すると衝突が発生していないデータの方がAUCが良い傾向になっている。
特にトレーンングエポック数が増えるとAUCの増分が増える傾向がある。
また、プロダクション環境において、モデルの経年劣化に対してロバストであることがわかる。

  • リアルタイムなオンライン学習で重要なものは何か

(1)モデル更新頻度
1週間のデータセットを5day-2dayに分割。
5dayのデータをバッチトレーニングとして利用し2dayをオンライン学習に利用する。
オンライン学習はそれぞれデータを10,50,100(実時間における更新頻度5hr,1hr,30minに対応)に分割し、それぞれでオンライン学習->評価を繰り返し性能を比較する。
比較の結果、sync頻度が高い方がAUCが良い結果になっている。
更新頻度にほぼ線形にAUCが改善しているように見える。

(2)本番テスト
オンライン学習をした場合とバッチ学習のみの比較。
ライブテストにおいてもAUC改善がおよそ15~18%の改善となっている。

実際に、100,000IDの1024次元のembeddingを分単位で更新しても400MB/min程度のデータにしかならない。また、密なパラメータは先述の通りdailyかつ最もトラフィックが小さい時間に更新するようにしている。

また、スナップショットについて、頻度が高い方がいいかと思っていたが、1日単位であってもほとんど性能に変化がなかった。

推薦システム実践入門読んだので簡単に所感

書くときは頑張って書く。

以前会社で同僚だったhttps://twitter.com/zr_4から献本してもらった推薦システム実践入門を読んだ。

www.oreilly.co.jp


章立ては以下のようになっている。
1章 推薦システム
2章 推薦システムのプロジェクト
3章 推薦システムのUI/UX
4章 推薦アルゴリズムの概要
5章 推薦アルゴリズムの詳細
6章 実システムへの組み込み
7章 推薦システムの評価
8章 発展的なトピック

推薦システムの書籍だとモデルの部分にフォーカスを置いたものが多い印象だけど、この書籍は4,5章でモデルの話をしている以外ではあまり触れられていない。
むしろ推薦システムをどのような目的で導入するべきなのか、どのようにシステムを作るべきなのか、どのように評価して改善をしていくのか、そういった推薦システムの基本的な部分を広く網羅したものになっている。

そういった意味では、いま推薦システムを作っているエンジニアだけでなく、始めて推薦システムについて知りたい人(エンジニアだけでなく企画職の方でも)が最初に読む本として良さそうに思う。

使われているモデルの理解を深めるのであれば下記の方が良いかもしれない。

www.kyoritsu-pub.co.jp

一応レコメンドシステムを担当している人間ではあるので、今回は5章は軽く目を通して、他の章をメインに読んだ。
全体的に、学術書のような堅苦しい内容というよりは、TechBlogを読んでいるような感じで読みすすめることができるので、(好き嫌いあるかもしれないが)読みやすいと思う。

個人的に良いなと思った章は3章で、推薦システムの利用シーンのケースとそれに対応するアプローチが網羅的に書かれている。
こういう内容をきれいにまとめてくれているものはなかなか無いので、自分でレコメンドシステムを作らないで他社製品を使うような人であってもかなり参考になると思う。
著者がアルゴリズム部分だけでなく推薦システムの広域な領域に知見があるからこそ書ける内容という感じ。

他にも6章、7章はレコメンドをサービスに届けるために必要なシステム周りの話と評価方法についてまとまっていて、このあたりに知見が無い人にとってはとても参考になりそう。
また、各章においてより詳しく知りたい場合の書籍がレコメンドされており、そういった気遣いもありがたい。

個人的には6章の実システムへの組み込みはもっと深堀りしてもいいかなとか思う部分もあったりするけど、推薦システムについて知りたけれはまずこの本を読んでみて、興味があるトピックについて更に別の書籍や文献で深堀りしていくというのが良さそうだった。

献本ありがとうございました!

GW読んだ本

すでに年明けの目標は達成できないでいる。

本を読むときについつい先頭から丁寧に読んでしまう。とてつもなく効率が悪い。
本を読むのが下手なのでコツが知りたい。

チームトポロジー

GW前からのんびり読んでいたチームトポロジー
pub.jmam.co.jp


「システムを設計する組織は、その構造をそっくりまねた構造の設計を生み出してしまう」というコンウェイの法則を踏まえて適切なソフトウェア開発組織を設計するという内容の本。
単純にチームを疎結合にしようとかではなく、以下の4つのチームと3つのインタラクションモードを定義して、それぞれの依存関係を減らして目標に向かって進む組織を作る。

チームの種類
  • ストリームアラインドチーム

価値のある単一の仕事のストリームに沿って働くチーム。ベースとなるチーム。

  • プラットフォームチーム

一部内部サービスをPFとして提供することでストリームアラインドチームを助ける。

  • イネイブリングチーム

特定の領域のスペシャリストから構成され、ストリームアラインドチームの能力ギャップを埋めるのを助ける。

  • コンプリケイテッド・サブシステムチーム

専門知識が必要となるパーツの開発・保守の責任をもつ。

インタラクションモード
  • コラボレーション

チーム間で密接に協力して作業する。

  • X-as-a-Service

最小限のコラボレーションで提供・利用する。

障害を取り除くために支援をしたり受けたりすること。

個人的にはこの組織構成の考え方よりは、チームの認知負荷を制限して、チーム間のコミュニケーションを明確にするという解きたい目的の部分の納得感とともに実態として難しさを感じるなという印象があった。

この形のほうが成果が出るという期待はあるし、おそらく当事者もこちらのほうが成果が出るという理解はできると思うが、認知負荷の制限の進め方を間違えると認知機会を奪われているというふうに考えてしまうことが結構ありそうな気がする。

特に専門家チームがストリームアラインドチームをサポートする体制になったときに、それぞれの役割と考え方を明確に理解させておかないと、「このチームはいい所取りをしている」、「このチームだけ新しいことをやっている」といった軋轢を産むことになりかねないなぁと思った。

また、いろんなことを知っていたい、広く裁量を与えられたいという考えは持ちがちだし、そういった人が評価されやすくなってしまいがちなので、配置の意義から成果報酬の考え方までが一貫していないと機能しないんだろうなと思う。

この辺の話はこの書籍の考え方云々というより組織マネージメントの課題という感じだけど、機能する組織と個人のやりがいみたいなところを完全につなげるのは難しいなというところを改めて感じた。

ジョブ理論

会社の上司から薦められた一冊。

www.amazon.co.jp

イノベーションにおいて大切なのは、どうやってプロダクトの質を高めるのかを考えるのではなくて、ユーザーがどんなジョブ(用事、仕事)を片付けたくてそのプロダクトを雇用するのかであるという主張がされている。

相関関係から何かを見出そうとするのではなくて、因果関係のメカニズムを踏まえてイノベーションを成功させるという考えのもと、少量のインタビューデータなどを深く掘り下げて、ユーザーがどんなジョブを解決するためにそのプロダクトを活用したのをかを様々な事例とともにまとめている。

最初に出てくるミルクシェイクをなぜ購入するのかを掘り下げた内容などは非常に面白い。

プロダクト開発においてそれが十分に優れているかを追い求めすぎると永遠に完成が見えなくなるが、こういうジョブを解決したいユーザーにとって十分に役に立つか、という問いであれば答えが得られやすいというところも納得感があった。

日頃からデータを扱う立場からすると大規模なデータからはイノベーションを生まれなさそうな旨の指摘が結構されており、ビッグデータイノベーションをなかなか産めていないのはそのとおりだよなと同調する部分もあった。
あと人が作ったデータは、人がデータから出した結論には大いにバイアスがあるとかそのへんは難しい課題だなと思わされた。
そう思うと会社の分析部隊を事業から独立させた立場においたり外部から雇うのは割と理にかなっているのかもしれない(それでも会社のデータを扱う以上はバイアスを取り除くのは不可能だけど)と思ったりもした。

余談だけど文中でamazonを優れている例としてあげていたが昨今のamazonはそうだっけ...と思ったところもあったりした。

年明け

2022年になってしまった。

2020年末のブログでこんなことを書いていた。
・毎月1本はブログを書きたい
・社のtechblogを書きたい

達成状況はというと
・ブログは月2回投稿した月もあったが3月と4月、11月と12月が未達
・techblogはタイミングの問題もあって2022/03あたりまでには出せそうだが未達

ということでどっちも未達。

なので今年も一旦同じ目標を組んでみようと思う。
追加で書籍、論文などを読む頻度は上げていきたい。

特に年末を中心に仕事が忙しすぎて自分のことに時間をあまり使えなかったので、今年は立ち回りを含めてうまくやっていきたい。

ちびちび読み進めていたEMPOWEREDをようやく読み終えた。
pub.jmam.co.jp


プロダクトマネージャーの仕事は解決するべき課題を提示して、チームがその課題を解決できるように環境を整えてあげること、というのは納得感があるし、プロダクトマネージャーに限らず管理職の立場としてもできる限りそうするべきなんだろうという気持ちになった。
個人的に一番難しいのはメンバーへの動機づけで、なんでそれをやるのかについて自分なりには説明しているつもりでも、作業してもらっているメンバーが意義を理解できていなかったり、同調していなかったりという印象を感じることが多いので、ここにもっと時間を割か無いといけないなと思わされた。
一方、一部自分の中で意識的にやってきていたことが好例として書かれていたりもしてそのあたりはやってきたことが間違いないと確信を持てたし、今後も続けていきたい。

定期的に読み返して自分の行動を振り返るのにもいい本だなとおもった。

随分前にLearn or Dieについても読了した。
www.kadokawa.co.jp

書籍の中からなにか学びが得られる、というたぐいの本ではないけど、優れた技術集団の考えかたは理解できた。
研究開発の「手段」としてのビジネスという考え方で会社として成り立つことができるのがとんでもないなと思った。

今年も興味の赴くままに知識を得ていきたい。

メモ:EX3 : Explainable Attribute-aware Item-set Recommendations(RecSys2021)

論文
https://dl.acm.org/doi/pdf/10.1145/3460231.3474240

正直こちらのWantedlyさんの参加報告見れば十分説がある。
www.wantedly.com

概要

これまでのレコメンドは関連するアイテム集合を提供することにフォーカスしていたが、ユーザーの嗜好に合わせた重要な属性を抽出し、それに合わせてアイテムセットを提供することで、より説明力が上がり購買につながるはず。
今回は過去のユーザー行動から重要な属性と、それに一致するアイテムの集合を生成するアプローチ(Extract-Expect-Explain Framework)の提案。

手法

問題設定としては、seedとなるアイテムと、そのアイテムと各属性に対するスコアのペア、グループ数が与えられた時に、その数分の説明可能なグループ(属性とそれに対応するクリック、購入されやすいレコメンドアイテムの集合)を出力すること。

論文のタイトル通り、Extract-Expect-Explainという3つのステップが行われる。
f:id:A_Koide0519:20211010144715p:plain

Extract-Step

個々のアイテムをd次元空間にマッピングするStep。
まずアイテムのタイトルなどのメタ情報を用いて特徴量を生成する。
続いて任意のアイテムpに対して関連性のあるアイテム集合N_pとの距離が近くなるようにアイテム空間を定義する。
なおN_pはCo-view(レコメンドなどを通じてseedアイテムと同時に見られている状態)かつView-to-buyされたアイテムからCo−buyアイテムを除いたものと定義する(ポジティブデータ)。
※ユーザー行動としてアイテム間を比べて買ったということを考えると妥当と思われる
また、ネガティブデータとしてView-to-buyのアイテム集合から|N_p|分アイテムをランダムサンプリングするN_p^-
最終的にエンコーダーはhinge lossを用いて、すべてのpに対してpN_pの距離がより近くなるように、pN_p^-の距離が遠くなるように学習される。
このエンコーダーを通してembeddingされたアイテムについて、各アイテム毎に距離の近いTopN件のアイテムをレコメンドの候補集合とする。

Expect-Step

seedのアイテムqに対して、クリックや購入に結びつくアイテム候補pを属性aのもとに学習する。
今回はAttribute Differentiating Networkというニューラルネットワークを提案している。
seedとなるアイテムと、Extract-Stepで抽出した候補アイテムに対して、そのアイテムペア間の関連度と、アイテムペアにおける属性の重要度スコアを同時に算出できる仕組みとなっている。
f:id:A_Koide0519:20211012151845p:plain

入力はExtract-Stepで抽出したアイテムのベクトル、onehot化された属性データ、アイテムのタイトルやカテゴリから抽出した文字ベクトル。
(a)のvalue-difference moduleは、アイテムq,pの属性a_jに対応する文字ベクトルの値の差異が計算される。
(b)のattention-based attribute scorerでは、q,pをconcatして低次元空間にマッピングしたベクトルと、(a)で作ったベクトルを用いて、pの各属性ごとの重要度を算出する
(c)のrelevance predictorでは、q,pをconcatして低次元空間にマッピングしたベクトルと(b)のアウトプットとして計算された全属性の情報をまとめたベクトルを使って、アイテムqpの関連度のスコアを算出する。

Explain-Step

seedのアイテムqに対して、K個の属性が付与されたグループを作成し、各アイテムを適切なグループに割り当てる。
1.Extract-Stepで候補アイテム集合C_qを取得
2.すべての候補アイテムに対して、Expect−Stepの候補アイテムp_iの各属性ごとの重要度と、qp_iの関連度のスコアを計算する。
また、その結果を掛け合わせることで、属性jにおける、アイテムqp_iの関連度のスコア(u_{ij})を計算する
3.候補アイテム×すべての属性に対して、下記を最大化するように候補アイテムをXに配置する
f:id:A_Koide0519:20211014195153p:plain
X_{ij}=1のとき、レコメンドアイテムiが属性jに配置されることを表している
u_{ij}=u(q,p_i,a_j)と考えて良いはず
4.すべての属性、すべての候補アイテムに対して、X_{ij}=1のときそのアイテムをグループG_jにinsertし、u_{ij}で降順ソートする。
その後、グループ全体の平均関連度スコアs_jを計算する
6.すべてのグループをsのスコアで降順ソートし、TopKのグループを返却する

今回は30個の候補アイテムに対して、5個の属性グループを作る。
また、一つの属性グループに対して5つのアイテムを割り当てる。

実験

amazonの7つのサブカテゴリの実データを用いて検証をした。
比較として
・ExtractのEmbeddingのみ
・BPR
・ACCM
・A2CF
との比較を実施。

expect-stepの評価

30個のアイテムからTop10を抽出した際のNDCG、Recall、Precisionで評価。
best baselineのA2CFと比較してもNDCGで10%以上の改善をしている。
Recall、Precisionについても全体で5%以上改善している。
カテゴリによっては30-50%の大幅な改善が見られている。

explain-stepの評価

重要な属性を抽出できているかの評価。
・ランダム:候補アイテムのランダムに任意の属性に割り当てる
・Greedy:候補アイテムに対し、そのタイミングでu_{ij}が一番大きい属性に候補アイテムを割り当てる
との比較を実施。
評価として、ランダムに抽出した1000caseをユーザーに5点満点で評価してもらった。
こちらの結果についても提案手法が最も良い結果を出している。
実際に提案手法では候補となるアイテム集合が異なると属性のランキングが変化している。

オンラインA/Bテスト

コンバーションが+0.080%増加し、売上が+0.105%向上

所感

属性ベースのレコメンド第2弾。
extractとexpectの結果にかなり大きな差があるが、基本的に属性とそれに対応するキーワードの情報を追加しただけでかなりのリフトがあって意外な感じがした。
この問題を実用化する時に、アイテムに対する属性と、それに対応するキーワードを付与する部分が一番大変だと思うので、そのあたりもいい方法があったら知りたい。

メモ:“Serving Each User”: Supporting Different Eating Goals Through a Multi-List Recommender Interface(recsys2021)

論文
https://dl.acm.org/doi/pdf/10.1145/3460231.3474232

概要

レシピサイトでのレコメンデーションを対象にした論文。
食の嗜好はその時々で異なる。今日はヘルシーなものが食べたいけど明日はジャンクなものを食べたいということは日常茶飯事。
この課題をレコメンドの提示方法の工夫で解決する。
具体的には複数のレコメンドリストを提示することで解消を図る。
実験として、

  • 複数のレコメンドを提示する/単一のレコメンドを提示する
  • レコメンドの説明を付与する/説明を付与しない

のパターンでユーザー実験を行った。
結果として複数リストの提示はダイバーシティ、選択の満足度においてユーザーの支持を得られた。

やりたいことは
[RQ1] 説明付きのmulti-listレコメンドが、single-listのレコメンドに比べてユーザーにとって有用なものかの評価
[RQ2] 説明付きのmulti-listレコメンドが、single-listのレコメンドに比べて異なるユーザーのゴールや健康的な食品選択の助けになっているかの評価

の2つ。

実験設定

ロジック

58,000個のレシピから5つのカテゴリ(Casseroles, Toasts. Salads, Pasta, Chicken)のアイテムをランダムに1,000個弱サンプリング。
また、レコメンドのseedになるアイテムを30個ほど選択。
ランキングはタイトルのtermをTFIDFで重み付けした類似度の降順ソート。
更にそこからsub-listを生成する。
まず上述の類似度によってTop40個のレシピを取得し、そこから下記のロジックによって各項目毎にTop5のレコメンドリストを生成する。

  • Similar Recipes:関連度そのまま
  • Fewer Calories:カロリーの低い順に並べ直す
  • Fewer Carbohydrates:100gあたりの炭水化物含有量が少ない順
  • Less Fat:100gあたりの脂質が少ない順
  • More Fiber:100gあたりの食物繊維が多い順

被験者

366人の参加者。男女比は52:48で、年齢の平均は約35歳。

手順

より健康的な選択肢も含めてユーザーが関心のあるレシピを見つけられたかどうかをチェックする.
ユーザーはデモグラと健康状態、料理経験を記入する。
5つのカテゴリ(Casseroles, Toasts. Salads, Pasta, Chicken)のレシピを検索するという形のタスクを行う形。下記の図のように検索結果としてシードアイテムを提示して、その下にレコメンドが掲載される。
ここをsingle listのパターンとmulti listのパターンで出し分けて、どのレシピが好きか、あるいは家で作ってみたくなるかを選択する。
5回の試行の後、進められたレシピセットを、選択の難しさ、多様性やわかりやすさ、の観点から評価してもらう。

f:id:A_Koide0519:20211003000015p:plain

評価指標

  • ユーザーの評価に関連する指標

1つ目の問いを確かめるための指標。
実験におけるユーザーのFB情報をもとに作成する。ユーザーには「選択の難しさ」、「多様性」、「理解のしやすさ」、「選択の満足度」の観点で評価をしてもらう。

  • 選択指標&ユーザー特徴

2つめの問いを確かめるための指標。
それぞれのレシピに対する健康度を表すものとしてFSA Scoreというものを付与する。
rangeは4(健康)~12(不健康)となっていて、UK Food Standard Agtencyというところが公開しているものを使う。
油、砂糖、塩が多くなるとスコアが高くなる。
選んだレシピのFAS Scoreとレコメンドしたレシピの平均FAS Scoreの関係性を利用する。
また、選んだアイテムに対して選んだときの目標があったかを尋ねる。
最後にデモグラと健康状態、料理経験(5pointスケール)を尋ねる。

結果

確認的因子分析

「選択の難しさ」、「多様性」、「理解のしやすさ」、「選択の満足度」のスコアと、それぞれの質問内容の関係性を確認的因子分析で確認した。
f:id:A_Koide0519:20211003005649p:plain

構造方程式モデリング

「選択の難しさ」、「多様性」、「理解のしやすさ」、「選択の満足度」のスコア、レコメンドのロジック、ユーザーの特徴と言った要素の関係性を構造的に明らかにするために、構造方程式モデリング利用する。
結果は以下。
f:id:A_Koide0519:20211003011028p:plain

single-list vs multi-list

レコメンドのパターンと、評価指標の関係性を確認する。
まず、multi-listであることが多様性に大きく寄与していることがわかる。
多様性の観点では、多様性の高さは選択の難しさを高めてしまうこと、multi-listの提示による選択の難しさは多様性によって媒介される事がわかった。一方、説明の有無は関与していない。
また、multi-listの提示による選択満足度は多様性によって媒介され、多様性は選択の満足度に影響を与えていることがわかった。一方、説明の有無は関与していない。

選択指標

対照的な結果として、説明付きmulti-listは非健康的なレシピ選択へ導いてしまっているが、説明の追加自体は健康的なレシピ選択へ導くという結果になった。
また、選択したアイテムのFSAスコアとユーザーのゴールにはネガティブな関係性があった。
これは健康的なレシピの選択がユーザーのゴールに関係を持つことを示している(FSA Scoreは低いほど健康的)。
実際にmulti-listに対して説明の有無による選択アイテムのカテゴリの割合を見てみると、説明ありの方はMore Fiberの選択率が10pt近く上昇している。また、食物繊維の多いレシピはFSAスコアが低くなる傾向がある。
さらに、ユーザーのゴールにマッチした選択によって、高い理解のしやすさを得られる事もわかった。

ユーザー特徴

ユーザの自己申告健康度合いと選んだレシピのFSAスコアにはネガティブな関係がある。
自己申告で健康とした人は健康志向なレシピを選びやすい。
また、ユーザーの料理経験と選択の満足度にはポジティブな関係があり、今回のインターフェースが経験者向けに設計されていることが示唆される。

結論

[RQ1] 説明付きのmulti-listレコメンドが、single-listのレコメンドに比べてユーザーにとって有用なものかの評価
muti-listのほうがユーザーをより満足されられるという結果になった。それは選択の多様性から導かれるものである。
このインターフェースが料理経験がより多い人にとって好まれやすいものである。
ラベルのないmulti-listのインターフェースでは説明を入れても選択肢の過多を減らせないし、満足度も上げられない。これは先行研究の結果とは少し異なる部分。
タイトルや詳細説明などの付加情報が入っていると説明の追加にインパクトがないのかも。

[RQ2] 説明付きのmulti-listレコメンドが、single-listのレコメンドに比べて異なるユーザーのゴールや健康的な食品選択の助けになっているかの評価
multi-listのインターフェースのほうが不健康な関連レシピを選びがちになっているが、一方で説明を加えることで多くのユーザーが食物繊維を多く含むレシピを選択してくれることもわかった。
健康的なレシピを選ぶことがユーザーの食事やレシピのゴールと関係している。
これはより健康的なレシピが存在するのであればそれをサポートしてあげることでユーザーの健康的な食事目標に貢献するかもしれないことを示唆している。

所感

最近こういったインターフェースのレコメンドのパターンが増えてきているんじゃないかという話を周りでしていた中でrecsys2021で発表されていたということで一通り確認。
こういったユーザーヒアリングも自分たちでやるのはなかなか大変なので傾向がなんとなくわかっただけでありがたい。

メモ JiZhi: A Fast and Cost-Eective Model-As-A-Service System for Web-Scale Online Inference at Baidu(KDD2021)

内容

Deepを活用したレコメンドモデルは様々な領域で活用されているが、十分に学習されたモデルを本番環境で通用する速度で推論でき、多くのユーザーから多様な時間帯でのアクセスを捌き、コストを最適化することはチャレンジングな取り組み。
この論文ではJiZhiというModel As A Serviceを提案している。

この仕組によって、推論の効率を犠牲にせずに200%の追加トラフィックに耐えることができ、1000万USドル以上のコスト削減を実現できている。

システム

f:id:A_Koide0519:20210908230458p:plain

Staged event-driven pipeline

各構成要素を以下のように定義する

定義1:ステージプロセッサ

推論のworkflowにおいて、ステージプロセッサpを以下のタプルで定義する。
{ \displaystyle p = \lt op,c \gt }
 op:特定のステージの機能をカプセル化したプリミティブを表す演算子
 c:上流のプロセッサからのイベントをキューイングするチャンネル
推論のworkflowはステージプロセッサの集合でモジュール化される。
 P=\{p_1,p_2,...\}
各ステージプロセッサでは、オペレータが入力されたイベントを処理したイベントを次のステージプロセッサに添付されたチャンネルキューに渡す。

定義2:Staged Event-Driven Pipeline (SEDP)

有向非巡回グラフとして定義される。
 G = (P, E)
Pはステージプロセッサの集合。
Eは2つのステージプロセッサを接続するエッジ
ex.  e_{i,j} p_i p_jを接続するエッジ
SEDPではすべてのエッジが同じステージのプロセッサを指し示し、チャンネルを共有しており、aggやjoinと言った複雑なイベントの処理を可能にしている。

SEDPはここのステージプロセッサの依存関係を自動で分析し、共有されたチャンネルを構築し、完全非同期実行をコンパイルする。

f:id:A_Koide0519:20210911171436p:plain

上記がuser-itemのworkflowの例。
user featureの抽出とitem featureの抽出、変換処理それぞれ別のステージプロセッサで実行される。リクエストのすべての生の特徴量は対応する特徴量パラメータ(embeddingsやsparse vector)を取り出すために再結合される。
最後に取り出したパラメータをDNN networkにfeedしてアイテムの関連スコアを取得する。
ステージプロセッサを非同期に実行することで、ロングテイルアイテムによるパイプラインの停滞の可能性を減らし、全体のスループットを向上させている。
ステージプロセッサのキャパシティ(並列数、メモリなど)は個別に調整できるので共有インフラの利用効率を高められる。

また、SEDPはマルチテナント拡張機能により、単一のパイプラインの中で複数のDNNモデルにアクセスでき、多段でDNNモデルを噛ませたり並列でDNNモデルを噛ませたりできる。これによりレコメンドの性能を上げたりA/Bテストを容易に実施できる。

Heterogeneous and hierarchical storage

f:id:A_Koide0519:20210911180556p:plain

The Distributed Sparse Parameter Cube

レコメンドでは、DNNは通常巨大でスパースなsub-networkと適度な密度のあるネットワークからなる。
そこでスパースなsub-networkの極めて高次元なパラメータを管理する仕組みを導入した。
これはread-onlyのKVSで、keyはコンパクトな特徴量のシグネチャとして定義され、valueはスパースな特徴量に対応するユーザーフィードバックの統計量とモデルの重みを表す。
すべてのキーはメモリに格納され、値はGBサイズにブロックにまとめられてメモリあるいはSSDに格納される。ここはlatencyとハードウェアの容量のtrade-offになる。

Heterogeneous and Hierarchical Cache

上述のcubeによって数ミリsecのlatencyで特徴量のアクセスができるが、オンライン推論のプロセスではまだ通信量が計算量が多いので、いくつかのキャッシュを導入した。

  • Cube cache

提供済みのBaiduのレコメンドサービスの中で、1億のcubeへのアクセス頻度可視化してみると、80%以上のリクエストは全体のたかだか1%の値にしかリクエストしていない。したがってキャッシュの導入はnetwork I/Oコストの削減に有効。
Cube chaceはmemory layerとdisk layerの2層のキャッシュになっており、memory layerにはLFUポリシーに基づいて上位0.1%のkey-valueのペアを格納し、disk layerには同様のポリシーに基づいて上位1%のkey-valueのペアを格納する。
これによってリクエストを90%削減でき、平均のレイテンシが10向上した。

  • Query cache

user-itemのスコアは短時間ではstableであるという考察から、過去のuser-itemのスコアをキャッシュする。
実際にスコアの不変の割合を計算してみると、2分後でも60%以上のスコアは不変だった。
このキャッシュは定められたtime windowを経過するか、ユーザーからのフィードバック(click,unlike)に基づいて更新される仕組みで、更新のポリシはLRUとなっている。結果として20%の計算コストを削減できている。

Intelligent resource manager

オンライン、オフライン両方のオートチューニングコンポーネントになっており、自動でリソース割当や各コンポーネントの負荷軽減の方針を検索、学習する。
#内容がなかなか難しいので詳細は省く

  • オフライン

目的としては、レイテンシの制約下においてリソースの消費を最小化する各種パラメータを探索することになる。
レイテンシの制約はデフォルトの設定以下になるようにする。

  • オンライン

レコメンドの問題では1st pahseでrecallが最大になるように候補を作り、2nd phaseでリランキングして数個のアイテムまで絞るが、2nd pahseに入力するアイテムの中で最初から低品質なものをカットしてしまうことで、リランキングの計算コストを抑えることができるはず。
そこで精度が指定した値以上に小さくならないように低品質な候補アイテムをプルーニングするポリシーを作成する。

評価

既存のBaiduのレコメンドシステムとの比較(リファレンスはあるけど読めていない)。
いくつかのBaiduの本番で動いているレコメンドサービスで比較した結果、各種パフォーマンスが改善。特にスループットインスタンス数が大きく改善している。
f:id:A_Koide0519:20210911191315p:plain

他にもいろいろな評価や分析をしているがここのインパクトがとにかく大きい。

所感

Intelligent resource managerの部分は難しくて読みきれなかった。
推論のパイプライン周りなどはかなり手が込んでいてすぐになにか試せそうという感じはしなかったが、ストレージ側のデータの持ち方やキャッシュの入れ方、キャッシュのポリシーの考え方は参考になりそう。