X運用 · 公開アルゴリズム · 第4回

SimClustersは「所属」の仕組みではない

Xのおすすめには、フォローしていない人の投稿が混ざってきますよね。あれがどうやって選ばれているか、知っていますか? 答えの1つが「SimClusters(シムクラスターズ)」という仕組みです。ざっくり言うと、「あなたが最近反応した(いいね・リポストなどをした)投稿と、視聴者層が同じ投稿」を探してくる仕組み。公開されたコードから、その中身を読み解きます。

「おすすめ解剖」シリーズの第4回です。第1回でThunder(フォロー中の人の投稿を集める係)、第2回でPhoenix(AIで候補を集めて並べる係)、第3回でセマンティックID(投稿の「中身」を住所に変える仕組み)を見てきました。今回は、候補集めの3本目、SimClustersです。

かなり分かりにくい仕組みなので、今回は数式や名前をいったん横に置いて、たとえ話を1本通して説明します。いつも通り、コードで確認できた事実を軸に書きます。たとえ話は理解のためのもので、コードにそう書いてあるわけではありません。

まず、よくある勘違いから

SimClustersという名前は、2023年に旧Twitterがコードを公開した時にも話題になったので、「自分がどこかのクラスターに所属していて、その所属の関係でおすすめに出る仕組み」と理解している人が多いと思います。

今のコードを読む限り、それは違います。

  • おすすめ候補を探す手がかりは「あなたが最近反応した投稿」であって、「あなたの所属クラスター」ではない
  • 投稿がどこに置かれるかを決めるのは「その投稿に誰がいいねしたか」であって、「投稿者の所属クラスター」ではない
  • 「所属」という登録は確かにコードにあるが、それは上位2,000万人の有名アカウントだけの話(1人1クラスター)で、使われる場所は「他人の興味を測る物差し」としてだけ。本人のおすすめにも、本人の投稿にも、直接は効かない(後半で説明します)
  • それ以外の人と、すべての投稿は、どこかに「所属」するのではなく、「料理に強く、野球に少し」のように、複数のクラスターへの濃さで表される

つまり「自分がどのクラスターに入っているか」を気にしても、おすすめは動きません。動くのは「あなたが最近何に反応したか」と「あなたの投稿に誰がいいねしたか」です。この記事は、そこを軸に読んでください。

3つの候補集め係——Thunder・Phoenix・SimClustersの決定的な違い

おすすめの処理は「候補を集める → 順位を付ける」の2段階です。候補集めは3つの係が並列で動いて、順位付けはPhoenixのAIが1回でまとめて行います。3つの係は、見ているものがまったく違います。

  • Thunder(第1回): フォロー中の人の投稿を、新着順にそのまま。最大1,200件。内容も興味も見ない
  • Phoenix検索(第2回・第3回): あなたの行動履歴(最大1,024件)から「あなた」を盤に置き、投稿の中身(セマンティックID)と投稿者情報で近い投稿を探す。最大1,000件。しかもPhoenixは順位付けも担当する
  • SimClusters(今回): フォロー関係を見ない。あなたが最近反応した投稿を起点に、「視聴者層が同じ投稿」を探す。48時間以内、最大800件。順位付けには関わらない(結果にフォロー中の人の投稿が混ざることもあるが、Thunderと重なれば1つにまとめられる)

一言で言えば、Thunderは「誰をフォローしているか」、Phoenixは「何に反応してきたか(中身)」、SimClustersは「反応した投稿に、どんな人がいいねしていたか(人)」で候補を集める係です。

たとえ話: 番組と、出演者と、視聴者

SimClustersを理解するために、言葉を3つだけ使います。番組、出演者、視聴者です。

【番組 = クラスター】

Xには、フォロワーの多い有名アカウントが上位2,000万人います。Xはこの2,000万人を「同じ人たちにフォローされている者同士」でまとめて、14.5万個のグループにします。このグループが「クラスター」です。この記事では「番組」と呼びます。

番組の正体は「有名アカウントの出演者名簿」です。料理番組には料理アカウントが、野球番組には野球アカウントが、猫番組には猫アカウントが出演している、という感じで、実質的にジャンル(界隈)ごとの名簿になっています。この記事では分かりやすく「料理番組」「野球番組」のように大きなくくりで説明します。

注記: 実際の番組はもっと細かく分かれています。料理なら「フレンチ」「イタリアン」「お弁当」くらいの単位で別の番組になっていて、全部で14.5万番組、1番組平均138人(2,000万÷14.5万の割り算で、実際の番組は大小のばらつきがあります)。ただしXが「これは料理」と名前を付けているわけではなく、番号だけで管理されていて、出演者の顔ぶれで実質ジャンルになっている、という形です。一覧は公開されていません。なお、この仕組みのモデル名は「20M_145K_2020」です。2,000万人(20M)・14.5万番組(145K)と、2020年という世代名が入っていて、出演者登録のバッチの開始日もコード上「2020-10-04」に設定されています。そしてこの世代のモデルが、今のおすすめ(home-mixer)で指定されています。つまりSimClustersは、2020年に作られた世代の仕組みが今も使われている、ということです。なぜ新しい世代に置き換わっていないのかはコードに書かれていませんが、後半で作りから読める推測を書きます。

【出演者 = 上位2,000万人のアカウント】

有名アカウントは、どれか1つの番組の出演者として登録されます。1人1番組だけ(コードでは「KnownFor」)。出演者になれるのは、上位2,000万人だけです。

【視聴者 = 興味リスト】

あなたが、ある番組の出演者を2人以上フォローしたり、いいねしたりしていると、あなたはその番組の「視聴者」とみなされます。何番組の視聴者でもかまいません(最大50番組)。しかも「料理番組は濃い80%、野球番組は薄い30%」のように、濃さ付きです。

これがあなたの「視聴者リスト」です(コードでは「InterestedIn」= 興味リスト)。上位2,000万人でなくても、条件を満たせば誰でも持てます。逆に、出演者2人以上とつながっていない人は持っていません(コードにも「視聴者リストが空の人」を数えるカウンターがあります)。

ここで「視聴」という言葉に注意してください。テレビと違って、見ているだけでは視聴者に数えられません。 数えられるのは、出演者をフォローすること、出演者の投稿にいいねすること、この2つだけです。

  • 「2人以上」は人数です。同じ出演者に何回いいねしても1人分。別々の出演者2人とつながって初めて視聴者になる
  • フォローといいねはどちらでもよく、混ぜてもよい。出演者Aをフォロー+出演者Bにいいね、でも2人。フォローなしで、AとBの投稿にいいねしただけでも2人
  • 濃さは、主にいいねで決まる。フォロー由来・いいね由来・いいねのlog版の3種類が別々に計算され、50番組に絞る時の優先順位はいいね由来が先。フォローだけだと薄い
  • いいねの重みは100日で半減する。最近いいねしている番組ほど濃い
クラスターのしくみ
クラスター=番組。出演者(上位2,000万人・1人1番組)と視聴者(誰でも・濃さ付き)は別の話

