2.1.4 ランキングの詳解

位置づけ

ランキングとは、候補検索で集めた候補作品を、ユーザーに提示する順序へ並べ替える工程である。候補検索が「有望な作品を漏らさず集める」工程であるのに対し、ランキングは「限られた表示枠の中で、どの作品を上から見せるべきか」を決める工程である。

推薦システム全体の流れで見ると、ランキングは次の位置にある。

  1. コンテンツ理解で作品を特徴量化する
  2. ユーザーモデリングでプロフィールの嗜好を表現する
  3. 候補検索で全作品から数百件から数千件程度を取り出す
  4. ランキングで候補を精密に並べ替える
  5. 再ランキングやビジネスルールで多様性、安全性、配信制約を調整する
  6. 画面上の棚や枠に表示する

Hulu のような動画配信サービスで考えると、候補検索は profile_id に対して数百から数千件の series_id を返す。ランキングは、それらの候補に対して、item_information_table の作品特徴量、unique_viewed_series の視聴履歴、ユーザー特徴量、文脈特徴量を組み合わせてスコアを付ける。

例えば、候補検索が次のような作品を返したとする。

  • 「名探偵コナン」
  • 「インターステラー」
  • 「SPY x FAMILY」
  • 「韓国恋愛ドラマ A」
  • 「世界の果てまでイッテQ」
  • 「TENET」
  • 「キッズ向けアニメ B」

ランキングの仕事は、これらを一律に人気順で出すことではない。あるプロフィールが最近 SF 映画をよく見ているなら、「インターステラー」や「TENET」を上げるかもしれない。別のプロフィールが家族でアニメを見ているなら、「名探偵コナン」や「SPY x FAMILY」を上げるかもしれない。さらに、キッズプロフィールであれば年齢適合性の低い作品を下げる、配信終了が近い人気作品を少し上げる、同じジャンルばかりが並ばないようにする、といった調整も必要になる。

ランキングは、推薦システムの中でも特にプロダクト指標に直結しやすい。上位 1 件から 10 件の並びが変わるだけで、クリック、視聴開始、視聴継続、満足度、解約抑制に影響するからである。

候補検索とランキングの違い

候補検索とランキングは、どちらも「ユーザーに合いそうな作品を選ぶ」処理なので混同しやすい。しかし、最適化すべき性質が異なる。

候補検索では、全カタログから候補を高速に集める必要がある。したがって、多少ノイズが混ざってもよいので、将来視聴される可能性のある作品を漏らさないことが重要である。評価指標としては Recall@K や Coverage が重視される。

一方、ランキングでは、候補集合の中で上位に何を置くかが重要である。ユーザーが実際に見るのは、候補 1000 件全体ではなく、画面上の数件から数十件である。したがって、ランキングでは上位位置の精度が重要になる。評価指標としては NDCG@K、MAP@K、MRR、HitRate@K、視聴開始率、総視聴時間、完走率などが使われる。

数式で書くと、候補検索は全アイテム集合 I\mathcal{I} から候補集合 Cu\mathcal{C}_u を作る。

CuI\mathcal{C}_u \subset \mathcal{I}

ランキングは、その候補集合 Cu\mathcal{C}_u の各アイテム ii に対してスコア s(u,i)s(u, i) を計算し、スコアの降順に並べる。

s(u,i)=fθ(u,i,xu,i)s(u, i) = f_\theta(u, i, x_{u,i})

ここで、uu はユーザーまたはプロフィール、ii は作品、xu,ix_{u,i} はユーザーと作品の組に依存する特徴量、fθf_\theta は学習されたランキングモデルである。

ランキング結果は次のように表せる。

πu=argsortiCus(u,i)\pi_u = \operatorname{argsort}_{i \in \mathcal{C}_u} s(u, i)

ここで πu\pi_u はプロフィール uu に対する推薦リストである。

動画推薦における「関連性」とは何か

教科書では「予測されるユーザとの関連性」と表現されている。しかし、動画推薦における関連性は単純な概念ではない。EC であれば購入、検索であればクリックや明示的な関連度ラベルが比較的分かりやすい。一方、SVOD の動画推薦では、主なフィードバックは視聴の有無であり、しかも「視聴した」ことにも濃淡がある。

Hulu の unique_viewed_series は、動画コンテンツ長の 25% 以上を視聴したシリーズを記録するテーブルである。これは推薦学習において非常に重要な暗黙的フィードバックである。つまり、ある profile_id がある series_id を 25% 以上視聴したなら、その作品に一定以上の関心があったとみなせる。

ただし、視聴済みをそのまま「好き」と解釈するのは危険である。

例えば、次のようなケースがある。

  • サムネイルに惹かれて再生したが、すぐ離脱した
  • 家族の別メンバーが同じプロフィールで視聴した
  • たまたま自動再生で流れた
  • 作品は好きだったが、時間がなくて途中で止めた
  • 子ども向け作品を親のプロフィールで再生した
  • TVOD 作品に興味はあるが、課金が必要なので視聴しなかった

このため、ランキングで予測したい目的は 1 つではなく、複数に分けて考える必要がある。

動画推薦でよく考える目的は次のようなものである。

  • クリックまたは詳細ページ閲覧の確率
  • 再生開始の確率
  • 25% 以上視聴される確率
  • 50% 以上視聴される確率
  • 完走される確率
  • 総視聴時間の期待値
  • 次エピソードへ進む確率
  • お気に入り、マイリスト、保存などの確率
  • 低評価、すぐ離脱、非表示などの負の反応の確率
  • 長期的な継続利用への寄与

Hulu のデータカタログにある unique_viewed_series は「25% 以上視聴」を持つため、少なくとも「一定以上視聴したか」を学習ラベルにしやすい。ただし、実運用では再生開始ログ、再生秒数、視聴完了率、詳細ページ閲覧、検索、マイリスト追加、スキップなどを加えるほど、ランキングの目的を細かく設計できる。

ポイントワイズランキング

ポイントワイズランキングは、ユーザーとアイテムのペアを 1 つずつ見て、そのペアが良いかどうかを予測する方法である。

最も素朴には、プロフィール uu が作品 ii を将来 25% 以上視聴する確率を予測する。

y^u,i=P(yu,i=1u,i,xu,i)\hat{y}_{u,i} = P(y_{u,i}=1 \mid u, i, x_{u,i})

ここで yu,i=1y_{u,i}=1 は、評価期間中にプロフィール uu が作品 ii を 25% 以上視聴したことを表す。

ロジスティック回帰であれば、スコアは次のように表せる。

y^u,i=σ(wTxu,i)\hat{y}_{u,i} = \sigma(\mathbf{w}^{\mathsf{T}} \mathbf{x}_{u,i})

ここで xu,i\mathbf{x}_{u,i} は特徴量ベクトル、w\mathbf{w} は重み、σ\sigma はシグモイド関数である。

σ(z)=11+exp(z)\sigma(z) = \frac{1}{1+\exp(-z)}

学習では、二値交差エントロピーを最小化する。

L=(u,i){yu,ilogy^u,i+(1yu,i)log(1y^u,i)}L = - \sum_{(u,i)} \left\{ y_{u,i}\log \hat{y}_{u,i} + (1-y_{u,i})\log(1-\hat{y}_{u,i}) \right\}

Hulu での具体例:

プロフィール P001 が過去に「インターステラー」「TENET」「ダークナイト」を視聴しているとする。候補として「オッペンハイマー」「名探偵コナン」「韓国恋愛ドラマ A」がある。ランキングモデルは各候補について、次のような特徴量を作る。

  • ユーザーの過去視聴ジャンル分布と候補作品ジャンルの一致度
  • 視聴済み作品の avg_fingerprint 平均と候補作品の avg_fingerprint の類似度
  • 視聴済み作品の avg_mood_tag と候補作品の avg_mood_tag の類似度
  • 候補作品の genresub_genrecastsfilm_directors
  • 候補作品の premiere_year
  • 候補作品の service_type
  • 候補作品の配信終了までの日数
  • 候補作品が視聴済みかどうか

そして、各作品に対して「25% 以上視聴される確率」を出す。

候補作品 予測値 y^u,i\hat{y}_{u,i} 解釈
オッペンハイマー 0.42 ノーラン作品嗜好と近く、SF・歴史ドラマにも反応しそう
名探偵コナン 0.18 人気作品だが、このプロフィールの映画嗜好とは少し遠い
韓国恋愛ドラマ A 0.05 過去履歴からは関連性が低い

