乙Py先生のプログラミング教室

乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

今回は最近公開された
Xのフィードアルゴリズムについてです

解説動画はこちら





Xのフィード・アルゴリズムの仕組みについて

Xのアルゴリズムコードはこちらになります。

xai



システムの4つの主要コンポーネント



Xのフィードアルゴリズムは
大きく4つのコンポーネントで構成されています。

4components



1. Home Mixer:
全体の司令塔(オーケストレーション層)です。

候補の抽出からランク付け、フィルタリングまでの全工程を管理します。
パイプラインは以下のステージで構成されています:

    1.Query Hydration - ユーザーのエンゲージメント履歴とメタデータを取得
    2.Candidate Sources - ThunderとPhoenixから候補を取得
    3.Hydration - 候補に追加データを付与
    4.Pre-Scoring Filters - 不適格な投稿を除外
    重複、古い投稿、自分の投稿、ブロック/ミュートしたアカウント、ミュートキーワードなど
    5.Scoring - 複数のスコアラーを順次適用
      Phoenix Scorer (ML予測)
      Weighted Scorer (予測の重み付け結合)
      Author Diversity Scorer (多様性のための減衰)
      OON Scorer (Out-of-Network調整)
    6.Selection - スコアでソートし、上位K件を選択
    7.Post-Selection Filters - 最終検証 (削除済み/スパム/暴力的コンテンツなど)
    8.Side Effects - キャッシュとログ記録


2. Thunder:
フォロー中ユーザーの投稿をリアルタイムで追跡するメモリ内ストアです。

ミリ秒単位の高速な読み込みを可能にします。

主要機能:
    1.Kafkaからのリアルタイム取り込み - 投稿の作成/削除イベントを消費
    2.ユーザー別ストア管理 - オリジナル投稿、リプライ/リツイート、動画投稿を分類
    3.サブミリ秒ルックアップ - 外部データベースにアクセスせずに高速検索
    4.自動トリミング - 保持期間を超えた古い投稿を自動削除

パフォーマンス最適化:
    1.タイムアウト機能 (デフォルト設定可能)
    2.ユーザーあたりの投稿数制限
    3.メモリ効率化のための自動容量調整


3. Phoenix:
機械学習(ML)を担当する心臓部です。

検索: フォロー外から好みに合う投稿を見つけ出します。
ランキング: ユーザーがその投稿に反応(いいねやリプライなど)する確率を予測します。

・アルゴリズムの詳細

2つのステップ

1. Retrieval(Retrieval段階):
数億のツイートから、2タワーモデル(Two-Tower Model)を用いて
「関連がありそうな数千件」をミリ秒単位で抽出します。

2. Ranking(ランキング段階):
抽出された数千件に対し、トランスフォーマーモデルを用いて
いいねやリポストなどの「具体的なエンゲージメント確率」を
詳細に予測・採点します。


Retrieval: Two-Tower Model (2タワーモデル)
   1. User Tower(ユーザー側): 
   ユーザーの属性(User Hashes)と、過去のエンゲージメント履歴(History)を
   トランスフォーマーで処理し、ユーザーの「現在の興味」を
   1つの数値ベクトル(User Representation)に凝縮します。

   2. Candidate Tower(ツイート側): 
   ツイート内容や投稿者情報を同様にベクトル化(Candidate Representation)します。

近さの計算(ドット積)
   「近さ」の採点は、ユーザーベクトルと
   ツイートベクトルの**ドット積(内積)**で行われます。

   ベクトル同士の向きが近い(興味が一致する)ほどスコアが高くなります。
   全てのツイートが事前にベクトル化されているため
   数億件の中から瞬時に上位K件を取得可能です。


Multi-Action Prediction (複数アクション予測)
   P(favorite)      - いいね
   P(reply)         - リプライ
   P(repost)        - リツイート
   P(quote)         - 引用ツイート
   P(click)         - クリック
   P(profile_click) - プロフィールクリック
   P(video_view)    - 動画視聴
   P(share)         - シェア
   P(dwell)         - 滞在時間
   P(follow_author) - フォロー
   P(not_interested) - 興味なし (負の重み)
   P(block_author)  - ブロック (負の重み)
   P(mute_author)   - ミュート (負の重み)
   P(report)        - 報告 (負の重み)


最終スコア計算:

   Final Score = Σ (weight_i × P(action_i))

ポジティブなアクションは正の重み、ネガティブなアクションは負の重みを持ちます。


4.Candidate Pipeline:
推薦システムを構築するための再利用可能なフレームワークです。
   Source データソースから候補を取得
   Hydrator 候補に追加特徴を付与
   Filter 表示すべきでない候補を除外
   Scorer ランキング用のスコアを計算
   Selector 上位候補をソート・選択
   SideEffect 非同期サイドエフェクト実行 (キャッシュ、ログ)
   QueryHydrator クエリコンテキストを準備