ここが一番の混乱ポイントなので、はっきり書きます。「番組の出演者」と「番組の視聴者」は別の話です。

  • 出演者になれるのは、上位2,000万の有名アカウントだけ。1人1番組
  • 視聴者には、上位2,000万人でなくてもなれる(条件は出演者2人以上とのつながり)。何番組でも
  • 有名アカウントは、どこかの番組の出演者であると同時に、別のいくつもの番組の視聴者でもある

普通のアカウント(あなた)は出演者ではありませんが、いろんな番組の視聴者です。これが「クラスターに所属していないけど、興味リストはある」という状態です。

そして、もしあなたが上位2,000万人に入っていれば、構造的には「どこかの番組の出演者名簿に名前がある」状態です。ただしその名簿は、世界中の人と投稿の座標を測るための枠組み(物差し)であって、あなた自身の投稿の伸び方には直接関係しません。ここは後でもう一度書きます。

【投稿の座標 = いいねした人たちの視聴者リストの合計】

投稿にいいねが付くと、いいねした人たちが、それぞれ「どの番組の視聴者か」を持っています。それを足し合わせると、その投稿の「視聴者層」が決まります。

料理番組の視聴者ばかりがいいねしているなら、その投稿は「料理番組寄り」。料理番組の視聴者と、ダイエット番組の視聴者が半々なら、その中間。これが投稿の「座標」です。

投稿者が誰か、投稿者がどの番組の出演者か、何が書いてあるか——は一切出てきません。いいねした人の顔ぶれだけで座標が決まります。

3語で言い直すと

  • クラスター(番組)の役割は、誰でも「どの番組の視聴者か」というラベルを持てるようにすること。視聴者のグループを作ること
  • それを元に、投稿に座標を持たせる。投稿の座標 = いいねした人の視聴者ラベルの合計
  • おすすめは、あなたが最近反応した投稿の座標の近所にある投稿を拾ってくる

第3回で見たセマンティックIDは「中身で決まる住所」でした。今回の座標は「いいねした人の顔ぶれで決まる座標」。投稿は、住所と座標の2つを持っている、と思ってください。

結論から: SimClustersは「視聴者層が同じ投稿を連れてくる係」

結論だけ先に言うと、SimClustersの仕事はこれです。

「あなたが最近反応した投稿」を手がかりに、「視聴者層が同じ(座標が近い)投稿」を最大800件探してくる。

ただし、探す範囲には関門があります。SimClustersは、番組ごとに「その番組の視聴者から今いいねされている投稿」のランキングを持っていて、候補として拾われるのは、そのランキングで上から800位以内の投稿だけ。それより下の投稿は、座標がどんなに近くても連れてこられません。この順位は「連れてくるかどうか」の資格であって、連れてきたあとの並び順(近さ)には関係しません。詳しくは後半で書きます。

そして、もう1つ大事なこと。SimClustersは、おすすめの順位を決めていません。

たとえるなら、オーディション会場に「この子、あなたの好みに合いそうなので呼んでおきました」と連れてくる係です。連れてきた800件は、Thunderの候補やPhoenixの候補と同じ列に並んで、そのあとPhoenixのAIが順位を付けます。SimClusters出身だから有利・不利という扱いはありません(フォロー外の投稿に共通の係数0.75は掛かります。これはPhoenix検索で拾われたフォロー外の投稿も同じです)。

つまりSimClustersは、「伸ばす・伸ばさない」を決める採点官ではなく、「あなたの近くにありそうな投稿」を候補として連れてくる探索係です。

おすすめの中での流れ(1枚の図)

おすすめ候補の選ばれ方
①最近反応した投稿(9種類・各15件・最大135件) → ②そのコマの場所 → ③近くのコマだけ拾う → ④交互に混ぜて最大800件 → Phoenixが順位付け

具体的な流れを、文字でも書いておきます。

あなた
↓ 最近の行動
反応: 投稿A
反応: 投稿B
反応: 投稿C

それぞれの投稿の「座標」を調べる

Aの座標の近所 → A1, A2, A3…
Bの座標の近所 → B1, B2, B3…
Cの座標の近所 → C1, C2, C3…

A1, B1, C1, A2, B2, C2… と交互に混ぜる

最大800件を「おすすめ候補」として提出

Thunder・Phoenixの候補と合流

Phoenixが順位付け

あなたのおすすめへ

コードで確認できる数字を添えます。

「最近の行動」に入るもの(それぞれ新しい順に最大15件):

  • いいね、リポスト、返信、ブックマーク、共有した投稿
  • 自分が投稿したもの
  • 拡大して見た写真
  • 動画の視聴(通常と没入型の2種類。コード上の条件は「動画の長さが10秒以上」で、視聴秒数の条件ではない)
おすすめ側の条件
根拠のコード(読み飛ばしてOKです)。1手がかりあたり200件、上位50番組、48時間以内、類似度0.5超、最終800件
https://github.com/xai-org/x-algorithm/blob/28e414f/home-mixer/sources/simclusters_source.rs#L24-L35

近所を探す時の条件:

  • 探す範囲は、手がかりの座標の上位50番組それぞれの「今伸びている投稿リスト」の中だけ。このリストは、その番組の視聴者からのいいねの合計スコア(8時間で半減)の高い順で、おすすめ側が見るのは上から800件。つまり関門は、その番組で上から800位に入ることです(コード上、リスト自体は1,600件保持されていますが、おすすめが見るのは上から800件なので、この記事では800で統一します。最後に持ち帰る「最大800件」とは別の数字です)。スコアは「いいねした人の、その番組での濃さ」を足していくので、濃い視聴者のいいねほど大きく足され、その番組以外の視聴者のいいねは一切足されない。順位は「その番組の濃い視聴者から、最近どれだけいいねされたか」で決まる。リストに入っていない投稿は、座標がどんなに近くても拾われない(図の「今伸びている投稿」の掲示板)
  • 1つの手がかりにつき、最大200件
  • 投稿されてから48時間以内のものだけ
  • 視聴者層の似ている度合い(コサイン類似度という数)が0.5を超えるものだけ
  • 全部合わせて、持ち帰るのは最大800件まで(上の「各番組の上から800件」とは別の数字)
800位の関門
候補として取られるのは、各番組のランキング(濃い視聴者からの最近のいいね合計、8時間で半減)で上から800位まで。順位は資格で、取られたあとの並び順は近さだけ
  • 手がかりとして機能するのは、いいねの総数が8件以上の投稿だけ(公開コード上)。7件以下の投稿に反応しても、その投稿は起点用の埋め込みを持たないので、そこからは候補がゼロになる。図で言えば「コマは盤にあるが、光らない」

「交互に混ぜる」も、コードにそのまま書いてあります(interleave = 交互配置)。Aの近所を全部出してからB…ではなく、A1、B1、C1、A2…と順番に取る。なので1つの投稿に強く反応したからといって、800件全部がその仲間で埋まることはありません。たとえるなら、最近の興味を何本かの釣り竿にして、それぞれから少しずつ釣ってくる感じです。