この場合、ポイントワイズランキングでは予測値の高い順に並べる。

ポイントワイズの長所は実装しやすく、ラベル設計が直感的で、分類問題または回帰問題として扱える点である。ロジスティック回帰、GBDT、ニューラルネットワークなど多くのモデルを使える。

一方、弱点もある。ランキングでは「どちらを上に出すべきか」が重要なのに、ポイントワイズでは各アイテムを独立に評価する。例えば、スコア 0.41 と 0.40 の差が本当に順位差として意味があるのか、スコア 0.90 の作品が 10 件並んだときに似た作品ばかりにならないか、といった問題は直接扱いにくい。

暗黙的フィードバックにおける負例の難しさ

Hulu のようなサービスでは、明示的な星評価よりも、視聴したかどうかが主な信号になる。このとき、ランキング学習で特に難しいのが負例である。

視聴した作品は、ある程度ポジティブとみなせる。しかし、視聴しなかった作品を単純にネガティブとはみなせない。ユーザーがその作品を嫌いだったのか、単に表示されなかったのか、表示されたが気づかなかったのか、TVOD で課金が必要だったから避けたのか、配信期間外だったのかが分からないからである。

暗黙的フィードバックでは、観測された正例と未観測のアイテムを区別する必要がある。

yu,i=1means observed positivey_{u,i}=1 \quad \text{means observed positive}
yu,i=0does not always mean negative preferencey_{u,i}=0 \quad \text{does not always mean negative preference}

実務では、未視聴作品から負例をサンプリングすることが多い。ただし、サンプリング方法によってモデルの性質が大きく変わる。

例えば:

  • ランダム負例: 全未視聴作品からランダムに選ぶ
  • 人気作品負例: 多くのユーザーが見ているのに、そのユーザーは見ていない作品を選ぶ
  • 表示済み未視聴負例: 実際に表示されたが視聴されなかった作品を選ぶ
  • 同ジャンル内負例: ユーザーが好むジャンル内で未視聴の作品を選ぶ
  • ハードネガティブ: 候補検索では高スコアだが実際には視聴されなかった作品を選ぶ

具体例:

SF 映画好きのプロフィールに対して、未視聴作品から負例を取るとする。「料理バラエティ」「幼児向けアニメ」「韓国恋愛ドラマ」を負例にすると、モデルは簡単に正例と負例を分けられる。しかし、それだけでは「SF 映画の中で何を上位にすべきか」を学びにくい。

一方、「インターステラー」は視聴済み正例、「TENET」は未視聴負例、「ダークナイト」は未視聴負例、のように同じ監督や近いジャンルの中で比較させると、モデルはより細かい嗜好差を学べる。ただし、未視聴の「TENET」は単にまだ見ていないだけかもしれない。したがって、負例にはノイズがある。

このため、暗黙的フィードバックのランキングでは、負例を「嫌いな作品」と断定せず、「その時点では観測されなかった作品」として扱う意識が重要である。

ペアワイズランキング

ペアワイズランキングは、2 つのアイテムを比較して、どちらを上に置くべきかを学習する方法である。

ユーザー uu に対して、正例アイテム ii と負例アイテム jj があるとする。このとき、望ましい関係は次である。

s(u,i)>s(u,j)s(u,i) > s(u,j)

例えば、プロフィール P001 が「インターステラー」を 25% 以上視聴し、「韓国恋愛ドラマ A」は表示されたが視聴しなかったなら、モデルには次の順序を学ばせたい。

s(P001,インターステラー)>s(P001,韓国恋愛ドラマ A)s(P001, \text{インターステラー}) > s(P001, \text{韓国恋愛ドラマ A})

代表的なペアワイズ損失の 1 つに BPR がある。BPR は Bayesian Personalized Ranking の略で、暗黙的フィードバック推薦でよく使われる。

LBPR=(u,i,j)logσ(s(u,i)s(u,j))L_{\text{BPR}} = - \sum_{(u,i,j)} \log \sigma(s(u,i)-s(u,j))

ここで、ii は観測された正例、jj は未観測または負例サンプリングされたアイテムである。この損失は、正例のスコアが負例のスコアより高くなるほど小さくなる。

ワークド例: BPR 損失の直感:

あるプロフィールについて、モデルが次のスコアを出したとする。

s(u,インターステラー)=2.0s(u,\text{インターステラー}) = 2.0
s(u,韓国恋愛ドラマ A)=0.5s(u,\text{韓国恋愛ドラマ A}) = 0.5

スコア差は 1.51.5 である。

σ(1.5)0.82\sigma(1.5) \approx 0.82

したがって、このペアの損失は次のようになる。

log0.820.20-\log 0.82 \approx 0.20

一方、モデルが誤って次のようにスコアを出したとする。

s(u,インターステラー)=0.5s(u,\text{インターステラー}) = 0.5
s(u,韓国恋愛ドラマ A)=2.0s(u,\text{韓国恋愛ドラマ A}) = 2.0

この場合、スコア差は 1.5-1.5 である。

σ(1.5)0.18\sigma(-1.5) \approx 0.18

損失は次のように大きくなる。

log0.181.71-\log 0.18 \approx 1.71

つまり BPR は、「視聴された作品が未視聴作品より上に来る」ようにモデルを押す。

ペアワイズランキングの長所は、ランキングの本質である相対順序を直接学習できる点である。暗黙的フィードバックでは、絶対的な確率ラベルよりも「このユーザーにとって、視聴済み作品は未視聴作品より上であってほしい」という学習の方が自然な場合が多い。

一方、弱点はペア数が膨大になることである。ユーザーごとに正例が mm 件、負例候補が nn 件あると、単純には m×nm \times n 個のペアができる。実務では負例サンプリングやハードネガティブマイニングが必要になる。

RankNet と SVM-Rank

教科書に出てくる RankNet は、ニューラルネットワークを使ったペアワイズランキング手法である。基本的な考え方は、2 つのアイテムのスコア差から「アイテム ii がアイテム jj より上に来る確率」を計算することである。

P(ij)=σ(sisj)P(i \succ j) = \sigma(s_i - s_j)

ここで iji \succ j は「iijj より上に置くべき」という意味である。

より一般には、yi,j=1y_{i,j}=1 を「iji \succ j」、yi,j=0y_{i,j}=0 を「jij \succ i」という教師ラベルとして、交差エントロピー損失を最小化する。

RankNet(i,j)=yi,jlogP(ij)(1yi,j)log(1P(ij))\ell_{\mathrm{RankNet}}(i,j) = -y_{i,j}\log P(i\succ j) -(1-y_{i,j})\log(1-P(i\succ j))

スコア sis_isjs_j は、ユーザー・作品・両者の交互作用特徴量を入力したニューラルネットワークの出力である。重要なのはスコアの絶対値ではなく差 sisjs_i-s_j である。両方のスコアに +10+10 を足しても順序は変わらず、損失も変わらない。

ワークド例: あるプロフィールが「インターステラー」を視聴し、「韓国恋愛ドラマ A」は表示されたが再生しなかったとする。このとき i=インターステラーi=\text{インターステラー}j=韓国恋愛ドラマ Aj=\text{韓国恋愛ドラマ A}yi,j=1y_{i,j}=1 と置く。モデルが si=2.0s_i=2.0sj=0.5s_j=0.5 を出した場合、

P(ij)=σ(2.00.5)=σ(1.5)0.82P(i\succ j)=\sigma(2.0-0.5)=\sigma(1.5)\approx 0.82

であり、損失は log(0.82)0.20-\log(0.82)\approx0.20 となる。逆に si=0.5s_i=0.5sj=2.0s_j=2.0 なら、確率は約 0.180.18、損失は約 1.711.71 である。後者ほど大きく更新され、正例のスコアを上げ、負例のスコアを下げる方向に学習する。

同順位を許す場合は yi,j=0.5y_{i,j}=0.5 と置くこともあるが、暗黙的フィードバックでは「視聴されたものを上」とする二値のペアを使うことが多い。なお、先行する BPR もシグモイドでペアの順序を学ぶという意味では RankNet に近い。BPR は通常 y=1y=1 の正負ペアに logσ(sisj)-\log\sigma(s_i-s_j) を使い、RankNet は正逆どちらの順序ラベルも同じ交差エントロピーの形で扱える。