おすすめが表示されるまでの流れ


フィードが生成されるまでには、以下のステップを踏みます。
flow


1. データの準備 (Hydration): ユーザーの過去のエンゲージメント履歴や
フォローリストを読み込みます。

2. 候補の抽出: 「Thunder(フォロー内)」と「Phoenix(フォロー外)」の
両方から候補となる投稿を集めます。
   
3. フィルタリング(前処理): 重複した投稿、古すぎる投稿
自分がブロックしている相手の投稿、既に見た投稿などを除外します。

4. スコアリング(ランク付け):
 Grokベースのモデルが「いいね」「リプライ」「リポスト」
 「クリック」などの発生確率を個別に予測します。
 それらを重み付けして最終スコアを算出します。
 特定の著者ばかりに偏らないよう「著者多様性スコア」で調整をかけます。

5. 最終選定: スコアの高い順に並べ替え、最終的な表示候補を選び出します。

6. フィルタリング(後処理): 削除済み、スパム、暴力的なコンテンツなどが
混じっていないか最終チェックを行います。


おすすめに表示されやすくなるポイント

ポジティブエンゲージメント
以下のアクションが予測されるとスコアが上昇:

いいね、リツイート、リプライ
動画視聴 (一定時間以上の動画)
フォロー
クリック、シェア、滞在時間

In-Network(フォロー中)
フォローしているアカウントの投稿は優遇されます。

新鮮な投稿 古すぎない
タイムリーな投稿が優先されます。

動画コンテンツ 一定時間以上の動画は
特別な重み付けを受けます。



おすすめに除外されやすくなるポイント

ネガティブシグナル 以下が予測されると
スコアが低下:

興味なし、ブロック、ミュート、報告

ブロック・ミュートしたアカウント
完全に除外されます。

ミュートキーワード
設定したキーワードを含む投稿は除外。

自分自身の投稿
自分の投稿は「For You」から除外。

既に見た投稿
過去に表示された投稿は除外(Bloom Filter使用)。

古すぎる投稿
一定期間以上経過した投稿は除外。

削除済み・スパム・暴力的コンテンツ
最終段階で除外されます。



スコアリングの仕組み

最終スコア = Σ (重み × 各アクションの予測確率)

= P(いいね) × いいね重み
+ P(リツイート) × リツイート重み
+ P(リプライ) × リプライ重み
+ ...
+ P(ブロック) × ブロック重み (負の値)
+ P(ミュート) × ミュート重み (負の値)
処理順序:

1. Phoenix Transformer → ML予測
2. Weighted Scorer → 重み付け結合
3. Author Diversity Scorer → 多様性調整
4. OON Scorer → In/Out-of-Network調整
5. Selection → 上位K件選択



ポジティブシグナルの重み

以下のアクションが予測されると、投稿のスコアが上昇します:

アクション 説明 重要度
いいね (Favorite) ユーザーがいいねする確率 ⭐⭐⭐
リツイート (Retweet) リツイートする確率 ⭐⭐⭐
リプライ (Reply) リプライする確率 ⭐⭐⭐
引用ツイート (Quote) 引用ツイートする確率 ⭐⭐
クリック (Click) 投稿をクリックする確率 ⭐⭐
プロフィールクリック 投稿者のプロフィールをクリック ⭐⭐
動画視聴 (Video View) 動画を視聴する確率 ⭐⭐⭐
画像展開 (Photo Expand) 画像を展開する確率 ⭐⭐
シェア (Share) 外部にシェアする確率 ⭐⭐
滞在時間 (Dwell) 投稿に滞在する時間 ⭐⭐
フォロー (Follow Author) 投稿者をフォローする確率 ⭐⭐⭐


実践的アドバイス

表示されやすくするには:
✅ エンゲージメントを促す投稿(いいね、RT、リプライされやすい)
✅ 動画・画像付きコンテンツ
✅ タイムリーな情報
✅ フォロワーとの関係構築

除外されないために:
❌ スパム的な投稿を避ける
❌ 暴力的・不適切なコンテンツを避ける
❌ ミュートキーワードに引っかからない
❌ 重複投稿を避ける



まとめ

今回のXのアルゴリズム更新のポイントは
「人間による調整を徹底的に排除し
AI(Grokベースのモデル)に判断を委ねたこと」にあります。

システムは「フォロー内」と「フォロー外」の投稿を統合し
膨大なユーザー履歴から
「あなたが次にどのボタン(いいね、リプライ等)を押すか」
を精密に予測して並べ替えます。

また、多様性を確保しつつ、不適切なコンテンツや重複を
二段階のフィルタリングで排除する
非常に高度かつクリーンな構成になっています。


アルゴリズムの詳細コードを見たい方は
ぜひgithubの方を見てみてください

それでは。