具体的な数で言うと、手がかりは最大9種類×15件=135件(いいね・リポスト・返信・ブックマーク・共有・自分の投稿・写真の拡大・動画視聴・没入型動画視聴)。1件につき最大200件取り、全体の上限10,000件を手がかりの数で等分します(135件あれば1件あたり約74件)。それを交互に取って800件に切るので、手がかりが135件あるなら、1件あたり平均6件弱しか最終候補に残らない計算です。逆に反応履歴が少ない人は、1件の手がかりから多く拾われます。

1つ注意。手がかりは「あなたの最近の反応」そのものなので、反応履歴がゼロの人にはSimClustersが動きません。9種類の手がかりがすべてゼロのアカウントでは、この候補源からは何も出てきません。

もう1つ、大事なこと。閲覧者としてのあなたの視聴者リストは、ここでは使われていません。 「あなたが料理番組の視聴者だから料理の投稿が来る」という経路は、SimClustersにはありません。来るのは「あなたが最近反応した投稿の、コマの近く」だけ。あなたの視聴者リストが使われるのは、あなたが誰かの投稿にいいねして、その投稿の座標を動かす時だけです。

「視聴者層が同じ」は、文章が似ているという意味ではない

ここがいちばん誤解されやすいところです。

SimClustersの「座標が近い」とは、同じ単語が入っている、という意味ではありません。

「今日のマンチェスター戦すごかった」

「このゴールは何回見ても鳥肌立つ」

文章だけ見ればほとんど違います。でも、同じサッカー番組の視聴者たちがいいねしているなら、座標は近い。

逆に、まったく同じ文章の投稿が2つあっても、片方にいいねしたのが料理番組の視聴者、もう片方にいいねしたのが投資番組の視聴者なら、座標は遠い。

つまりSimClustersの座標は、投稿を「何が書いてあるか」で並べたものではなく、「どんな人が集まったか」で決まるものです。第3回のセマンティックID(中身で住所を決める)との決定的な違いがここです。

投稿の座標は、どうやって決まるのか(数字)

座標の決まり方は上に書いた通り「いいねした人の視聴者ラベルの合計」です。図にするとこうなります。

投稿の座標の決まり方
投稿の座標=いいねした人の視聴者ラベルの合計。投稿者も文章も見ない(数字はイメージ)

コードから分かる基本ルールを並べておきます。

投稿の座標が決まる条件
根拠のコード。半減期8時間、投稿1件あたり内訳は上位400番組分、番組1つあたり上位1,600投稿(おすすめが見るのは上から800件)、手がかりになる最低いいね数8件
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/summingbird/common/Configs.scala#L39-L65
  • ロープは、視聴者のいいね1件目から付き始める
  • 足されるのは、いいねした人の視聴者リストのうち、濃さ(いいね由来のスコア)が0.3以上の番組だけ。視聴者でない人(出演者を2人以上フォロー・いいねしていない人)のいいねと、0.3未満の番組しか持たない人のいいねは、ロープにならない
  • 出演者(上位2,000万人)のいいねも、普通の人のいいねと同じ扱い。その人自身の視聴者リストが足されるだけで、出演者だから重いということはない
  • 座標のスコアは8時間で半分に減っていく。いいねが止まると、座標がどんどん薄れる
  • 投稿してから3日を過ぎると、もう更新されない
  • 自分の投稿に自分でいいねしても、座標(ロープ)には数えない。ただし「光る」条件の8件は公開のいいね数で数えるので、そちらにはセルフいいねを除外する処理は確認できない
  • いいねを取り消しても、一度足された分は引かれない(取り消しを処理するコードがありません)
  • コマの場所は1つ。その場所を決めている「どの番組の視聴者がどれだけいいねしたか」の内訳(綱引きの図のロープ)は、太い順に最大400番組分まで記録される。検索の時に見るのは、手がかり側の投稿のロープのうち太い50本。つまり投稿者側の入口は最大400、閲覧者側が1回の検索で見るのは50

【投稿の3つの状態】

投稿には3つの状態があって、条件がそれぞれ別です。

  • 「座標がある」= 盤の上に位置がある。視聴者のいいね1件目から付く
  • 「見つかる」= 他人の手がかりから候補として拾われる。条件は、その番組のランキング(おすすめが見る、上から800件の範囲)に入る太さがあること。候補は必ずこのランキングから取られるので、どんなに向きが良くても、入っていない投稿は拾われない
  • 「光る」= 誰かがその投稿に反応したとき、近所探しの起点になれる。条件は、手がかり用の埋め込み(永続版)があること。これは公開コード上、いいねの総数が8件以上の投稿にだけ作られる。埋め込みが無い手がかりからは候補がゼロになる。この8件は公開のいいね数で数えるので、誰のいいねでもよい(視聴者でなくても数える)

「見つかる」の条件が、投稿者にとっていちばん大事です。番組のランキングは「その番組の視聴者からのいいねの合計スコア(8時間で半減)」の高い順なので、実質、同じ層からのいいねがそれなりに集まらないと、SimClusters経由では選ばれません。野球ファン1万人のいいねは、料理番組のランキングには1ミリも効きません。

ただし、このハードルは絶対数ではなく相対的なものです。競争相手はXの全投稿ではなく、同じ番組の、48時間以内の、今いいねが付いている投稿だけ。8時間で半減するので順位は常に入れ替わり、1つの投稿は最大400番組のランキングに同時に載れます(料理の投稿なら、お弁当・時短・節約…それぞれの番組で別々に予選がある)。どのくらい高いかは番組の大きさで天地の差で、ニッチな番組(平均138人の出演者の界隈)なら、48時間にその層からいいねが付く投稿が800件に満たないことも普通にあるはずで、その場合は濃い視聴者のいいねが1件でもあれば圏内。巨大な番組では何千件も競合します。一番厳しいのは「小さなアカウントが、大きなメジャー番組で勝負する」形で、自分の界隈の番組で勝負するなら見た目ほど高くない。ただし番組ごとの投稿数は公開コードから分からないので、数字では言えません(ここは解釈)。

桁感だけ、概算で書いておきます(コード外の数字を使った概算で、解釈です)。Xの投稿数は1日あたり約2億件と言われています。48時間なら約4億件。これを14.5万番組で単純に割ると、1番組あたり約2,740件。1つの番組に特化したとしても、その番組の中で48時間に流れる投稿はこの規模で、そのうち上から800件だけが「選ばれる可能性がある」投稿です。この2,740件のうち、その番組の濃い視聴者のいいねが付かなかった投稿(ロープが付かない投稿)は、ランキングに入らず自動的に圏外。ロープが付いた投稿同士で、上から800位を争います。人気の番組には投稿が集中するので、門はさらに狭くなります。あくまで「1つの番組の中の競争は、だいたいこの桁」という目安です。

【予選は太さ、本選は向き】