SVM-Rank もペアワイズの考え方に基づくが、ニューラルネットワークではなく SVM のマージン最大化を使う。直感的には、正例アイテムのスコアが負例アイテムのスコアより、少なくとも一定のマージンだけ高くなるようにする。

wTxu,iwTxu,j+1ξu,i,j\mathbf{w}^{\mathsf{T}}\mathbf{x}_{u,i} \ge \mathbf{w}^{\mathsf{T}}\mathbf{x}_{u,j} + 1 - \xi_{u,i,j}

ここで ξu,i,j\xi_{u,i,j} はマージン違反を許すためのスラック変数である。

SVM-Rank では、全ペアに対してこの不等式をなるべく満たしつつ、モデルを過度に複雑にしないように次の目的を最小化する。

minw,ξ12w2+C(u,i,j)ξu,i,j\min_{\mathbf{w},\boldsymbol{\xi}} \frac{1}{2}\|\mathbf{w}\|^2 + C\sum_{(u,i,j)}\xi_{u,i,j}
subject towT(xu,ixu,j)1ξu,i,j,ξu,i,j0\text{subject to}\quad \mathbf{w}^{\mathsf{T}}(\mathbf{x}_{u,i}-\mathbf{x}_{u,j}) \ge 1-\xi_{u,i,j},\qquad \xi_{u,i,j}\ge0

最初の項は重みを小さく保つ正則化、2 項目は順序違反への罰則である。CC を大きくすると違反を強く嫌い、小さくすると単純なモデルを優先する。ヒンジ損失として書けば、各ペアの損失は次の一行になる。

SVM(u,i,j)=max(0,1wT(xu,ixu,j))\ell_{\mathrm{SVM}}(u,i,j) = \max\left(0,\,1-\mathbf{w}^{\mathsf{T}}(\mathbf{x}_{u,i}-\mathbf{x}_{u,j})\right)

ワークド例: 特徴量を「ユーザーの SF 嗜好との一致」と「作品人気度」の 2 つとし、w=(2.0,0.2)\mathbf{w}=(2.0,0.2) とする。SF を好むユーザーに対して、作品 ii の特徴量を (0.9,0.5)(0.9,0.5)、作品 jj(0.2,0.8)(0.2,0.8) とすると、

si=2.0×0.9+0.2×0.5=1.9,sj=2.0×0.2+0.2×0.8=0.56s_i=2.0\times0.9+0.2\times0.5=1.9,\qquad s_j=2.0\times0.2+0.2\times0.8=0.56

であり、差は 1.341.34 である。必要なマージン 11 を満たすため損失は 00 になる。一方、差が 0.40.4 なら ξ=10.4=0.6\xi=1-0.4=0.6、損失も 0.60.6 になる。SVM-Rank は「正例が上なら十分」ではなく、「少なくとも 1 だけ離して上に置け」と要求する点が RankNet と異なる。RankNet は確率を滑らかに改善し、SVM-Rank はマージンを満たしたペアには追加の損失を与えない。

Hulu のランキングでこれらを考えるなら、例えば「視聴された作品」と「表示されたが視聴されなかった作品」のペアを作り、どちらを上位に置くべきだったかを学習する。ただし、実運用では単純な RankNet や SVM-Rank そのものよりも、GBDT、DNN、Two-Tower と Cross Network の組み合わせ、Transformer 系のシーケンスモデルなどにランキング損失を組み合わせることが多い。

リストワイズランキング

リストワイズランキングは、アイテムを 1 件ずつ、または 2 件ずつではなく、リスト全体として最適化する考え方である。

ランキングの評価指標は、多くの場合、リスト全体に対して定義される。例えば NDCG@K は、上位に関連性の高いアイテムが来るほど高くなる。

DCG@K は次のように定義される。

DCG@K=r=1K2relr1log2(r+1)\text{DCG@K} = \sum_{r=1}^{K} \frac{2^{rel_r}-1}{\log_2(r+1)}

ここで rr は順位、relrrel_r は順位 rr に置かれたアイテムの関連度である。理想的な並びの DCG を IDCG@K とすると、NDCG@K は次である。

NDCG@K=DCG@KIDCG@K\text{NDCG@K} = \frac{\text{DCG@K}}{\text{IDCG@K}}

NDCG の重要な点は、上位の誤りを強く罰することである。順位 11 の重みは大きく、順位が下がるほど割引される。これは推薦 UI の現実に合っている。ユーザーはリストの上位ほど見やすく、下位ほど見ないからである。

ワークド例: NDCG の直感:

あるプロフィールに対して、関連度を次のように置く。

  • 25% 以上視聴された作品: rel=1rel=1
  • 視聴されなかった作品: rel=0rel=0

ランキング A が次の順序だったとする。

  1. 視聴された作品
  2. 視聴されなかった作品
  3. 視聴された作品

このとき DCG@3 は次である。

DCG@3=211log2(2)+201log2(3)+211log2(4)=1+0+0.5=1.5\text{DCG@3} = \frac{2^1-1}{\log_2(2)} + \frac{2^0-1}{\log_2(3)} + \frac{2^1-1}{\log_2(4)} = 1 + 0 + 0.5 = 1.5

理想的な順序は、視聴された作品を 1 位と 2 位に置くことである。

IDCG@3=1log2(2)+1log2(3)=1+0.631=1.631\text{IDCG@3} = \frac{1}{\log_2(2)} + \frac{1}{\log_2(3)} = 1 + 0.631 = 1.631

したがって NDCG@3 は次である。

NDCG@3=1.51.6310.92\text{NDCG@3} = \frac{1.5}{1.631} \approx 0.92

一方、視聴された作品が 2 位と 3 位に下がると、DCG は下がる。つまり、同じ 2 件を当てても、上位に置けているかが評価される。

ListNet、LambdaRank、LambdaMART は、このようなリスト全体の品質をより直接的に上げようとする手法である。

ListNet の代表的な考え方は、作品を独立に判定する代わりに、リスト上の「1 位になりそうな確率分布」同士を近づけることである。教師関連度を yiy_i、モデルスコアを sis_i とすると、それぞれを softmax で確率にする。

Py(i)=exp(yi)jexp(yj),Ps(i)=exp(si)jexp(sj)P_y(i)=\frac{\exp(y_i)}{\sum_j\exp(y_j)},\qquad P_s(i)=\frac{\exp(s_i)}{\sum_j\exp(s_j)}

そして、教師分布 PyP_y と予測分布 PsP_s の交差エントロピー iPy(i)logPs(i)-\sum_i P_y(i)\log P_s(i) を小さくする。例えば関連度が (2,1,0)(2,1,0) の 3 作品では、教師の softmax はおよそ (0.67,0.24,0.09)(0.67,0.24,0.09) になる。モデルがスコア (0.1,2.0,0.0)(0.1,2.0,0.0) を出すと予測分布はおよそ (0.12,0.78,0.10)(0.12,0.78,0.10) であり、最も重要な作品に十分な確率を置けていないことが分かる。これは「各ペアをどちらが上か」と個別に列挙せず、1 つの表示リスト単位で学習する例である。

LambdaRank と LambdaMART

LambdaRank は、RankNet を拡張して、NDCG のようなランキング指標を改善しやすい方向に学習する手法である。ポイントは、単なるペアの正誤ではなく、「その 2 つを入れ替えると NDCG がどれだけ変わるか」を勾配の強さに反映することである。

例えば、1 位と 2 位の入れ替えは、20 位と 21 位の入れ替えよりもユーザー体験への影響が大きい。LambdaRank は、このような位置依存の重要度を学習に入れる。

直感的には、次のような考え方である。

  • 上位で間違っているペアは強く直す
  • 下位で間違っているペアは相対的に弱く直す
  • 関連度差が大きいペアほど強く直す
  • 入れ替えによる NDCG 改善が大きいペアほど強く直す

具体的には RankNet のペアごとの更新量に、入れ替えによる ΔNDCG|\Delta\mathrm{NDCG}| を掛けるイメージである。順位 ri,rjr_i,r_j、関連度 reli,reljrel_i,rel_j のアイテムを入れ替えたときの DCG の絶対変化は、