今回は最適化問題を解くことが出来る
OR-Toolsについてです。

解説動画はこちら




OR-Toolsとは


Googleが開発している、組合せ最適化のためのライブラリ

様々な最適化問題を解くためのソルバーが充実していて
C++実装だが、Pythonなどいろいろな言語で使えます。


解ける最適化問題

次のような最適化問題を解くことができます。


1.配送ルート最適化
巡回セールスマン問題 : 1台の車両で最短経路を回る
配送計画問題 : 複数台の車両で分担して配送する

2.スケジューリングと制約プログラミング
決められた制約を全て満たしつつ、最適なスケジュールを組む
従業員のシフト作成
工場のライン計画

3.線形計画・整数計画(LP, MIP)
目的関数を最大化、または最小化する問題を数式で解く手法
生産計画 : 在庫と予算の範囲内で利益の最大化
リソース配分 : 予算内での広告効果最大化の割り当て

4.詰込み・割当問題
ナップサック問題 : 容量制限のあるバッグに価値が最大になるよう詰める
ビンピッキング問題 : サイズの異なる荷物を出来るだけ少ないトラックに詰める

5.ネットワークフロー
最大流問題 : パイプラインで一度に流せる最大量を求める
最小費用問題 : 指定量の輸送で、コストが最も安くなるルートと量の特定


インストール

Google Colab でも無いみたいなので、入れる必要あります。
pip install ortools


OR-Toolsの基本的な使い方

1.ライブラリの読み込み

解く問題に応じて、対応するライブラリを読み込みします
# CP-SATソルバー(制約プログラミング/MIP)
from ortools.sat.python import cp_model

# 線形計画法ソルバー(LP)
from ortools.linear_solver import pywraplp

# 配送計画(Routing)
from ortools.constraint_solver import pywrapcp, routing_enums_pb2

2. 最適化モデル構築

次に最適化モデルを作ります。
基本の「4ステップ」があります。

STEP 1: モデルのインスタンス作成
まず、問題を定義するための「箱」を作ります。

from ortools.sat.python import cp_model

model = cp_model.CpModel()


STEP 2: 変数の作成
「何を求めたいか」を変数として定義します。

整数変数: model.NewIntVar(下限, 上限, '変数名')
ブール変数: model.NewBoolVar('変数名')


STEP 3: 制約条件の追加
model.Add(...) を使って、守らなければならないルールを記述します。

等式・不等式: model.Add(x + y <= 10)
論理制約: 「Aの時だけBを適用する」といった
条件付き制約(OnlyEnforceIf)も可能


STEP 4: 目的関数の設定と実行
「何を最大化(または最小化)したいか」を決め
ソルバーを起動します。

# 最小化の場合
model.Minimize(目的の式)

# ソルバーの起動
solver = cp_model.CpSolver()
result = solver.Solve(model)

ここまでのコードを作れば
最適化問題が解ける様になっていると思います。


問題を解いてみる

簡単なつるかめ算をやって
あっているかを確認してみましょう。


問題1:
「つる」と「かめ」が合計で10匹、足の合計は28本です
それぞれ何匹ずついるでしょうか?

コードはこんな感じになります。
from ortools.sat.python import cp_model

def solve_tsurukame():
    # モデルの作成
    model = cp_model.CpModel()

    # 変数の定義 (0匹以上10匹以下)
    tsuru = model.NewIntVar(0, 10, 'tsuru')
    kame = model.NewIntVar(0, 10, 'kame')

    # 制約1: 合計が10匹
    model.Add(tsuru + kame == 10)

    # 制約2: 足の合計が28本
    model.Add(2 * tsuru + 4 * kame == 28)

    # ソルバーの準備と実行
    solver = cp_model.CpSolver()
    result = solver.Solve(model)

    if result == cp_model.OPTIMAL:
        print(f'つる: {solver.Value(tsuru)} 羽')
        print(f'かめ: {solver.Value(kame)} 匹')

solve_tsurukame()
つる: 6 羽
かめ: 4 匹


問題2:
50円切手と80円切手が計20枚、合計で1240円になるとき
それぞれ何枚ずつあるでしょうか?

from ortools.sat.python import cp_model

def solve_stamps():
    model = cp_model.CpModel()

    # 変数の定義 (0枚以上20枚以下)
    s50 = model.NewIntVar(0, 20, '50yen')
    s80 = model.NewIntVar(0, 20, '80yen')

    # 制約1: 合計20枚
    model.Add(s50 + s80 == 20)

    # 制約2: 合計金額が1240円
    model.Add(50 * s50 + 80 * s80 == 1240)

    solver = cp_model.CpSolver()
    result = solver.Solve(model)

    if result == cp_model.OPTIMAL:
        print(f'50円切手: {solver.Value(s50)} 枚')
        print(f'80円切手: {solver.Value(s80)} 枚')