SimClustersは2段階です。予選が「太さ」(その番組のランキングに入れるか)、本選が「向き」(ランキングに載った投稿の中で、どの手がかりの仲間として、どの順で拾われるか)。本選で比べるのは、全体の太さそのものではなく、各番組のスコアの配合(向き)が手がかりの投稿とどれだけ似ているか。料理90・猫10と料理900・猫100は同じ向きなので似ている度合いも同じ、料理900・猫500は配合が違うので変わる。予選を通らないと本選に出られません。

そして、予選と本選は「別の軸」で動いています。予選(ランキング)は1つの番組の中の話です。いっぽう「座標の近さ」は、1つの番組の中では差が出ません。パスタ番組の視聴者だけがいいねした投稿は、全部「パスタ100%」で向きが同じなので、近さは全部1.0で区別がつかない。座標に意味が出るのは、いいねした人の配合が番組をまたいで違うときだけです。たとえばカルボナーラ系の投稿は「パスタ視聴者70%・卵料理視聴者30%」、ペペロンチーノは「パスタ90%・ニンニク料理10%」のように配合が違うから、手がかりが「パスタ65%・卵料理35%」の投稿なら、パスタ番組で1位のペペロンチーノより、500位のカルボナーラの方が近くて先に選ばれる。「ランキングは番組の中の順位、近さは番組をまたいだ配合の一致度」——この2つが別々に動くので、「1位なのに後回し」「500位なのに先」が起きます。

なお、近さは「同じ人がいいねしたか」(人の重なり)を数えているのではありません。見ているのは配合です。同じ人がいいねしていれば配合は当然同じになるので結果は一致しますが、別の人たちでも配合が同じなら近くなります。

【濃さと一途さは別物】

いいねした人の「濃さ」と「一途さ」も、効く場所が違います。

  • 濃さ = その人が、その番組の出演者をどれだけフォロー・いいねしているか。番組ごとに別々に決まり、他の番組にも濃いかどうかは関係ない。濃さは、その番組のロープの太さに効く(予選)
  • 一途さ = その人が、その番組だけに濃いか、他の番組にも濃いか。これは配合に効く(本選)。カルボナーラ番組だけに濃い人のいいねは、カルボナーラのロープだけを太くする。パスタにも卵料理にも濃い人のいいねは、3本のロープを同時に太くして、向きを散らす
  • 薄い人(0.3未満)のいいねは、どちらにも効かない

同じ番組への濃さが同程度なら、他の番組への濃さが少ない人ほど、その番組の向きをそろえやすい。ただし太さはあくまで「その番組への濃さ」で決まるので、料理0.9・投資0.8の人と料理0.4だけの人なら、一途なのは後者でも、料理のロープを太くするのは前者。濃いけど一途でない人(料理全般に濃い)のいいねは、太さには効くが向きを散らす。現実には視聴者1人が最大50番組の濃さを持つので、1番組だけの配合の投稿はまずなく、どの投稿も複数の番組にまたがる配合を持ちます。

【投稿者目線で通して見ると】

「カルボナーラ温玉のせ」を投稿したとします。いいねした人の配合次第で、パスタ・カルボナーラ・卵料理などの番組にロープが伸びます(投稿の内容ではなく、誰がいいねしたかで決まる)。それぞれの番組の濃い視聴者からのいいねが多いほど、その番組のランキングで上がり、上から800位に入れば、その番組の手がかりを持つ人の候補になります。入口は最大400番組分。カルボナーラ激推しの人のいいねが多ければ、カルボナーラのロープが太くなって向きもカルボナーラに寄る。パスタ好き・卵料理好きくらいの人が同じ人数いいねしても、カルボナーラのロープへの寄与は小さい。そして閲覧者が「別のカルボナーラ温玉の投稿」に反応したとき、その投稿のロープの太い50番組が検索され、各番組の800位以内から、配合が近い順に拾われる。ペペロンチーノがパスタ番組で1位でも、配合が違えばカルボナーラより後になります。

つまり、カルボナーラに一途な人からのいいねが増えるほど、カルボナーラ番組のロープが太くなってランキングが上がり、配合もカルボナーラに寄って、カルボナーラ寄りの手がかりからは拾われやすくなる。その分、配合の中で卵料理の割合は下がるので、卵料理寄りの手がかりからは遠ざかる(卵料理のロープ自体は細くならないので、卵料理番組のランキングは変わらない。変わるのは近さの方)。太さは番組ごとに積み上がり、向きは配合で決まる——投稿者から見たSimClustersは、この2つの掛け合わせです。

【いいねの数は何に効くか】

「8時間で半減」は、言い換えると「いいねが続いている投稿ほど、座標がはっきりする」ということです。勢いが止まった投稿は、数時間でぼやけていきます。

半減の時間軸
縦軸は1つの番組でのスコア(その番組の視聴者からのいいねの合計)。いいねが止まると8時間で半分ずつ。おすすめが見る上位800件から外れた時点で候補から消える。48時間で打ち切り

ここで「いいね8件」と「いいね80件」の違いを整理しておきます。

  • 8件は「光る(手がかりになれる)条件」。8件未満の投稿は、候補として拾われることはあっても、誰かの反応から近所を探す起点にはならない
  • 同じ配合の視聴者のいいねなら、何人いいねしても座標の「向き」は変わらない。実際は人ごとに配合が少しずつ違うので、件数が増えれば向きも少しずつ動くが、検索が見ているのは向き(コサイン類似度)であって件数ではない。8件でも80件でも、向きが同じなら「仲間度」は同じ
  • 変わるのは「番組のランキングに入りやすさ・順位・残りやすさ」。その番組の視聴者からのいいねが多いほど800位以内に入りやすく、長く残り、途切れると押し出されて候補から消える(他の番組の視聴者のいいねは、この番組のスコアには足されない)
  • 逆に、いろいろな番組の視聴者からいいねが付くと、ロープが多方向から伸びてコマは真ん中寄りになる。元の番組の視聴者の仲間としては拾われにくくなる一方、ロープがつながった番組それぞれのランキングに名前が載りうるので、別の層の仲間として拾われるようになる(ここは解釈。SimClusters経由の露出が減るとは限らず、「層が変わる」と読むのが正確です)
割合と太さ
ロープの割合(向き)はどの投稿の仲間かを決め、太さ(絶対量)はランキングに入れるか・残れるかを決める。数字はイメージ

盤のたとえの限界を1つ書いておきます。盤は2次元なので「猫番組に引っ張られると犬番組から遠ざかる」ように見えますが、実際は番組ごとに別の方向があり(14.5万方向)、猫のロープが増えても犬のロープは細くなりません。犬番組のランキングでの順位も変わりません。変わるのは「割合」です。内訳そのものは絶対量(いいねの合計スコア)で記録されていますが、似ている度合い(コサイン類似度)を出す時には向き、つまり割合だけが使われます。犬一色の投稿と比べると、犬100%なら似ている度合いは1.0、犬50%・猫50%なら0.71(まだ犬の仲間)、犬25%・猫75%なら0.32(0.5を割って、犬寄りの投稿の近所としては拾われない)、という具合です。角度で決まる数なので、50%で0.5にはなりません。ロープの太さ(絶対量)は「ランキングに載るか・残るか」に効き、ロープの割合(向き)は「どの投稿の仲間として拾われるか」に効く。この2つは別物です。