ΔDCG=2reli1log2(ri+1)2reli1log2(rj+1)+2relj1log2(rj+1)2relj1log2(ri+1)|\Delta\mathrm{DCG}| = \left| \frac{2^{rel_i}-1}{\log_2(r_i+1)} - \frac{2^{rel_i}-1}{\log_2(r_j+1)} + \frac{2^{rel_j}-1}{\log_2(r_j+1)} - \frac{2^{rel_j}-1}{\log_2(r_i+1)} \right|

であり、ΔNDCG=ΔDCG/IDCG|\Delta\mathrm{NDCG}|=|\Delta\mathrm{DCG}|/\mathrm{IDCG} とする。実装ではこの値で RankNet 由来の勾配を重み付けする。損失を単に書き換えるというより、「各ペアをどの強さで直すか」を決める仕組みである。

ワークド例: 関連度 22 の作品 A が 3 位、関連度 00 の作品 B が 1 位に誤っているとする。A と B を交換する DCG の改善は、

(221)(1log2(2)1log2(4))=3×(10.5)=1.5(2^2-1)\left(\frac{1}{\log_2(2)}-\frac{1}{\log_2(4)}\right) =3\times(1-0.5)=1.5

である。同じ A と B が 20 位と 22 位にいる場合は、割引値の差が小さいため改善量も小さい。したがって両方とも「順序の誤り」ではあるが、前者のスコア差を強く修正する。NDCG を評価に使うなら、この重み付けによって学習信号と評価指標のずれを小さくできる。

LambdaMART は、LambdaRank の考え方と MART、つまり勾配ブースティング決定木を組み合わせた手法である。MART は Multiple Additive Regression Trees の略で、複数の決定木を順に足し合わせて強いモデルを作る。

各木は、前段の木が直し切れていない誤差(LambdaRank では NDCG 重み付きの擬似勾配)を予測する。最終スコアは MM 本の木の和である。

s(u,i)=m=1Mηfm(xu,i)s(u,i)=\sum_{m=1}^{M}\eta f_m(\mathbf{x}_{u,i})

ここで fmf_mmm 本目の決定木、η\eta は 1 本の木の寄与を小さくする学習率である。例えば最初の木が「最近 30 日の SF 視聴比率 >0.4>0.4 なら +0.3+0.3」、次の木が「配信終了まで 7 日未満かつ過去に同じシリーズを視聴なら +0.2+0.2」という補正を学ぶ、と考えるとよい。木の足し合わせにより、単独の線形重みでは表しにくい条件分岐と交互作用を扱える。

LambdaMART が実務で長く使われてきた理由は、次の点にある。

  • 数値特徴量、カテゴリ特徴量、交互作用特徴量を扱いやすい
  • 非線形な関係を表現できる
  • 特徴量重要度や分岐を見て、ある程度解釈できる
  • 中規模から大規模の表形式特徴量で強い
  • DNN よりも学習とデバッグが軽い場合が多い

Hulu のランキングで LambdaMART 的なモデルを使うなら、特徴量として次のようなものを入れられる。

  • プロフィールの過去 7 日、30 日、180 日のジャンル視聴比率
  • 候補作品の genresub_genremedia_type
  • 候補作品の人気度
  • 候補作品の新着度
  • 候補作品の配信終了までの日数
  • 視聴済み作品 embedding と候補作品 embedding の最大類似度、平均類似度
  • 同じ contents_provider_name の視聴回数
  • 同じ castsfilm_directors の視聴回数
  • service_type が SVOD か TVOD か
  • 候補作品が is_live かどうか
  • is_blacklist や公開期間に基づく除外フラグ

ただし、LambdaMART は表形式特徴量に強い一方で、長い視聴シーケンスやテキストの意味理解をそのまま扱うのは得意ではない。そのため、近年は LLM embedding、動画 embedding、シーケンスモデルの出力を特徴量として LambdaMART に入れる、または DNN ランカーに置き換える、という設計がよく使われる。

マルチタスクランキング

教科書にある「クリックする確率、いいねする確率、保存する確率、コメントする確率などを予測する」という説明は、マルチタスクランキングのことである。

マルチタスクランキングでは、1 つのモデルが複数の目的を同時に予測する。

動画推薦では、例えば次のような出力を持てる。

p^play(u,i)=P(再生開始u,i)\hat{p}_{\text{play}}(u,i) = P(\text{再生開始} \mid u,i)
p^25(u,i)=P(25% 以上視聴u,i)\hat{p}_{25}(u,i) = P(\text{25\% 以上視聴} \mid u,i)
p^complete(u,i)=P(完走u,i)\hat{p}_{\text{complete}}(u,i) = P(\text{完走} \mid u,i)
t^watch(u,i)=E[視聴時間u,i]\hat{t}_{\text{watch}}(u,i) = E[\text{視聴時間} \mid u,i]
p^negative(u,i)=P(すぐ離脱または非表示u,i)\hat{p}_{\text{negative}}(u,i) = P(\text{すぐ離脱または非表示} \mid u,i)

最終的なランキングスコアは、これらを組み合わせて作る。

S(u,i)=w1p^play(u,i)+w2p^25(u,i)+w3p^complete(u,i)+w4g(t^watch(u,i))w5p^negative(u,i)S(u,i) = w_1 \hat{p}_{\text{play}}(u,i) + w_2 \hat{p}_{25}(u,i) + w_3 \hat{p}_{\text{complete}}(u,i) + w_4 g(\hat{t}_{\text{watch}}(u,i)) - w_5 \hat{p}_{\text{negative}}(u,i)

ここで w1,,w5w_1,\ldots,w_5 はビジネスやプロダクト上の重み、gg は視聴時間を適切にスケール変換する関数である。

各タスクは共通の特徴抽出部を共有し、その上に目的別の出力層を持つ構成にすると実装しやすい。学習損失の一例は次である。

L=λplayLBCE(yplay,p^play)+λ25LBCE(y25,p^25)+λcompleteLBCE(ycomplete,p^complete)+λtLreg(twatch,t^watch)+λnegativeLBCE(ynegative,p^negative)\mathcal{L} = \lambda_{\text{play}}\mathcal{L}_{\text{BCE}}(y_{\text{play}},\hat p_{\text{play}}) +\lambda_{25}\mathcal{L}_{\text{BCE}}(y_{25},\hat p_{25}) +\lambda_{\text{complete}}\mathcal{L}_{\text{BCE}}(y_{\text{complete}},\hat p_{\text{complete}}) +\lambda_t\mathcal{L}_{\text{reg}}(t_{\text{watch}},\hat t_{\text{watch}}) +\lambda_{\text{negative}}\mathcal{L}_{\text{BCE}}(y_{\text{negative}},\hat p_{\text{negative}})

LBCE\mathcal{L}_{\text{BCE}} は二値ラベルの交差エントロピー、Lreg\mathcal{L}_{\text{reg}} は例えば Huber 損失のような視聴時間の回帰損失である。λ\lambda は、ラベル数や事業上の重要度が異なるタスクの影響を調整する。例えば「完走」は「再生開始」よりずっと少ないので、何も調整しないと再生開始タスクに学習が引っ張られやすい。

ワークド例: 作品 A と B について、モデルが次を出したとする。視聴時間は分単位だが、極端な長尺作品を支配的にしないため g(t)=log(1+t)g(t)=\log(1+t) を使う。

作品 p^play\hat p_{\text{play}} p^25\hat p_{25} p^complete\hat p_{\text{complete}} t^watch\hat t_{\text{watch}} p^negative\hat p_{\text{negative}}
A: 45 分ドラマ 0.70 0.55 0.35 24 0.05
B: 150 分映画 0.50 0.45 0.30 70 0.08

w=(1,2,2,0.2,3)w=(1,2,2,0.2,3) とすると、A のスコアはおよそ 1×0.70+2×0.55+2×0.35+0.2log(25)3×0.052.991\times0.70+2\times0.55+2\times0.35+0.2\log(25)-3\times0.05\approx2.99、B は約 2.612.61 となる。この重みでは「長く見られそう」だけで B を上げず、再生・25% 視聴・完走もバランスよく評価する。重みは恣意的に固定するのではなく、オフライン検証と A/B テストで調整する対象である。