solve_stamps()
50円切手: 12 枚
80円切手: 8 枚



問題3:

動画内ではすこし難しめの
入試問題なんかもやっています。

是非みてみてください。



まとめ


OR-Toolsは最適化問題を解くのに、かなり有効なライブラリです。

実社会の巨大な課題にも応用可能で
「Amazonのような配送ルート作成」や
「学校の複雑な時間割作成」など
他にもいろいろな最適化に応用できるものがあります。

だだし、使いこなすにはちょっとした
数学の知識が必要かもしれません。

使いこなせるとかなり問題を解ける幅が広がるので
実社会の問題解決にかなり有利かもしれません。

是非使ってみてください
それでは。



 

今回はPythonからRustを呼び出して
超高速化する方法についてです。

解説動画はこちら




Pythonは書きやすくて便利だけど
他の言語に比べるとどうしても遅い。


そんな時はRustの高速なネイティブコードを
Pythonから呼び出して計算速度を上げられます。


Python-Rust連携の方法

maturin

Rustで書かれたコードをPythonのパッケージ(wheel形式)
としてビルド・公開するためのビルドツールです。

これを使ってPythonとRustを連携させます。

主な手順は以下です。
1.Rust と maturin をインストール
2.Rust拡張用のプロジェクトを作る
3.Rustコードを作る
4.Cargo.toml を修正する
5.Python用拡張としてビルドする

早速手順を見ていきましょう。

なおGoogle ColabでのRust-Python連携方法になります。
自前のPCだとかだと、少し手順は変わってきます。

1.Rust と maturin をインストール

まず初めはColab内に必要なものをインストールします
# Rust をインストール
!curl https://sh.rustup.rs -sSf | sh -s -- -y -q
import os
os.environ["PATH"] = f"{os.environ['HOME']}/.cargo/bin:" + os.environ["PATH"]
!rustc --version
!cargo --version
!pip install -U maturin
!maturin --version

2. Rust拡張用のプロジェクトを作る
デフォルトのディレクトリはcontentになっているので
その中にプロジェクトを作り移動します。
!maturin init fastcalc
%cd /content/fastcalc

UIのフォルダマークからディレクトリが
作成されていると思います。


3. Rustコードを作る

すでにあるコードを上書きする形で
コードを書き換えます。
ここでは簡単な計算を行うコードを指定して
関数を作っています。

%%writefile src/lib.rs
use pyo3::prelude::*;

#[pyfunction]
fn sum_squares(n: u64) -> u64 {
    let mut s = 0;
    for i in 0..n {
        s += i * i;
    }
    s
}

#[pymodule]
fn fastcalc(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(sum_squares, m)?)?;
    Ok(())
}

4. Cargo.toml を修正

設定用のファイルも上書きします。

%%writefile Cargo.toml
[package]
name = "fastcalc"
version = "0.1.0"
edition = "2021"

[lib]
name = "fastcalc"
crate-type = ["cdylib"]

[dependencies]
pyo3 = { version = "0.21", features = ["extension-module"] }

5. Python用拡張としてビルド

RustコードをPythonライブラリとしてビルドします。

# Python環境から Rust を見えるように PATH を追加
!export PATH="$HOME/.cargo/bin:$PATH"

# wheel を作る
!maturin build --release

# wheel を pip install
!pip install target/wheels/*.whl

6.Pythonから Rust 関数を呼ぶ

1-5までが出来ていたら
ライブラリを呼び出して、Rustの関数が実行できます。

import fastcalc
fastcalc.sum_squares(100_000_000)

7.Python版と速度比較

これで速度比較が出せると思います。

import time

def sum_squares_py(n):
    s = 0
    for i in range(n):
        s += i * i
    return s

N = 100_000_000

t0 = time.time()
sum_squares_py(N)
t1 = time.time()
python_time = t1 - t0

t2 = time.time()
fastcalc.sum_squares(N)
t3 = time.time()

rust_time = t3 - t2
print("Python: {:.8f} sec".format(python_time))
print("Rust  : {:.8f} sec".format(rust_time))
print("Rust vs Python : {:.10f}".format(python_time / rust_time))

どれくらいの速度差になるかは
是非動画の方を見てみてください。

動画内ではもう一つの
シミュレーションも行っていますので
参考になると思います。



まとめ

maturinを使ったRustコードのPython拡張を作って実行できるようにすると
実行速度が高速な関数を呼び出せるようになります。


Pythonの簡単さはそのままに、重い計算はRustに任せる
これが Python × Rust 連携の最強パターンです。


最近はPolarsなどの大量データ処理や
深層学習モデルの構築や推論なども
Rust製ライブラリが増えてきています。

無いものは自分で作れると
自作の処理の時短になって
めちゃくちゃ捗ります。

今日はここまでです
それでは。

このページのトップヘ