【コマを動かすのはいいねだけ】

もう1つ、投稿者側から見て大事なこと。投稿の座標を動かすのは、いいねだけです。座標を作る処理の入力はいいねイベントのみで、リポスト・返信・ブックマーク・閲覧・動画視聴では座標は動きません。閲覧者側の手がかりにはリポストや写真拡大も入るので、ここは非対称です。読者は何で反応しても手がかりになるが、投稿者のコマを動かすのは読者のいいねだけ。ただしこれはSimClustersの中だけの話で、リポストや返信は他の場所(Phoenixの順位付けなど)では効きます。「リポストは無意味」という意味ではありません。

コマを動かすのはいいねだけ
SimClustersの座標を動かすのはいいねだけ。リポスト・返信・ブックマーク・閲覧は動かさない。投稿ごとにゼロから

ここからは解釈ですが——この作りだと「初速」が効きます。番組ごとのランキング(おすすめが見るのは上から800件)は8時間で半減するので、いいねが止まった投稿は押し出されていきます。つまり「最初の48時間に、同じ視聴者層から集中していいねが付き続けること」が、SimClusters経由で拾われる条件に直結する、と読めます。

視聴者の決まり方と、番組の決まり方(数字)

視聴者(興味リスト)の条件:

視聴者の条件
根拠のコード。週次・過去30日、根拠2人以上、最大50番組
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/scalding/InterestedInFromKnownFor.scala#L66-L67
  • その番組の出演者を2人以上フォロー・いいねしていないと、視聴者にならない。「1人だけフォローしている分野」は興味リストに入らない
  • 1人が持てるのは最大50番組まで
  • 週に1回更新。いいね由来の重みは100日で半減(フォロー・いいねの履歴をいつまで見るかの期間は、公開コードからは確定できない)

番組(クラスター)の条件:

番組作りの条件
根拠のコード。アクティブフォロワー400人以上、上位2,000万人、最大3エポック
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/scalding/update_known_for/UpdateKnownFor20M145K2020.scala#L57-L65
  • アクティブフォロワー400人以上のアカウントを、上位2,000万人分
  • 「誰にフォローされているかが似ている人同士」をまとめて14.5万番組。つまり番組の形を決めているのは、2,000万人の「フォロワー構造」
  • 出演者登録は1人1番組だけ。複数に当てはまっても、いちばんスコアの高い1つだけ残る
  • 週に1回、更新

2,000万人の役割——「物差し」であり、バズの起点にもなりやすい

ここまでをつなぐと、2,000万人の役割がはっきりします。

2,000万人は、すべての人と投稿を測るための「物差し」です。あなたの興味は「どの番組の出演者を何人フォローしているか」で測られ、投稿の座標は「いいねした人がどの番組の視聴者か」で測られる。つまり一般ユーザーの興味も、投稿の座標も、全部「2,000万人の有名アカウントとの距離」で表現されています。有名アカウントが座標軸そのものです。

バズを作っているのは誰か、という問いに対しては、こう整理できます。

  • 座標軸を作っているのは2,000万人(彼らのフォロワー構造)
  • 投稿を動かしているのは、いいねした人(誰でも)。ただし「どこかの番組の視聴者」である人のいいねだけが効く
  • つまり「有名アカウントのフォロワーたちが、まとまっていいねすると、投稿はその番組の座標にくっきり置かれる」

ここからは解釈ですが——有名アカウントのフォロワーには、同じ番組の他の出演者もフォロー・いいねしている人が多い(だからこそ同じ番組にまとめられている)。そういう人はその番組の濃い視聴者なので、その人たちがいいねする有名アカウントの投稿は、最初から座標がくっきりしやすい。そのぶん番組の上位リストに乗りやすく、同じ番組の投稿にいいねした人たちのおすすめに出やすい。その意味で「2,000万人がバズの起点になりやすい構造」は、コードから読めます。

そして、ここで必ず出る疑問。「2,000万人に入っていない人は、どうなるの?」

コード上、登録の有無であなたのおすすめや、あなたの投稿の座標が変わる処理はありません。「不利にならない」は、その意味での評価です。出演者登録が使われる場所は「他人がどの番組の視聴者かを測る時」だけです。あなた自身のおすすめにも、あなたの投稿の座標にも、あなたの登録は使われません。登録されている意味は1つだけで、しかも「自分のため」ではなく「他人の興味を測るため」。あなたをフォローしたり、あなたの投稿にいいねしたことが、その人の視聴者リストを計算する材料の1つになる(出演者2人以上の根拠のうちの1人分)——それだけです。あなたをフォローしただけで、その人があなたの番組の視聴者になるわけではありません。あなたが2,000万人に入っているなら、あなたはその物差しの目盛りの1つだ、ということです。

では、登録されていない普通のアカウントの投稿はどうなるか。投稿の座標はいいねした人で決まるので、普通に座標が付きます。ただし、いいねした人の顔ぶれは自分でコントロールできません。

  • 有名アカウントAさん(料理番組の出演者)の投稿: Aさんのフォロワーの中に、同じ料理番組の他の出演者もフォロー・いいねしている人が多ければ、料理番組の濃い視聴者が集まりやすい → その人たちがいいねすると、座標が料理番組にくっきり
  • 普通のBさん(フォロワー300人)の投稿: いいねした人の顔ぶれは、Bさんのフォロワーが「他に誰をフォローしているか」で決まる。料理好きばかりならAさんと同じ扱い。友達・知り合いばかりなら座標がぼやける

平たく言うと: 登録されていなくても盤には乗れる。でも、同じ番組の視聴者に囲まれていないと、座標が定まらない。

ここから分かる通り、SimClustersの投稿の座標には、投稿者自身の過去投稿の実績を直接引き継ぐ仕組みがありません。投稿1件ごとに、その投稿にいいねした人のラベルだけで、新しく座標が作られます。前の投稿の座標は次に引き継がれず、投稿者自身の視聴者リストも出演者登録も、自分の投稿の座標には使われません。投稿者として積み上がるのは「自分のラベル」ではなく、「自分にいいねしてくれる人たちのラベルのそろい方」だけです。

Phoenixとの違い——SimClustersは「候補集め」にしか使われない

おすすめの処理は「候補を集める → 順位を付ける」の2段階で、Phoenixは両方、SimClustersは候補集めだけです。SimClustersの800件は他の候補と同じ列に並んで同じ条件で採点されます(フォロー外の投稿に共通の係数0.75が掛かるだけで、Phoenix検索で拾われたフォロー外の投稿も同じです)。