ただし、単純に重み付き和にすればよいわけではない。例えば、長尺映画は総視聴時間が長くなりやすいが、短いアニメやバラエティの価値が低いとは限らない。完走率を重視しすぎると短尺作品ばかりが上がる可能性がある。再生開始率を重視しすぎると、釣り合いの悪いサムネイルや有名作品ばかりが上がる可能性がある。

そのため、目的関数はプロダクトの価値観を反映する設計問題でもある。

Hulu であれば、例えば次のような観点があり得る。

  • SVOD では、短期クリックよりも継続的な満足や視聴習慣を重視したい
  • TVOD では、購入またはレンタルに至る確率と価格感度を考慮したい
  • 新作や独占配信作品を適度に露出したい
  • 配信終了が近い作品を、関心が高そうなユーザーに知らせたい
  • キッズプロフィールでは安全性や年齢適合性を強く守りたい
  • 同じシリーズの既視聴エピソードを推薦しないようにしたい

ランキングスコアは機械学習モデルの出力であると同時に、サービスとして何を良い推薦とみなすかの定義でもある。

特徴量設計

ランキングモデルは、候補検索よりも多くの特徴量を使える。候補数が絞られているため、全カタログに対しては重すぎる特徴量も、候補数百件から数千件なら計算できるからである。

Hulu のデータカタログを前提にすると、ランキング特徴量は大きく次のように分けられる。

ユーザー特徴量

ユーザー特徴量は、プロフィール uu 自体を表す特徴量である。

例えば:

  • 過去 7 日、30 日、180 日の視聴回数
  • 視聴ジャンル分布
  • 視聴時間帯の傾向
  • 映画とシリーズの比率
  • SVOD と TVOD の反応差
  • 新作に反応しやすいか
  • 長尺作品を見やすいか
  • キッズ作品の視聴比率
  • 最近の視聴作品 embedding の平均

unique_viewed_series だけでも、profile_id ごとの視聴済み series_idlast_viewing_date から、最近性を考慮した嗜好を作れる。

例えば、最近視聴ほど大きな重みを与えるユーザー embedding は次のように作れる。

u=iHuα(tu,i)viiHuα(tu,i)\mathbf{u} = \frac{ \sum_{i \in \mathcal{H}_u} \alpha(t_{u,i}) \mathbf{v}_i }{ \sum_{i \in \mathcal{H}_u} \alpha(t_{u,i}) }

ここで Hu\mathcal{H}_u はプロフィール uu の視聴履歴、vi\mathbf{v}_i は作品 ii の embedding、α(tu,i)\alpha(t_{u,i}) は最終視聴日からの経過日数に応じた重みである。

例えば指数減衰を使うなら、現在日を TT、視聴日を tu,it_{u,i} として次のように置ける。

α(tu,i)=exp(λ(Ttu,i))\alpha(t_{u,i}) = \exp\left(-\lambda (T - t_{u,i})\right)

これにより、3 年前に一度見た作品より、昨日見た作品の方がユーザーベクトルに強く反映される。

ワークド例: 半減期を 30 日とし、λ=log2/30\lambda=\log 2/30 とする。昨日見た SF 作品の重みは exp(λ×1)0.98\exp(-\lambda\times1)\approx0.98、60 日前に見た恋愛ドラマの重みは exp(λ×60)=0.25\exp(-\lambda\times60)=0.25 になる。各作品 embedding をこの重みで加重平均すれば、「最近の SF 視聴」が 4 倍程度強く嗜好ベクトルに反映される。これは、すべての履歴を同じ重みで平均して現在の関心をぼかす問題を避けるための具体的な設計である。

アイテム特徴量

アイテム特徴量は、候補作品 ii 自体を表す特徴量である。

item_information_table からは、例えば次の特徴量を使える。

  • genre
  • sub_genre
  • media_type
  • service_type
  • contents_provider_name
  • countries_of_origin
  • premiere_year
  • rating_name
  • kids_mature_flg
  • is_live
  • is_audio_contents
  • catch_up_flg
  • hulu_brand_line_flg
  • sockets_tag
  • sentence
  • description
  • casts
  • producers
  • film_directors
  • writers
  • awards
  • video_duration
  • avg_mood_tag
  • avg_fingerprint
  • publish_start_at
  • publish_end_at

特に avg_mood_tagavg_fingerprint は、コンテンツベース推薦とランキングの橋渡しとして有用である。例えば「感動的」「サスペンスフル」「知的」「未来的」といった雰囲気がユーザー嗜好と合うかを特徴量にできる。

ユーザーとアイテムの交互作用特徴量

ランキングで重要なのは、ユーザー単体、アイテム単体だけでなく、ユーザーとアイテムの相性である。これを交互作用特徴量として表す。

例えば:

  • ユーザー embedding と作品 embedding の cosine 類似度
  • 最近視聴作品と候補作品の最大類似度
  • 過去視聴ジャンルと候補作品ジャンルの一致
  • 過去視聴キャストと候補作品キャストの重なり
  • 過去視聴監督と候補作品監督の重なり
  • 過去に同じ contents_provider_name の作品を見た回数
  • 候補作品と同一シリーズを視聴済みか
  • 候補作品の sub_genre に対するユーザーの反応率

cosine 類似度は次のように定義できる。

cos(u,vi)=uTviuvi\cos(\mathbf{u}, \mathbf{v}_i) = \frac{\mathbf{u}^{\mathsf{T}}\mathbf{v}_i} {\|\mathbf{u}\| \|\mathbf{v}_i\|}

ここで u\mathbf{u} はプロフィール embedding、vi\mathbf{v}_i は作品 embedding である。

具体的に、u=(0.8,0.6)\mathbf{u}=(0.8,0.6)、候補 A の embedding を (0.9,0.1)(0.9,0.1)、候補 B を (0.0,1.0)(0.0,1.0) とする。A との cosine 類似度は 0.78/(1×0.82)0.860.78/(1\times\sqrt{0.82})\approx0.86、B とは 0.600.60 である。これは「A のほうが履歴の意味的な方向に近い」という 1 つの特徴量になる。ただし、この値だけで並べるのではない。人気度、鮮度、視聴可能時間、シリーズ継続性などの特徴量と合わせてモデルに判断させる。

具体例:

プロフィールが「インターステラー」「TENET」「メッセージ」を見ている場合、avg_fingerprint の平均は SF、思索的、緊張感、知的な作品方向に寄る可能性がある。このプロフィールに対して、候補作品「オッペンハイマー」の embedding 類似度が高ければ、ランキングモデルはそれを強い相性特徴量として使える。

一方、「名探偵コナン」は人気が高くても、このプロフィールの embedding とはやや遠いかもしれない。ただし、過去にアニメ映画を見ている、家族向け視聴が多い、週末に長尺映画を見る傾向がある、といった別の特徴量があれば上位に来る可能性はある。

再ランキング

ランキングモデルが各候補にスコアを付けた後、そのままスコア順に出せばよいとは限らない。モデルのスコア順は、短期的な関連性を最大化する一方で、リスト全体の品質を損なうことがある。

例えば、あるプロフィールがアニメをよく見る場合、ランキング上位 20 件がすべてアニメになるかもしれない。しかし、ユーザーはアニメが好きでも、毎回アニメだけを見たいとは限らない。映画、バラエティ、海外ドラマ、配信終了間近の作品、新作なども適度に混ぜた方が、発見性や満足度が上がる場合がある。

再ランキングは、初期ランキング結果をリスト全体として調整する工程である。

再ランキングでよく扱う目的は次のようなものである。

  • 多様性
  • 新規性
  • セレンディピティ
  • 同一ジャンルの出しすぎ抑制
  • 同一シリーズの重複抑制
  • 視聴済み作品の除外
  • 配信期限や公開開始日の考慮
  • キッズやレーティング制約
  • SVOD/TVOD の露出バランス
  • プロモーション枠や編成方針
  • 権利上または品質上のブラックリスト除外

Hulu の場合、publish_start_atpublish_end_atis_blacklistservice_typerating_namekids_mature_flgis_live などは、再ランキングやフィルタリングで重要になる。

例えば、ランキングスコアが高くても publish_end_at を過ぎている作品は表示してはいけない。is_blacklist=true の作品も除外する必要がある。キッズプロフィールで不適切な rating_name の作品を出すべきではない。これらは関連性以前の制約である。

多様性制御

多様性制御の代表的な考え方は、「関連性が高く、かつ既に選んだ作品と似すぎていないものを選ぶ」である。

よく使われるヒューリスティックに MMR がある。MMR は Maximal Marginal Relevance の略である。次に選ぶアイテム ii を、次のスコアで決める。

MMR(i)=λs(u,i)(1λ)maxjSsim(i,j)\text{MMR}(i) = \lambda s(u,i) - (1-\lambda) \max_{j \in \mathcal{S}} \operatorname{sim}(i,j)

ここで S\mathcal{S} はすでに選ばれたアイテム集合、s(u,i)s(u,i) はランキングモデルの関連性スコア、sim(i,j)\operatorname{sim}(i,j) は作品間類似度である。λ\lambda は関連性と多様性のバランスを決めるパラメータである。

λ\lambda が 1 に近いほど元のランキングスコアを重視する。λ\lambda が小さいほど、既に選んだ作品と似ていないことを重視する。

具体例:

初期ランキングの上位が次のようだったとする。

  1. 名探偵コナン 劇場版 A
  2. 名探偵コナン 劇場版 B
  3. 名探偵コナン TV シリーズ
  4. SPY x FAMILY
  5. 葬送のフリーレン
  6. インターステラー

単純なスコア順では、上位が「名探偵コナン」関連で埋まる。これはシリーズファンには良い場合もあるが、ホーム画面の推薦棚としては重複感が強い可能性がある。

MMR を使うと、1 件目に「名探偵コナン 劇場版 A」を選んだ後、2 件目では同じシリーズの B よりも、少しスコアが低くても「SPY x FAMILY」や「インターステラー」を選ぶ可能性がある。これにより、リスト全体の発見性が上がる。

ワークド例: 1 件目にコナン A を選んだ後、残り 3 作品の関連性スコアとコナン A との類似度が次の通りだとする。λ=0.7\lambda=0.7 を使う。

候補 s(u,i)s(u,i) コナン A との類似度 MMR
コナン B 0.95 0.95 0.7×0.950.3×0.95=0.380.7\times0.95-0.3\times0.95=0.38
SPY x FAMILY 0.80 0.45 0.7×0.800.3×0.45=0.430.7\times0.80-0.3\times0.45=0.43
インターステラー 0.72 0.10 0.7×0.720.3×0.10=0.470.7\times0.72-0.3\times0.10=0.47

元のスコアだけならコナン B が 1 位だが、MMR ではインターステラーが選ばれる。この結果が常に望ましいわけではない。例えば「コナン映画を続けて見たい」という明確な意図の棚では、λ\lambda を高くする、同一シリーズの連続を許す、といった棚別の設定が必要である。

DPP による再ランキング

教科書に出てくる DPP は Determinantal Point Process の略で、日本語では決定点過程または行列式点過程と呼ばれる。DPP は、多様性のある部分集合を選ぶための確率モデルである。

DPP の直感は、「質が高いアイテムを選びたいが、互いに似すぎているアイテムばかりは選びたくない」というものである。

アイテム集合 YY が選ばれる確率を、カーネル行列 L\mathbf{L} の部分行列の行列式で表す。

P(Y)det(LY)P(Y) \propto \det(\mathbf{L}_Y)

ここで LY\mathbf{L}_Y は、選ばれたアイテム集合 YY に対応する部分行列である。

行列式は、ベクトルが張る体積に対応する。似たベクトルばかりを選ぶと体積が小さくなり、行列式も小さくなる。互いに異なる方向のベクトルを選ぶと体積が大きくなり、行列式も大きくなる。したがって DPP は、多様なアイテム集合を好む。

推薦でよく使う形として、品質スコア qiq_i と類似度 sim(i,j)\operatorname{sim}(i,j) を分けて、次のようにカーネルを作る。

Li,j=qisim(i,j)qjL_{i,j} = q_i \cdot \operatorname{sim}(i,j) \cdot q_j

qiq_i はランキングモデルの関連性スコアから作れる。sim(i,j)\operatorname{sim}(i,j) は作品 embedding の cosine 類似度などから作れる。

2 作品だけを選ぶ場合、LY\mathbf{L}_Y2×22\times2 行列になる。品質が qA=0.9q_A=0.9qB=0.8q_B=0.8、類似度が sim(A,B)=0.95\operatorname{sim}(A,B)=0.95 なら、自己類似度を 1 として、

det(0.920.9×0.95×0.80.9×0.95×0.80.82)=0.92×0.82×(10.952)0.051\det \begin{pmatrix} 0.9^2 & 0.9\times0.95\times0.8\\ 0.9\times0.95\times0.8 & 0.8^2 \end{pmatrix} =0.9^2\times0.8^2\times(1-0.95^2) \approx0.051

となる。B の代わりに品質 qC=0.7q_C=0.7、A との類似度 0.20.2 の C を選ぶと、行列式は 0.92×0.72×(10.22)0.3810.9^2\times0.7^2\times(1-0.2^2)\approx0.381 である。C は B より関連性が低くても、A と十分異なるため、ペア集合としては高く評価される。この「品質の積」と「似すぎへの罰則」が同時に入ることが DPP の具体的な意味である。

Hulu であれば、avg_fingerprintavg_mood_tag を使って作品間類似度を作り、ランキングモデルのスコアを品質 qiq_i にする設計が考えられる。

ただし、DPP は万能ではない。多様性を強くしすぎると、ユーザーの明確な嗜好から外れた作品が上がりすぎる。例えば、アニメを見たいユーザーに対して、無理にニュース、ライブ、海外ドラマ、映画を混ぜると満足度が下がるかもしれない。多様性は「関連性を壊さない範囲」で入れる必要がある。

学習済み Reranker

ヒューリスティックな再ランキングでは、MMR やルールでリストを調整する。一方、学習済み Reranker は、リスト全体の状態を入力として、最終的な並び替えを学習する。

例えば、初期ランキング上位 50 件を入力し、Transformer のようなモデルで各位置の関係を見ながら再スコアリングする方法がある。これにより、次のようなリスト内特徴を扱える。

  • 同じシリーズが連続しているか
  • 同じジャンルが上位に偏っているか
  • 新作と定番作品のバランスがよいか
  • 短尺と長尺のバランスがよいか
  • SVOD と TVOD の混ざり方が適切か
  • 既視聴作品や類似しすぎる作品が多くないか

学習済み Reranker の難しさは、正解ラベルである。単体アイテムの視聴有無はログから作りやすいが、「このリスト全体が良いか」は簡単には分からない。実際にユーザーに表示されたリストには表示位置バイアスがあり、上に置かれた作品ほど見られやすい。

そのため、Reranker の評価や学習では、A/B テスト、反実仮想評価、探索トラフィック、位置バイアス補正などが重要になる。

実装上は、初期ランカーの上位 NN 件について、各候補の単体特徴量に加え、既に選んだ作品との最大類似度、同一シリーズ数、ジャンル別の件数などを状態として持たせる。たとえば 1 件ずつ選ぶ方策なら、時刻 tt のスコアを st(u,i,St1)s_t(u,i,\mathcal{S}_{t-1}) として、既選択集合 St1\mathcal{S}_{t-1} に依存させる。通常のランカーの s(u,i)s(u,i) では表せない「すでに同じシリーズを 2 件出したので 3 件目を下げる」という判断を学習できる。

位置バイアスと露出バイアス

ランキング学習で非常に重要なのがバイアスである。ログにはユーザーの嗜好だけでなく、過去の推薦システムが何を表示したかの影響が含まれる。

代表的なバイアスは次の 2 つである。

  • 位置バイアス: 上位に表示された作品ほどクリックまたは視聴されやすい
  • 露出バイアス: 表示されなかった作品は、視聴される機会がなかった

例えば、「作品 A」が 1 位に表示され、「作品 B」が 30 位に表示されたとする。A の視聴率が B より高かったとしても、A の方が本当に好まれていたとは限らない。単に A が目立つ位置にあったからかもしれない。

この問題を無視すると、ランキングモデルは過去に上位表示された作品をさらに上位に出すようになる。人気作品や既存の強い作品がますます強くなり、新作やロングテール作品が学習されにくくなる。

補正の考え方として、表示確率、つまり propensity を使う方法がある。あるアイテム ii がユーザー uu に表示される確率を pu,ip_{u,i} とする。表示されたうえで得られたラベルに対して、逆確率重みを付ける。