候補集めの段階での違いは、「置き場所の決め方」です。

  • Phoenix検索: 置き場所は投稿の中身+投稿者の情報(第3回の住所)。あなた自身も盤に置かれ、あなたの近所の投稿を探す。つまり「あなたに合いそうな内容」を探す
  • SimClusters: 置き場所は「いいねした人の顔ぶれ」(今回の座標)。あなたは盤に置かれず、あなたが最近反応した投稿の近所を探す。つまり「あなたの仲間が読んでいるもの」を探す

映画で言えば、Phoenixは「この人の視聴履歴を見ると、この映画が好きそう」。SimClustersは「この人が昨日見た映画Aが好きなら、映画Aと同じ客層に人気の映画を持ってこよう」。

周期(鮮度)の違いも整理しておきます。

  • SimClusters: 投稿の座標はいいねが付くたびに更新(8時間で半減、3日で停止)。検索結果は10分キャッシュ。視聴者リストと出演者登録は週に1回
  • Phoenix: 投稿が検索の索引に載るまでの時間は、公開コードからは分からない。読者側は、リクエストのたびに直近1,024件の行動から計算
  • 候補の年齢は、どちらも48時間以内(全候補に共通のフィルタ)

ここから読めることが1つ。Phoenixは行動履歴(最大1,024件)をまとめてモデルに入れ、「あなた」の位置を作ります。新しい1件がその位置をどれだけ動かすかはモデル次第で、コードからは言えません。SimClustersは、反応した投稿1件1件がそれぞれ独立した検索起点(釣り竿)になります。反応した投稿に手がかり用の埋め込みがあれば(公開コード上、永続版はいいね総数8件以上)、次の検索からその近所が候補に入ります(検索結果は手がかりの投稿ごとに10分キャッシュされますが、新しく反応した投稿は別の手がかりとして追加されるので、その投稿のキャッシュが無ければ次のリクエストから検索されます)。「さっき反応した投稿の仲間が、おすすめに増える」という体感は、この作りと整合します。ただし「Phoenixより敏感」と数字で比べることはできません。反応履歴の使い方が違う、までが言えることです。

なぜ2020年世代の仕組みが最新AIの隣で現役なのかは、コードに理由は書かれていません。ただ、作りから読めることがあります(ここは解釈)。今のおすすめが使っているのは2020年世代のデータ(番組・視聴者リスト・投稿の座標)そのものですが、使い方が変わっています。読者自身の視聴者リストを起点にして「あなたの番組の投稿」を届ける経路——2023年の公開時に「所属で届く」と理解された形——は、今のhome-mixerにはありません。残っているのは、反応した投稿同士の近さと、番組ごとの勢い(ランキング)だけ。つまり2020年に作られたデータを、「所属」ではなく「勢い」を拾う道具として使い直している。Phoenixが中身(住所)を見るのに対し、SimClustersは「今どの層で伸びているか」を8時間単位で拾う。中身と勢い、2つの物差しが補い合う形になっていて、古い世代の仕組みが今の設計に合っているから残っている——そう読めます。

SimClustersから読める、バズの構図(解釈)

SimClustersは、界隈ごとの「今伸びている投稿群」の中から、あなたが最近反応した投稿と視聴者層が近いものを見つける仕組みです(「その界隈の人だから配る」のではなく、「あなたが反応した投稿と近いから見つかる」)。バズを起こす装置ではなく、伸び始めたものをさらに伸ばす方向に働く装置。言い換えると、今のSimClustersは「つながり」で候補を集める仕組みではなく、「勢い」で候補を集める仕組みです。閲覧者側の起点はあなた自身のつながり(視聴者リスト)ではなく最近反応した投稿で、投稿側も誰が書いたかではなく今誰にいいねされているか。届く条件は、誰とつながっているかではなく、今その層にどれだけいいねされているか。手軽ではない代わりに、乗れば同じ層の中で回り続ける回路がある。その意味で、ここまでの部品をつなぐと、SimClusters経由で投稿が広がっていく経路が1本描けます。この節は全体が「コードの作りから読める構図」で、実際のバズがこの通りに起きているかは検証していません。

バズの構図
同じ層の中でループが回り、いいねが続く間だけ隣の層へにじむ(解釈)

ステージ1: 盤に乗る(投稿直後〜数時間)

投稿 → フォロワーのうち同じ層(例: 料理番組の視聴者)がいいね → ロープが付き、料理番組の上位リストに載る。フォロワーが同じ層で固まっているアカウントほど、最初から向きがくっきり。いいねの総数が8件を超えると、「手がかり」としても使われ始める。

ステージ2: 同じ層の中でループが回る

料理番組のリストに載る → 「料理寄りの投稿を最近いいねした人」の候補に入る → Phoenixが順位付けして表示 → その人たちがいいね → ロープが太くなる → リストの上位に残る → もっと多くの料理好きの候補に入る → …。これが正のフィードバック。ただし8時間で半減するので、いいねが続いている間だけ回る。止まると半減してリストから落ち、ループが切れる。

ステージ3: 隣の層へにじむ

料理好きは、お弁当・時短・節約などの番組の視聴者でもある。いいねが増えるほど、それらの番組にもロープが伸びる → 隣の番組のリストにも載る → 隣の層の候補に入る → いいね → さらに隣へ。同心円状の広がり。隣の番組は手がかり側も似た形をしているので、似ている度合いは保たれる。

ステージ4: 飽和・終了

無関係な層まで届くと向きがぼやけ、元の層の仲間度が下がる(層が変わる)。いいねの勢いが落ちれば8時間単位で消え、48時間で強制終了。

この構図から言えること:

  • 起点は「太さ」と「顔ぶれ」の両方。太さで番組の予選を通り、顔ぶれでできる向きで仲間度が決まる。同じ層がまとまっていいねすることが、その両方を満たす
  • 伸び続ける条件は「途切れないこと」。8時間の半減期がタイムリミット
  • 広がり方は「似た層 → 隣の層」の順。いきなり全方位ではない
  • SimClustersが直接見ているのはフォロワー数ではなく、いいねでできる太さと向き。大きいアカウントが速いのは、フォロワーの層がそろっていて、太さと向きが即座に決まるから(フォロワーが多いほどいいねの母数が増える、という間接効果は否定しない)

言えないこと:

  • SimClustersは候補集めだけ。ループの各周で必ず表示される保証はなく、表示はPhoenixの順位付け次第
  • Thunder(フォロワーへの配信)など他の経路も同時に動いていて、バズのどれだけがSimClusters経由かはコードから分からない

だからどうなる?

【読む側】

おすすめに出てくる「知らない人の投稿」の一部は、あなたが最近反応した投稿の「視聴者層仲間」です。あなたが何に反応するかで、次の候補探しに使われる手がかりが変わります。これは推測ではなく、仕組みの通りです。