wu,i=1pu,iw_{u,i} = \frac{1}{p_{u,i}}

表示されにくかったのに視聴されたアイテムは大きく重み付けし、表示されやすかったアイテムの観測は相対的に小さく扱う、という考え方である。

ワークド例: 1 位の表示確率を p=0.40p=0.40、10 位の表示確率を p=0.05p=0.05 と近似する。両方の作品が視聴されたなら、逆確率重みはそれぞれ 2.52.52020 である。10 位の視聴は「見つけにくい位置でも選ばれた」強い選好信号として、より大きく扱われる。ただし pp が極端に小さいと重みが発散して学習が不安定になるため、実務では 1/p1/p を上限でクリップする、自己正規化する、位置ごとの propensity をランダム探索ログで推定する、といった対策を取る。

ただし、propensity を正しく推定すること自体が難しい。実務では、少量のランダム探索枠を設ける、表示ログを厳密に保存する、ランキング位置を特徴量に入れないよう注意する、オフライン評価とオンライン A/B テストを分けて考える、などが必要になる。

LLM をランキングに使う方法

教科書では、LLM がランキングや再ランキングを強化する方法として、埋め込み、プロンプトベースランキング、合成データ生成、評価者としての利用が挙げられている。

LLM embedding を特徴量として使う

最も実務に載せやすいのは、LLM やマルチモーダルモデルから得た embedding をランキング特徴量に入れる方法である。

Hulu の item_information_table には descriptionsentencesockets_tagcastsfilm_directorsavg_mood_tagavg_fingerprint がある。これらを使って、作品の意味表現を作れる。

例えば、作品説明文からテキスト embedding を作ると、「宇宙」「人類存続」「父と娘」「時間」「科学」といった意味的な近さを捉えられる。これにより、ジャンルが同じ「洋画 / SF」でなくても、テーマが近い作品をランキングで上げられる。

また、ユーザーの視聴履歴をテキスト化して embedding することもできる。

例えば:

このプロフィールは、近未来SF、時間を扱う映画、重厚な人間ドラマ、クリストファー・ノーラン監督作品を好む。最近は長尺映画を週末夜に視聴している。

このようなユーザープロファイル embedding と候補作品 embedding の類似度をランキング特徴量にする。

実際の特徴量行では、例えば次のように数値化する。

profile_id item_id text cosine 最近日数 同一監督の視聴回数 25% 視聴ラベル
U1 オッペンハイマー 0.84 0 2 1
U1 韓国恋愛ドラマ A 0.19 0 0 0

text cosine は候補検索で使うだけでなく、他の特徴と共にランカーに渡す。類似度が高くても、すでに視聴済み、配信終了済み、年齢制約に合わない、といった条件があれば最終的には表示しない。embedding は意味的な近さを 1 本の数値に圧縮する手段であり、事業制約を代替するものではない。

プロンプトベースランキング

LLM に直接「このユーザーに対して、候補作品を並べ替えよ」と依頼する方法もある。

例えば、次のような入力を作る。

ユーザーの最近の視聴:
- インターステラー
- TENET
- ダークナイト

候補:
- オッペンハイマー
- 名探偵コナン
- 韓国恋愛ドラマ A
- 世界の果てまでイッテQ

ユーザーが次に視聴しそうな順に並べよ。

LLM は作品説明や一般知識を使って、それらしい順序を返せる可能性がある。特に、コールドスタート作品、メタデータが豊富な作品、説明可能性が必要な場面では有用である。

本番利用を想定するなら、自由文の順位ではなく、候補 ID と根拠を固定スキーマで返すようにする。例えば「候補外の作品を追加しない」「返す ID は入力候補に限る」「各候補に 0–100 の相対スコアと根拠タグを返す」と制約する。LLM の出力をそのまま表示順にせず、既存ランカーの特徴量または少数候補用の再ランキング信号として扱えば、出力の揺れや幻覚の影響範囲を限定できる。

ワークド例: 上の 4 候補に対して、LLM が オッペンハイマー: 92 (監督・重厚な人間ドラマ)名探偵コナン: 45 (人気だが履歴との直接一致は弱い) のような構造化結果を返したとする。このスコアを単独で採用するのではなく、llm_pairwise_scorellm_reason_tag=director_match として GBDT/DNN の入力へ加え、実ログからどの程度有効かを検証する。

しかし、直接 LLM で本番ランキングを全リクエスト処理するのは、レイテンシ、コスト、安定性、再現性、評価の難しさがある。したがって、実務では次のような補助的な使い方が現実的である。

  • 少数候補の再ランキング
  • 新作やロングテール作品の意味特徴量生成
  • 作品タグや説明文の正規化
  • 学習データが少ない領域のペアワイズラベル補助
  • 推薦理由文の生成
  • オフライン評価の補助

合成トレーニングデータ

LLM は、ユーザー嗜好と作品説明から、擬似的なペアワイズ比較ラベルを作るためにも使える。

例えば、「SF 映画とノーラン作品を好むユーザーには、候補 A と候補 B のどちらがより合うか」を LLM に判定させる。これにより、視聴ログが少ない新作や、まだ十分に露出されていない作品に対して、初期のランキング学習信号を補える。

ただし、LLM のラベルは実ユーザー行動そのものではない。LLM は一般的にもっともらしい嗜好を推測するが、実際の Hulu ユーザーがその作品を視聴するか、課金するか、継続利用するかは別問題である。したがって、合成ラベルは本物の行動ログを置き換えるものではなく、コールドスタート補助や事前学習に使うものと考えるべきである。

例えば新作 C と D について、十分なログがないため LLM に「この履歴ならどちらがより関連するか」を判定させ、C \succ D に 0.7 の信頼度を付ける。このペアを学習に使うなら、実ログ由来のペアの重みを 1.0、合成ペアを 0.1–0.3 のように低く置く。また、モデルが実ログのみ・実ログ+合成ラベルの二条件で、新作に限定した将来期間の評価を改善するか比較する。もっともらしいラベルを大量に増やすことではなく、未知作品での予測を改善できたかが採用基準である。

LLM を評価者として使う

LLM は、推薦リストの説明可能性や意味的一貫性を評価する補助にも使える。

例えば、次のような観点を LLM に判定させられる。

  • 視聴履歴と推薦リストのテーマが合っているか
  • 推薦理由が自然か
  • 同じような作品ばかり並んでいないか
  • キッズ向けプロフィールに不適切な説明が含まれていないか
  • 新作プロモーションの文脈が不自然でないか

ただし、LLM 評価はオンライン指標の代替ではない。LLM が「良い推薦」と判断しても、実際のユーザーが視聴するとは限らない。LLM 評価は、オフラインでの品質チェックやアノテーション補助として使い、最終的には A/B テストや長期指標で確認する必要がある。

ワークド例: 評価対象を「最近 SF を視聴したプロフィール」とし、推薦 10 件を入力する。LLM には relevancediversitysafety をそれぞれ 1–5 で採点させ、各点に候補 ID を引用した短い根拠を必須にする。たとえば関連性 5、多様性 2 なら、「SF 作品は多いが、上位 6 件中 5 件が同一シリーズ」と機械的に検査できる。この評価は、候補外作品を含めない・根拠がリスト中のメタデータと矛盾しない、といったルールベース検査と組み合わせる。人手評価との一致率を測り、十分に一致する観点だけを品質監視に使う。

オフライン評価

ランキングモデルを学習したら、まずオフライン評価を行う。Hulu の unique_viewed_series を使うなら、時間でデータを分割するのが自然である。

例えば:

  • 学習期間: 2025-10-01 から 2025-12-31
  • 検証期間: 2026-01-01 から 2026-01-31
  • テスト期間: 2026-02-01 から 2026-02-28

学習期間の視聴履歴からユーザー特徴量を作り、検証期間またはテスト期間に 25% 以上視聴された作品を正解として評価する。

評価指標としては、次のものが使える。

  • Recall@K
  • HitRate@K
  • NDCG@K
  • MAP@K
  • MRR
  • Coverage
  • Novelty
  • Diversity
  • Calibration

HitRate@K は、上位 KK 件に正解が 1 件でも含まれるかを見る。