手がかりには「自分が投稿したもの」も入っています(最大15件)。自分の投稿にいいねが8件以上付いていれば、それも起点になるので、あなたのおすすめには「あなたの投稿と客層(いいねした人の配合)が同じ投稿」が混ざってきます。自分の投稿を支持してくれた層が、他に何を支持しているかが見える、ということです。同じ層で今いいねされている投稿やアカウントを見つける入口になります。ただし、そこで見つけた投稿にあなたがいいねしても、SimClusters内ではあなたの投稿の座標には効きません(効くのは、その人たちがあなたの投稿にいいねしてくれた時だけ)。発見の入口であって、SimClustersが直接つないでくれるわけではありません。

【投稿する側】

SimClusters経由で拾われるための条件を、コードから逆算するとこうなります。

  • 視聴者のいいねが付くこと(1件目からロープが付く)。いいねの総数が8件以上になれば「手がかり」にもなれる
  • その番組の視聴者からのいいねが、その番組の上位リスト(上から800件の範囲)に入る程度に集まること。ここに入らないと、SimClusters経由では選ばれない(実質、同じ層からのいいねがそれなりに要る。必要な量は番組の大きさ次第)

一番短くまとめると、SimClusters経由で他人に届くには「その層の番組のランキングで、今、800位以内にいること」。この仕組みの中では、それ以外に方法はありません。

  • いいねした人の顔ぶれがそろっていること(そろっているほど座標がはっきりする)。視聴者でない人のいいねは、数には入っても場所を動かさない
  • 投稿から48時間以内であること
  • 視聴者層の似ている度合いが0.5を超えること

投稿者自身のフォロワー数は、この仕組みでは見ていません。見ているのは「誰がいいねしたか」だけ。だから小さいアカウントの投稿でも、いいねした人の顔ぶれがそろっていれば、ちゃんと座標が付きます。

SimClustersの中では、投稿者側の視点ではいいねがすべてです。リポストも返信もブックマークも、投稿の座標には効きません。同じ配合の視聴者からのいいねが増えるだけなら向きは変わらず、主にロープが太くなる(実際は人ごとに配合が違うので、向きも多少は動く)。太さは上位リストに残り続ける長さに効き、いいねが途切れれば8時間単位で消えていきます。

そして、発信の軸(何を書いているか)は、SimClustersの座標には直接効きません。投稿の中身も、投稿者が誰かも、この仕組みは読んでいないからです。見ているのは「見る側」だけ。あなたが料理のことを書いているから料理番組の近くに置かれるのではなく、料理番組の視聴者がいいねしたから料理番組の近くに置かれる。発信内容は「誰がいいねするか」を通して間接的に効くだけです。

これは「誰を集めるか」にも関わります。集めるべきは「同じ界隈の発信者」ではなく「同じ番組を濃く見ている人」です。視聴者ラベルは発信内容ではなく、その人が誰をフォローし誰の投稿にいいねしているかで決まるので、料理の発信者でも普段いいねしているのが投資やゲームなら、その人のいいねは投資・ゲームの方向にロープを足します。同じ界隈の発信者は互いにフォロー・いいねし合っていることが多く、結果的に同じ番組の濃い視聴者でもあることが多いので無駄ではありませんが、効いているのは発信の側ではなく視聴の側です。

ただし、同じ系統の発信者には、もう1つ別の意味があります(解釈)。手がかりには「自分が投稿したもの」が入るので、その人の投稿(いいね8件以上)は、その人自身のおすすめの起点になっています。あなたの投稿がその人の投稿と客層が同じで、その番組のランキングで800位以内にいれば、その人のおすすめ候補にあなたの投稿が入る。つまり同じ系統の発信者は「あなたの投稿を見つけやすい位置にいる人」で、見つけていいねしてくれれば、たいていその番組の濃い視聴者でもあるので、太さと向きの両方に効きます。「同じ系統の発信者で、その番組に濃い人」が、一番価値のある仲間ということになります。

【「狙ってクラスターを作る」は有効か?】

よく出る疑問なので、2つに分けて書いておきます。

  • 番組(クラスター)を新しく作る → 個人には無理で、できても得がない。番組は上位2,000万人を「誰にフォローされているか」で週1回まとめて作られ、数も14.5万で固定。個人に「番組を1つ作る」操作は、公開コードにはない
  • 既存の番組に「寄る」→ SimClustersの候補集めの範囲では筋が通る(解釈)。投稿者にできる積み上げは、ここだけ。同じ番組の視聴者がフォロワーに多いほど、投稿のたびにロープの向きがそろう。寄り方は「その番組の出演者と同じ人たちにフォローされ、いいねされること」。自分が出演者になる必要はない

寄る時に、知っておくべき2層構造があります。

  • フォロワーの顔ぶれ(視聴者ラベル)は、ゆっくり変わる。視聴者リストは週1回更新、いいねの重みは100日で半減。一度そろえば、しばらく安定する資産
  • 投稿のロープとリストは、速く変わる。毎回ゼロから、8時間で半減、リストは常に入れ替わる

つまり「似た界隈の人を集める」は有効で、集めた層はすぐには消えない。ただし、投稿ごとに、その番組からのいいねが続いて入るほど800位以内に残りやすく、「フォロワーとして持っている」だけでは効かない。しかも、料理にも投資にも育児にも濃い「雑食」の視聴者のいいねは3方向にロープを足して向きをぼやけさせるので、その番組に絞って濃い視聴者のいいねほど、向きをそろえる力が強い。まとめると「似た界隈の、その番組に濃い人を集める。そして投稿ごとに、その層からのいいねが続くほど残りやすい」。集めるのはゆっくり効き、いいねは投稿ごと。

ここまでは、SimClustersの候補集めの中だけで見た話です。候補になった先で表示されるかは、Phoenixの順位付けと他の候補源との合流次第なので、「X運用として有効」と言い切るのは解釈です。コードから言えるのは「同じ方向の視聴者ラベルを持つ人にいいねされるほど、投稿のロープの向きはそろいやすい」まで。どのくらい効くかの数字も言えません。

ここからは解釈ですが——同じ番組の視聴者が集まっているコミュニティの中で伸びる投稿は、座標がはっきりしやすい。逆に、いろんな分野の人からバラバラにいいねされると、座標がぼやけて、似ている度合いが0.5を超えにくくなる、と読めます。どのくらい効くかは、数字では言えません。

よく聞かれる「相互フォローグループ」も、この枠で考えられます。相互フォロー自体は無関係(フォロー関係を見ない)ですが、仲間のいいねは「手がかりになれる8件」を越えるのに効き、8時間で半減する作りなので初速にも効きます(ここは解釈)。ただし、メンバーのジャンルがバラバラだと、ロープが多方向に分散して、特定の番組との似ている度合いが下がりやすくなります。2〜3方向までなら0.5を超えることもありますが(2方向均等で0.71、3方向で0.58)、4方向均等でちょうど0.5、それ以上に散らばると、どの番組の近所にも入りにくくなります。同じジャンルでまとまっているほど向きがそろい、混在するほどぼやける、と読めます(解釈)。

同じ理由で、相互交流のいいねが効くかどうかも、その人の発信内容ではなく、その人自身の視聴者ラベルで決まります。出演者を2人以上フォロー・いいねしていない人はそもそも視聴者ではなく、視聴者でもラベルが薄い(濃さ0.3未満)人のいいねはロープになりません。日常の雑談が中心のアカウントや何でもいいねする「雑垢」でも、どこかの番組の出演者をよくフォロー・いいねしていれば濃いラベルを持ちますし、逆に専門の発信者でも、見る側としては別の番組に濃いことがあります。「日常垢だから薄い」とは言えず、見るのはその人のラベルだけ。いいねの総数(8件)には数えられますが、コマを動かすのは「どこかの番組を濃く見ている人」のいいねだけです。なお「仲間内でいいねを回す」行動そのものは、SimClustersとは別の審査系が見ている可能性があります。そちらは次回で扱います。

【プロフィール本文は?】

SimClustersは、プロフィール本文を読んでいません。手がかりは「反応した投稿」、座標は「いいねした人の顔ぶれ」、視聴者かどうかは「フォロー・いいねの相手」。どこにもプロフィール本文は出てきません。「プロフにAIと書いたらAI番組の視聴者になる」という構造は、このコードにはありません。

まとめ

  • 「自分がどのクラスターに所属しているか」でおすすめが決まる仕組みではない。動くのは「何に反応したか」「誰にいいねされたか」
  • クラスター=番組(有名アカウント平均138人の出演者名簿)。その役割は、誰でも「どの番組の視聴者か」を持てるようにすること
  • 投稿の座標=いいねした人の視聴者ラベルの合計。中身も投稿者も見ない。視聴者のいいね1件目から付き、8時間で半減。手がかりになるには総数8件
  • SimClustersは「あなたが最近反応した投稿と視聴者層が同じ投稿」を、48時間以内・最大800件、連れてくる係。順位は決めない
  • 投稿には3つの状態がある。盤に乗る(視聴者のいいね1件目から)/起点になれる(いいね総数8件以上)/候補として選ばれる(その番組のリストで上から800件に入る太さがある)。盤に乗り、起点にもなれても、番組のリストに入っていなければSimClusters経由では選ばれない。予選は太さ、本選は向き
  • 2,000万人は物差し。バズの起点になりやすいが、登録されていなくても投稿は座標を持てる
  • 反応した投稿1件1件が独立した検索起点になる構造。「さっき反応した投稿の仲間が増える」体感と整合する
  • 「視聴」=出演者をフォロー・いいねすること。見ているだけでは数えない。自分の視聴者リストは、自分のおすすめにも自分の投稿にも使われない
  • SimClustersの中では、投稿者側はいいねがすべて。視聴者のいいねでロープが付き、向きは視聴者層で決まり、いいねの多さは「番組の上位リストに入れるか・残れるか」に効く。ラベルの薄い人のいいねは場所を動かさない(発信内容ではなく、その人の視聴者ラベルで決まる)
  • 発信の軸は座標に直接効かない。効くのは「見る側」だけ。クラスターを作るのは無理、既存の番組に寄るのは候補集めの範囲では筋が通る(解釈)。フォロワーの層はゆっくり積み上がり、いいねは投稿ごとに続くほど残りやすい
  • Phoenix(中身の住所)とSimClusters(視聴者層の座標)、投稿は2つの置き場所を持っている

公開コードからは分からないこと:

  • 反応履歴を何日分さかのぼっているか(データの取得元が公開コードの外)
  • Thunder・Phoenix・SimClustersの候補が、最終的にどんな比率でおすすめに出ているか(順位付けに丸投げなので、比率そのものは存在しない)
  • 各数字は公開コードの値で、本番では異なる可能性

次回は、ここまでに溜まった「審査」の話——エンゲージメント稼ぎへの対策——を予定しています。

参照(クリックすると該当箇所が開きます)

おすすめ側の条件(手がかり・48時間・0.5・800件・交互配置):
https://github.com/xai-org/x-algorithm/blob/28e414f/home-mixer/sources/simclusters_source.rs#L24-L35

反応履歴の種類(いいね・RP・返信・ブクマ・共有・自分の投稿):
https://github.com/xai-org/x-algorithm/blob/28e414f/home-mixer/query_hydrators/explicit_engagement_signals_query_hydrator.rs

反応履歴の種類(写真拡大・動画視聴。動画の長さ10秒以上の条件はL21とL128):
https://github.com/xai-org/x-algorithm/blob/28e414f/home-mixer/query_hydrators/implicit_engagement_signals_query_hydrator.rs

反応履歴の種類一覧(9種類):
https://github.com/xai-org/x-algorithm/blob/28e414f/home-mixer/models/engagement_signals.rs#L5-L15

種類ごとの上限15件:
https://github.com/xai-org/x-algorithm/blob/28e414f/home-mixer/params/param.rs#L786-L790

視聴者層の似ている度合いの計算(コサイン類似度):
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclustersann/candidate_source/ApproximateCosineSimilarity.scala

投稿の座標の条件(8時間・8件・内訳は上位400番組分):
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/summingbird/common/Configs.scala#L39-L65

投稿の座標を作る処理(セルフいいね除外・3日・視聴者でない人のいいねは寄与しない):
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/summingbird/storm/TweetJob.scala#L59-L72

手がかり用の埋め込みはいいね総数8件以上の投稿だけ(PersistentTweetJob):
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/summingbird/storm/PersistentTweetJob.scala#L50-L56

手がかりの埋め込みが無ければ候補ゼロ:
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclustersann/candidate_source/SimClustersANNCandidateSource.scala#L36-L56

いいねの重みの半減期100日(favScoreHalfLife100Days):
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/scalding/InterestedInFromKnownFor.scala#L241-L265

視聴者の条件(最大50・根拠2人):
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/scalding/InterestedInFromKnownFor.scala#L66-L67

番組作りの条件(400人以上・2,000万人・週次):
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/scalding/update_known_for/UpdateKnownFor20M145K2020.scala#L57-L65

1人1番組の処理:
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/scalding/update_known_for/UpdateKnownForSBFRunner.scala#L469-L491

フォロー外共通の係数0.75(OonWeightFactor):
https://github.com/xai-org/x-algorithm/blob/28e414f/home-mixer/params/param.rs#L253-L256

候補の年齢上限48時間(全ソース共通):
https://github.com/xai-org/x-algorithm/blob/28e414f/home-mixer/params/config.rs#L36

出演者登録バッチの開始日(firstTime = 2020-10-04):
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/scalding/update_known_for/UpdateKnownFor20M145K2020.scala#L37

モデル名(20M_145K_2020):
https://github.com/xai-org/x-algorithm/blob/28e414f/simclusters/simclusters_v2/common/ModelVersions.scala

READMEのSimClustersの説明:
https://github.com/xai-org/x-algorithm/blob/28e414f/README.md

この記事のもとになったX記事

Xで公開した第4回の記事を、サイト用に読みやすく再構成したものです。

前の回:セマンティックIDと投稿の住所 次の回:おすすめができるまでの9ステップ ブログ一覧へ