HitRate@K=1UuU1[Ru(K)Yu]\text{HitRate@K} = \frac{1}{|\mathcal{U}|} \sum_{u \in \mathcal{U}} \mathbf{1} \left[ \mathcal{R}_u^{(K)} \cap \mathcal{Y}_u \ne \emptyset \right]

ここで Ru(K)\mathcal{R}_u^{(K)} はプロフィール uu への上位 KK 件推薦、Yu\mathcal{Y}_u は評価期間中に視聴された正解集合である。

ワークド例: あるユーザーの正解集合を Yu={A,C}\mathcal{Y}_u=\{A,C\}、上位 3 件の推薦を Ru(3)=[B,A,D]\mathcal{R}_u^{(3)}=[B,A,D] とする。A が 2 位にあるため HitRate@3 は 1、Recall@3 は 1/2=0.51/2=0.5 である。最初の正解が 2 位なので MRR は 1/2=0.51/2=0.5 となる。複数正解の順位も評価したいなら、A を 2 位に置いた場合の二値 DCG は 1/log2(3)0.6311/\log_2(3)\approx0.631、理想 DCG は 1+1/log2(3)1.6311+1/\log_2(3)\approx1.631 なので NDCG@3 は約 0.3870.387 である。HitRate が 1 でも「正解を十分上位に出せている」とは限らないことが分かる。

Coverage は推薦カタログ全体のうち、少なくとも 1 回推薦された作品の割合である。例えば 1,000 作品中 120 作品しか誰にも推薦されていなければ Coverage は 0.120.12 である。NDCG と併せて見ることで、人気作だけに偏った改善を見逃しにくくなる。

動画推薦では、NDCG@K だけでなく、Coverage や Diversity も見るべきである。NDCG だけを最適化すると、人気作品に寄りやすく、サービス全体の発見性が落ちる場合がある。

オンライン評価

オフライン指標が良くても、オンラインで良いとは限らない。ログにはバイアスがあり、また推薦はユーザー行動に介入するシステムだからである。

オンライン A/B テストでは、例えば次の指標を見る。

  • 推薦枠のクリック率
  • 再生開始率
  • 25% 以上視聴率
  • 総視聴時間
  • 完走率
  • セッションあたり視聴数
  • 連続視聴率
  • 翌日以降の再訪率
  • 解約率または継続率
  • TVOD 購入率
  • ユーザーあたり推薦作品の多様性
  • 苦情、非表示、低評価などの負の反応

重要なのは、短期指標だけで判断しないことである。クリック率を上げるだけなら、派手なサムネイルや有名作品を上げればよいかもしれない。しかし、それが長期満足や継続利用につながるとは限らない。

SVOD では、特に長期的な満足が重要である。短期の再生開始率が少し下がっても、ユーザーが「自分に合う作品を見つけやすい」と感じ、長期継続が上がるなら、そのランキングは価値がある可能性がある。

テスト結果は率だけでなく、対照群との差と不確実性で判断する。例えば対照群の 25% 視聴率が 12.0%12.0\%、処置群が 12.6%12.6\% なら、相対改善は (12.612.0)/12.0=5%(12.6-12.0)/12.0=5\%、絶対差は 0.60.6 ポイントである。これが偶然のばらつきではないかを信頼区間または事前に決めた統計検定で確認する。同時に、非表示率、再生後すぐ離脱率、キッズ不適合の表示数などをガードレール指標として監視する。主指標が伸びてもガードレールを悪化させる変更は、そのまま採用しない。

実務上のランキングパイプライン例

Hulu のようなサービスで、ランキングを実装するときの一例は次のようになる。

  1. item_information_table から、公開中かつブラックリストでない作品を抽出する
  2. unique_viewed_series からプロフィールごとの視聴履歴を作る
  3. 視聴履歴と作品 embedding からユーザー embedding を作る
  4. 候補検索でプロフィールごとに数百から数千件の候補を集める
  5. 候補ごとにランキング特徴量を作る
  6. ランキングモデルで再生開始確率、25% 以上視聴確率、視聴時間期待値などを予測する
  7. 複数目的を統合して初期ランキングスコアを作る
  8. 視聴済み、配信終了、ブラックリスト、レーティング不適合などを除外する
  9. MMR、DPP、ルール、学習済み Reranker でリスト全体を調整する
  10. 棚や画面枠ごとの制約に合わせて最終表示する
  11. 表示ログ、クリックログ、再生ログを保存し、次回学習と評価に使う

1 リクエストを具体化すると、候補検索が 1,000 件を返し、ハード制約で 80 件を除外し、ランカーが残り 920 件にスコアを付ける。上位 50 件を MMR または Reranker に渡し、同一シリーズ上限や棚のルールを適用して 20 件を画面に表示する、という粒度である。ログには少なくとも request_idprofile_id、候補 ID、候補段階、各段階の順位・スコア、表示位置、表示時刻、モデルバージョン、クリック・再生・視聴時間を残す。これがないと、後で「候補に入らなかった」のか「ランカーで下がった」のか「表示されたが選ばれなかった」のかを区別できず、改善もバイアス補正もできない。

ここで重要なのは、ランキングモデルだけで推薦体験が決まるわけではないことである。候補検索で漏れた作品はランキングできない。特徴量が弱ければモデルは判断できない。再ランキングが強すぎればモデルの関連性を壊す。表示ログが不十分なら学習と評価が歪む。したがって、ランキングは単体モデルではなく、推薦パイプライン全体の中で設計する必要がある。

よくある落とし穴

ランキングで起きやすい落とし穴をまとめる。

視聴済みをすべて「好き」とみなす

25% 以上視聴は強い正例だが、必ずしも満足を意味しない。自動再生、家族利用、作業中のながら見、途中離脱などが混ざる。可能なら、視聴完了率、再視聴、次エピソード視聴、低評価、非表示などと組み合わせるべきである。

未視聴をすべて「嫌い」とみなす

未視聴は未観測であり、負の嗜好とは限らない。表示されていなければ視聴機会がなかっただけである。負例サンプリングと表示ログの扱いが重要である。

オフライン NDCG だけを追う

NDCG は重要だが、それだけでは多様性、新規性、カバレッジ、長期満足を捉えきれない。人気作品に寄ったモデルが高い NDCG を出すこともある。

ランキングスコアをビジネス価値と混同する

モデルスコアは目的関数に対する予測であって、絶対的な価値ではない。再生開始率、総視聴時間、継続率、TVOD 購入率、作品露出、公平性など、どの価値を重視するかでスコア設計は変わる。

再ランキングで関連性を壊す

多様性やプロモーションは重要だが、やりすぎるとユーザーに合わない作品が上位に出る。再ランキングは関連性とのバランスが必要である。

配信制約を軽視する

動画配信では、公開開始、公開終了、地域、権利、レーティング、ブラックリストなどの制約がある。これらはモデル以前に守るべき制約である。

まとめ

ランキングは、候補検索で得た作品集合を、ユーザーに提示する順序へ変換する中心的な工程である。ポイントワイズ、ペアワイズ、リストワイズは、ランキング問題をどの単位で学習するかの違いである。ポイントワイズは実装しやすく、ペアワイズは相対順序を学びやすく、リストワイズは NDCG のようなリスト指標に近い最適化ができる。

Hulu のような動画推薦では、主なフィードバックが暗黙的であるため、負例の扱い、表示バイアス、位置バイアスが特に重要である。unique_viewed_series の 25% 以上視聴は有用な正例だが、未視聴をそのまま負例とみなすべきではない。

また、ランキングは単に視聴確率が高い作品を並べるだけではない。SVOD/TVOD、配信期間、ブラックリスト、キッズ適合性、ジャンル多様性、新作露出、長期満足などを含めて、推薦リスト全体を設計する必要がある。

LLM は、作品説明やユーザープロファイルの embedding、コールドスタート補助、少数候補の再ランキング、合成ラベル生成、評価補助として有用である。ただし、本番ランキングの主役として使うには、レイテンシ、コスト、安定性、実ユーザー行動との乖離に注意が必要である。

実務的には、ランキングは「モデルを 1 つ作る話」ではなく、「候補検索、特徴量、学習ラベル、負例サンプリング、スコア統合、再ランキング、制約処理、ログ設計、評価」を一体で作る問題である。この全体設計の良し悪しが、ユーザーが Hulu 上で「次に見たい作品を自然に見つけられるか」を大きく左右する。