멀티태스크 랭킹 — 참여 확률 여러 개를 하나의 점수로
최종 갱신: 2026-08-09
랭커가 "이 유저가 이 아이템을 좋아할까"를 스칼라 하나로 예측하지 않고, 행동 종류별로 확률을 따로 예측한 뒤 하나의 점수로 합쳐서 정렬하는 구조.
⚠ 이 노트의 Meta system card 기반 주장(예측 헤드 개수 등)은 전부 2026-08-09 열람 스냅샷이다 — 전체 주의는 ../services/facebook.md의 "system card 인용의 유효기간" 절에 있다.
score = Σ_k w_k · P(action_k | user, item)
단, 이 가중합은 여러 결합 형태 중 하나일 뿐이다. Meta는 같은 회사 안에서 지면마다 덧셈형·곱셈형·곱셈 페널티를 각각 다른 글에서 수식으로 공개했다(아래 표). "멀티태스크 랭킹 = 가중합"은 관찰이 아니라 가정이다.
여기서 진짜 설계 결정은 네 가지다. 어떤 행동을 헤드로 둘 것인가, 어떤 형태로 결합할 것인가, 음수 행동을 어떻게 섞을 것인가, 가중치 w_k를 어디서 가져올 것인가.
왜 이 구조인가
- 목적 함수를 코드 배포 없이 바꿀 수 있다. 모델은 확률만 뱉고, 제품 판단(리트윗이 좋아요보다 몇 배 중요한가)은 가중치로 분리된다.
[추정]— X가 가중치를 전부 런타임 주입으로 뺀 구조가 이 해석과 일치한다. - 희소한 행동(신고, 차단)을 별도 헤드로 두면 학습 신호가 죽지 않는다. 단일 스칼라로 합치면 흔한 행동에 묻힌다.
[추정] - 대가: 가중치가 곧 제품 정책이 되는데, 그 값이 공개 소스에 안 남는다. 아래 X 사례가 이 문제의 교과서다.
케이스: Meta — 결합 형태가 지면마다 다르다
Facebook이 공개한 결합은 선형 하나인데, Instagram은 세 개를 서로 다른 문제에 쓴다고 공개했다. 한 회사 안에서 최소 3종이다.
| 지면 | 형태 | 수식 (별도 표기 없으면 verbatim) | 연도 |
|---|---|---|---|
| Facebook Feed | 덧셈 | Vijt = wijt1·Yijt1 + wijt2·Yijt2 + … + wijtk·Yijtk |
2021 |
| Instagram Suggested Posts | 곱셈 | Value(Post) = (probability_like)^weight_like * (1- probability_not_interested)^weight_see_less |
2020 |
| Instagram Explore | 덧셈 + 음수항 | Expected Value = W_click * P(click) + W_like * P(like) – W_see_less * P(see less) + etc. |
2023 |
| Instagram Notifications | 곱셈 페널티 | ⚠ verbatim 아님 — 원문은 LaTeX 이미지다. Score(c) = R(c) × D(c), D(c) = ∏_{i=1..m} (1 - w_i · p_i(c)) 는 그 이미지를 옮긴 것 [관찰] 2026-08-09. 곱셈 구조와 R·D 정의는 본문 산문이 뒷받침 [확인] → feed-diversity.md |
2025 |
[확인] 순서대로 — How machine learning powers Facebook's News Feed ranking algorithm(2021) / Designing a Constrained Exploration System(2020) / Scaling the Instagram Explore recommendations system(2023) / A New Ranking Framework for Better Notification Quality on Instagram(2025)
지면별 맥락은 facebook.md · instagram.md. 여기서는 형태 비교만 한다.
읽는 법
- Facebook 수식의
w는(i,j,t)로 인덱싱된다 — 포스트·유저·시점별 개인화된 가중치라는 뜻이다.[확인]2021 — 원문이 "for each post i, we estimate Yijt", *"the characteristics of the post X_it toward viewer j at time t"*이라i=포스트,j=뷰어다. 다만 심볼릭 수식뿐이라 실제 구현이 정말i(포스트)에 의존하는지는 확인할 수 없다[추정]. - 곱셈형과 덧셈형은 음수 신호의 권한이 다르다. 곱셈형은
P(not_interested) → 1이면 value가 0으로 붕괴하니 사실상 hard veto이고, 덧셈형은 음수항이 아무리 커도 다른 항이 이길 수 있는 교환 가능한 비용이다.[추정]— 수식 형태에서 직접 따라 나온다. - 곱셈형도 로그를 취하면 선형이다 →
Σ w·log P.[추정]즉 Facebook의Σ w·P와 "선형결합"이라는 점은 같고 P를 쓰느냐 log P를 쓰느냐만 다르다. - ⚠ 2020 곱셈 → 2023 덧셈을 "전환"으로 읽으면 안 된다. 지면이 다르다(Suggested Posts vs Explore). 같은 지면의 전후 비교 자료가 없다.
[추정] - 네 번째(Notifications)는 결합이라기보다 다양성 페널티다. 상세는 → feed-diversity.md.
X와 정반대인 지점 — 음수를 곱하느냐
같은 문제에 두 회사가 반대 방향으로 갔다.
- Instagram 2020은 음수 확률을 곱해서 거부권을 준다(
(1 - P_not_interested)^w).[확인]2020 - X 2025는 일부러 곱하지 않는다 — 임계값을 넘으면 상수 페널티만 더한다(아래 설계 축 2).
[확인] - X 2026은 곱하되 음수 총점을
0.001스케일로 압축해 양수 후보와 절대 섞이지 않게 한다.[확인]
[추정] X는 음수 헤드가 순위를 흔드는 것을 막는 데 두 세대를 썼고, Instagram은 그 흔들림(붕괴)을 오히려 기능으로 쓴다. 코드에도 블로그에도 이유는 없다.
가중치를 어디서 가져오는가 — 회사 간 진짜 분기점
| 주체 | 공개된 방법 | 근거 |
|---|---|---|
| 설문과 각 이벤트의 correlation으로 정한다 | [확인] 2021 |
|
| offline replay/offline tuning + Bayesian optimization | [확인] 2020, 2023 |
|
| X | 방법 미공개. 주입 지점(FeatureSwitch 파라미터 / query feature)과 값 범위만 코드에 있다 | [확인] 공개 레포(c54bec0·xai-org/x-algorithm) 전수 — 값은 런타임 주입이라 코드에 없다 |
- Instagram 원문
[확인]: "offline replay over user sessions and b) online Bayesian optimization"(2020), "There are two popular approaches to parameters tuning: Bayesian optimization and offline tuning."(2023 — 이 글에 "replay"라는 단어는 0회다, 2026-08-09 전문 확인). - Facebook 원문과 "correlation"의 의미, 설문이 왜 희소성 문제를 안 겪는지는 → survey-signals.md. 여기서 반복하지 않는다.
- 같은 회사가 같은 문제에 다른 답을 공개했다.
[추정]실제로는 둘 다 쓰고 강조점만 다를 가능성이 높지만, 공개된 문장 수준에서는 명확히 갈린다. - 세 주체 모두 숫자는 안 준다. Meta는 방법을 공개하고 값을 감췄고, X는 주입 지점과 범위를 공개하고 값을 감췄다. 공개 축이 다를 뿐 결론은 같다 — 목적 함수의 값 = 제품 정책 = 비공개.
- Meta에는 X의
ModelWeights목록에 대응하는 물건이 하나 있다: Transparency Center가 예측을 사용 빈도 3단계(Used most frequently / occasionally / less frequently)로 계층화한 것. 가중치 대신 서열만 공개한 형태다.[확인]Our Approach to Facebook Feed Ranking (2025-06-11 갱신)
헤드 수 19~22 vs ~10 — 비교하면 안 되는 두 숫자
| 출처 | 헤드 수 | 출처 종류 |
|---|---|---|
| X Phoenix 공개 체크포인트 | 19 | 소스코드 |
| X 2026 서빙 코드 | 22 | 소스코드 |
| X 2026 VMRanker proto 복사본 | 21 | 소스코드 |
| X 2025 Navi / Phoenix | 15 / 13 | 소스코드 |
| Facebook Feed 카드 | 10 | system card |
| Facebook Feed Recommendations 카드 | 10 | system card |
| Threads Feed 카드 | 10 | system card |
| Instagram 각 카드 | 총 개수 미확정 | system card |
[확인] X 쪽은 위 설계 축 3의 파일 인용. Meta 쪽은 각 system card — fb-feed, fb-feed-recommendations, ig-threads-feed (2023~, 규제 대응 문서)
"X는 헤드가 두 배"라고 쓰면 안 된다. 두 숫자의 성격이 다르다.
- system card는 모델 덤프가 아니라 공개 커뮤니케이션 산출물이다. Facebook Feed 카드는 10종을 나열하는데, 같은 Transparency Center 본문은 hide/snooze/unsubscribe·report·angry reaction 예측이 분포를 낮추는 방향으로 쓰인다고 따로 서술한다 — 카드에 없는 헤드가 본문에 있다.
[확인]→ facebook.md - Instagram은 카드에서 추출한 목록과 카드가 명시한 개수가 어긋나는 지면이 4개(Feed·Stories·Reels Chaining·Suggested Accounts)라서 총 개수를 확정하지 못했다.
[확인]→ instagram.md - Threads 카드가 전체 헤드를 실은 것인지 *"significant predictions"*만 실은 것인지 판별 불가다.
[추정]→ threads.md - 그리고 X 쪽 숫자도 단일하지 않다. 한 레포 안에서 19/21/22, 이전 세대에서 13/15/17. → 결론은 양쪽 같다: "헤드 수"라는 단일 값은 존재하지 않는다. 어느 파일·어느 카드를 봤는지 반드시 같이 적어야 한다.
부정 헤드의 존재 여부는 Meta 안에서도 갈린다: Instagram은 수식 안에 항으로 박아 공개했고(– W_see_less·P(see less)), Facebook은 본문 서술로만 밝히고, Threads 카드에는 부정 예측 헤드가 하나도 없다. [관찰] 2026-08-09 (ig-threads-feed 카드 본문 1건) X 2026은 5개(not_interested/block/mute/report/not_dwelled)다. [확인]
케이스: X — 설계 축 6가지
1. 가중치는 코드에 없다
X는 세 세대 모두 가중치를 FeatureSwitch(런타임 설정) 로 뺐다. 레포에 있는 건 default 값이고, 프로덕션 값은 레포 밖에 있다.
| 세대 | 파라미터 수 | 범위 | 레포상 default |
|---|---|---|---|
| 2023 Scala | 17 | 제각각 — 9개는 0..100, 부정 4종은 음수 전용(Report −20000..0 포함), GoodClick류 상한 1,000,000 | 10개 1.0, 7개 0.0 |
| 2025 Scala | 30 | 2023과 같은 골격 (Report −20000..0 동일) | 전부 0.0 |
| 2026 Rust | 22 | 미공개 (params 모듈 자체가 없음) |
미공개 |
(⚠ 이전 판은 2023을 "0.0~100.0, 음수 표현 불가"로 적었다 — 원문 대조 결과 오류. 음수 전용 범위 4종이 2023 ef4c5eb부터 있었다. 2026-08-09 수정. → x.md 가중치 절)
[확인] 2023·2025 — ScoredTweetsParam.scala:151(2023), home-mixer/.../param/HomeGlobalParams.scala:788-978(2025). 2026 — home-mixer/scorers/ranking_scorer.rs:43-66
2025에서 default가 전부 0.0인 건 "좋아요 가중치가 0"이라는 뜻이 아니다. "가중치는 전부 런타임 주입이고 레포에는 없다"는 뜻이다. 이걸 잘못 읽으면 정반대 결론이 나온다.
범위 자체에 정책이 박혀 있는 경우는 있다. ReportParam은 min -20000.0 / max 0.0, WeakNegativeFeedbackParam·StrongNegativeFeedbackParam은 min -1000.0 / max 0.0 — 음수 전용으로 잠겨 있다. 운영자가 실수로도 양수를 못 넣는다. 이 경계는 2023부터 동일하다(2025 신설이 아니다). [확인] — HomeGlobalParams.scala:924-946, 2023 72eda9a 대조
→ 널리 인용되는 X 가중치 표(fav 0.5, retweet 1.0, reply 13.5, report −369.0 …)의 출처와 신뢰도는 x.md의 "가중치 — 무엇이 공개됐고 무엇이 아닌가" 참조. 요약하면 2023-04-05 시점 ML 레포 README 한 곳뿐이고, 서빙 레포 31개 커밋 어디에도 나온 적 없다.
2. 음수 헤드를 곱셈에 넣느냐 마느냐
가장 갈리는 지점이다. X 2025는 곱하지 않는다.
// 양수 가중치
combinedScore + score * weight
// 음수 가중치 — 임계값을 넘으면 상수 페널티만
normScore = if (maxHeadScore == 0.0) 0.0 else score / maxHeadScore
if (normScore > thresholdNormalized || score > thresholdConstant)
combinedScore + weight // score를 곱하지 않는다
else combinedScore
[확인] — home-mixer/.../util/RerankerUtil.scala:106-121
이유는 [추정]이다: 음수 헤드는 확률이 작고 노이즈가 커서 곱셈으로 넣으면 점수가 요동친다. 임계값 통과 여부만 보면 계단 함수가 되어 안정적이다. 코드에 이유는 안 적혀 있다.
정규화 기준이 요청 내 배치 상대값(score / maxHeadScore, 그 요청에 들어온 후보 전체의 헤드별 최댓값)이라는 게 중요하다. 같은 포스트라도 같이 채점된 후보 구성이 바뀌면 음수 페널티 발동 여부가 바뀐다. [확인] — RerankerUtil.scala:43-65
전환 중인 흔적도 있다. EnableNegSectionRankingParam을 켜면 combinedScore + weight * (1.0 min (score + 0.1))로 바뀌는데, 바로 위에 "This should be shipped and cleaned as soon as possible" 주석이 달려 있다. [확인] — RerankerUtil.scala:115-118
주의: 레포 default 상태에서는 음수 헤드가 아무 감점도 만들지 않는다. 관련 boolean 4개(NormalizedNegativeHead, ConstantNegativeHead, UseWeightForNegHeadParam, EnableNegSectionRankingParam)가 전부 false다. [확인] — HomeGlobalParams.scala:545-573
2026 Rust는 방식을 바꿔서 음수 헤드도 그냥 곱한다. 대신 총점이 음수가 되면 통째로 압축한다.
fn offset_score(combined_score: f64, w: &ScoringWeights) -> f64 {
if w.total_sum == 0.0 { combined_score.max(0.0) }
else if combined_score < 0.0 {
(combined_score + w.negative_sum) / w.total_sum * NEGATIVE_SCORES_OFFSET
} else { combined_score + NEGATIVE_SCORES_OFFSET }
}
[확인] — ranking_scorer.rs:175-183
이 함수는 2025 Scala 함수의 직역이다. 세 갈래 분기가 순서까지 한 줄씩 대응한다 [확인] RerankerUtil.scala:130-135:
if (modelWeightsSum == 0) combinedScoreSum.max(0.0)
else if (combinedScoreSum < 0)
(combinedScoreSum + negativeModelWeightsSum) / modelWeightsSum * Epsilon
else combinedScoreSum + Epsilon
대응: modelWeightsSum ↔ w.total_sum, negativeModelWeightsSum ↔ w.negative_sum, Epsilon ↔ NEGATIVE_SCORES_OFFSET.
→ 그래서 미공개 상수 하나를 되찾을 수 있다. 2026 NEGATIVE_SCORES_OFFSET은 crate::params에 있어 값이 안 보이지만, 2025 대응물은 val Epsilon = 0.001로 코드에 그대로 있다 [확인] RerankerUtil.scala:16. 두 레포는 "코드 중복 0"이라고 알려져 있지만 점수 집계 수식만은 포팅됐고, 그 덕에 2025 값이 2026 상수의 하한 근거가 된다 [추정].
의미: 음수 총점은 0.001 스케일로 눌린다. 양수 후보의 최솟값이 0 + 0.001 = 0.001이므로 음수 후보는 항상 모든 양수 후보 아래로 간다. 순서는 보존하되 섞이지 않는 설계다.
같은 식이 죽은 파일 weighted_scorer.rs:87-89에도 남아 있다 — 거기서는 p::NEGATIVE_WEIGHTS_SUM / p::WEIGHTS_SUM을 상수로 읽는다. 즉 가중치 합을 요청별로 계산하는 구조로 바뀌기 전 세대의 형태다 [추정].
3. 헤드 목록은 세대마다 다르고, 레포 안에서도 여러 벌이 돌아다닌다
2026 Rust 랭커가 읽는 헤드 22개 [확인] ranking_scorer.rs:12-39,146-170:
| 구분 | 헤드 |
|---|---|
| 참여 | favorite, reply, retweet, quote, share, share_via_dm, share_via_copy_link |
| 클릭·체류 | click, profile_click, photo_expand, quoted_click, dwell |
| 영상 | vqv, quoted_vqv |
| 연속값 | cont_dwell_time, cont_click_dwell_time |
| 팔로우 | follow_author |
| 음수 | not_interested, block_author, mute_author, report, not_dwelled |
공개된 Phoenix 체크포인트의 ACTIONS는 19개다 — quoted_vqv, not_dwelled, click_dwell_time이 없다. [확인] — phoenix/runners.py:233-253
즉 공개 모델(19)과 프로덕션 서빙 코드(22)의 헤드 수가 안 맞는다. 공개 체크포인트가 구버전이거나 일부 헤드를 뺀 것이다 [추정]. vm_ranker.rs가 proto로 복사하는 필드는 21개(quoted_vqv_score 누락)라서, 세 군데가 전부 다르다. [확인] — vm_ranker.rs:69-93
2025 Scala는 두 종류의 랭커가 각자 헤드 세트를 갖는다:
- Navi(프로덕션 heavy ranker) 15개 — fav, reply, retweet, reply_engaged_by_author, click_engaged, click_dwell, good_profile_click, vqv, vqv_immersive, bookmark, share, dwell, video_quality_watched, video_watch_time_ms, negative_feedback_v2.
[확인]home-mixer/.../model/PredictedScoreFeature.scala:294-311 - Phoenix(트랜스포머 rescorer) 13개 — 위에서 몇 개 빠지고
open_link,screenshot이 추가. 가중치는 Navi와 같은ModelWeights를 공유한다. 별도 세트가 없다.[확인]PhoenixPredictedScoreFeature.scala:174-189
Navi는 음수 헤드가 negative_feedback_v2 하나뿐이다. 2026의 5개(not_interested/block/mute/report/not_dwelled)로 세분화된 건 세대 간 변화다. [확인]
함정: 2025 레포에는 PredictedScoreFeature라는 같은 이름의 파일이 두 개 있고 헤드 세트가 다르다 — model/(15개 Seq, 실사용)와 product/scored_tweets/scorer/(17개 Set, Report·StrongNegativeFeedback·VideoPlayback50 등 포함). 실제 스코어러가 import하는 건 model/ 쪽이다. scorer/ 쪽을 근거로 "X는 report 헤드를 쓴다"고 쓰면 틀린다. [확인] — RerankerUtil.scala:4의 import 경로
4. 가중치 주입 경로가 요청 단위일 수 있다
2025 Navi는 가중치를 param이 아니라 query feature에서 읽는다.
weight = query.features.get(feature.weightQueryFeature).getOrElse(0.0)
[확인] — RerankerUtil.scala:28-29. 헤드마다 weightQueryFeatureName / biasQueryFeatureName / debiasQueryFeatureName 3종이 있다 [확인] PredictedScoreFeature.scala:43-56.
즉 목적 함수가 요청마다 달라질 수 있다. 유저 세그먼트별·실험별로 다른 가중치를 꽂는 구조로 보이나, 값을 채우는 upstream 서비스는 레포에 없다 [추정].
같은 레포에서 Phoenix 쪽은 param에서 직접 읽는다(query.params(feature.modelWeightParam)) — 두 랭커의 주입 경로가 다르다. [확인] — PhoenixModelRerankingScorer.scala:51
5. 부적격 헤드는 0이 아니라 bias로 대체된다
영상이 없는 포스트에 vqv 헤드를 쓸 수 없다. X 2025는 이때 0을 넣지 않고 bias 값을 넣는다.
score = if (isEligible) predictedScoreOpt.getOrElse(0.0) else bias
[확인] — RerankerUtil.scala:34-37. 0을 넣으면 영상 없는 포스트가 구조적으로 불리해지기 때문으로 보인다 [추정].
자격 조건도 손으로 정한 것들이다: 영상 헤드는 duration >= 10초, EnableDwellOrVQVParam이 켜지면 Dwell과 VQV가 상호 배타가 된다. [확인] — PredictedScoreFeature.scala:154-164,220-232,273-279
임계값 클리핑도 있다. VQV 점수가 ScoreThresholdForVQVParam 미만이면 0.0으로 잘리고, binary scheme이 켜지면 상수로 대체된다. [확인] — :176-188
6. 가중합 이후에도 점수가 계속 바뀐다
가중합은 끝이 아니다. 2026 Rust의 순서:
- 헤드별 가중합 →
offset_score(ranking_scorer.rs:146-183) normalize_score(candidate, raw)— 함수 본체가 공개 안 됨(crate::util모듈 부재)- 작성자 다양성 감쇠 — 같은 작성자의 n번째 포스트에
(1 - floor) · decay^n + floor곱하기 (:186-217) - OON 배수 — in-network가 아닌 후보에만
effective_oon곱하기 (:220-239, 272-275) - 이후
VMRanker(DPP 슬레이트 최적화)가 점수를 통째로 덮어쓸 수 있다 (vm_ranker.rs:47-52)
[확인] — ranking_scorer.rs:248-284, phoenix_candidate_pipeline.rs:300
2025 Scala도 같은 성격이지만 덧셈이다. DiversityRescoringFeatureHydrator가 MMR로 score = relevance + diversityWeight · minDistance를 계산해 ScoreFeature를 덮어쓴다. [확인] — DiversityRescoringFeatureHydrator.scala:70,102
→ 다양성 레이어 상세는 feed-diversity.md.
케이스: Netflix — 헤드×가중치 프레임 자체를 벗어난다
X·Meta의 Σ w·P(action) 프레임에 Netflix를 넣으면 안 맞는다. 공개된 목적함수가 가중합이 아니라 보상 함수다.
[확인] Recommending for Long-Term Member Satisfaction at Netflix, 2024:
- 컨텍스추얼 밴딧 프레임: 추천 = 행동, 유저 반응 = 보상. north star는 retention인데 직접 최적화하지 않는다 — "계정당 월 1회" 수준의 희소·노이즈 신호라 개별 추천에 귀속이 안 된다.
- 공개된 프록시 보상 형태:
r(user, item) = f(play, complete, thumb)— 행동별 확률 예측치의 가중합이 아니라 관측된 행동들의 함수다. 예측 헤드 목록×가중치 벡터라는 분해 자체가 등장하지 않는다. - 지연 피드백을 예측으로 매운다: Delayed Feedback Prediction Model이
p(최종 피드백 | 관측 피드백)을 예측해 보상에 주입. X·Meta 문헌에 대응물이 없는 장치다 — thumbs는 시청 후 며칠 뒤에 올 수 있어서 실시간 학습과 충돌하는 문제를 정면으로 다룬다. - "CTR 과최적화는 클릭베이트를 조장한다" 명시 — 가중치 튜닝이 아니라 보상 설계(reward engineering) 루프로 접근: 가설 → 보상 수정 → 밴딧 정책 학습 → A/B. 가중치를 정하는 "방법"이 Facebook(설문 correlation)·Instagram(Bayesian opt)과 또 다른 세 번째 답이다.
다만 프레임이 다르다고 헤드가 없는 건 아니다. FM은 multi-token/다중 예측 헤드를 갖고 [확인] FM 블로그 2025, 가중 목적함수도 쓴다("5분 트레일러와 2시간 완주가 같을 수 없다"). 차이는 그 가중이 학습 목적함수 안에 있고, 서빙 시점의 Σ w·P 결합층이 공개 문헌에 없다는 것. GenRec(2026)은 아예 reward-weighted loss로 학습한 LLM이 직접 랭킹한다 [확인] GenRec 블로그 — 결합이 모델 파라미터로 흡수된 형태다.
덤: 화면의 % Match는 랭킹 점수가 아니라 표시용이다 — "시청 습관·행동 분석만으로" 산출 [확인] 2017 발표. 유저에게 보이는 숫자와 정렬에 쓰는 숫자가 다른 시스템의 명시적 사례. → netflix.md
이 케이스에서 일반화할 수 있는 것
- "가중합"은 가정이지 관찰이 아니다. Meta 한 회사만 봐도 덧셈·곱셈·덧셈+음수항·곱셈 페널티 4종이 지면별로 공개돼 있다. 새 서비스를 볼 때
Σ w·P를 기본값으로 깔고 시작하면 안 된다. - "모델이 뭘 예측하나"는 공개돼도 "무엇을 중요하게 보나"는 안 공개된다. X는 헤드 목록이 코드에, 가중치가 설정에 있다. Meta는 헤드 목록이 카드에, 가중치를 정하는 방법이 블로그에, 값은 어디에도 없다. 공개 축이 다를 뿐 감춰지는 것은 같다.
- 음수 신호 처리 방향이 회사마다 반대다. X는 곱셈을 피하는 쪽(2025 상수 페널티, 2026 음수 총점 압축), Instagram 2020은 곱해서 거부권을 주는 쪽. 같은 문제에 정반대 설계가 둘 다 프로덕션에 있다.
- 헤드 수는 출처 종류에 따라 달라진다. X는 파일마다(19/21/22/15/13/17), Meta는 문서마다(카드 10종 vs 본문에만 있는 부정 예측). 소스코드는 파일 단위로, system card는 문서 단위로 불일치한다. 숫자를 비교하려면 먼저 두 숫자가 같은 종류인지 물어야 한다.
- 가중합 점수는 최종 순위가 아니다. 다양성·OON·슬레이트 최적화가 뒤에 붙는다. 실제로 X 2026은
weighted_score와score를 별도 필드로 둘 다 저장한다[확인]ranking_scorer.rs:277-281. Meta도 포인트와이즈 pass 1 뒤에 컨텍스트 pass 2가 따로 있다[확인]2021. Σ w·P프레임은 보편이 아니라 광고형 지면의 관행일 수 있다. Netflix는 같은 문제(여러 행동 신호의 통합)를 보상 함수 + 밴딧으로 푼다. 사업 모델이 구독(retention)이면 목적함수도 세션 참여 극대화가 아니라 장기 만족 프록시로 기운다 — 프레임 선택이 기술이 아니라 수익 모델의 함수일 가능성.[추정]- north star를 직접 최적화하지 않는 이유는 신호 밀도다. retention(월 1회)·설문(희소) 같은 진짜 목표는 프록시 보상/가중치 결정 레이어로 밀려나고, 랭커는 밀도 높은 행동 신호를 다룬다. Facebook의 설문 correlation과 Netflix의 reward engineering이 같은 구조의 두 구현이다.
누가 이걸 쓰는가
- X — 2023·2025·2026 세 세대 전부. 헤드 19~22, 가중치는 FeatureSwitch·query feature 주입. → x.md
[확인] - Facebook —
Vijt = Σ wijtk·Yijtk(덧셈), pass 1 포인트와이즈 멀티태스크 신경망, 가중치는 설문 correlation. Feed 카드 헤드 10종 + 본문에만 있는 부정 예측. → facebook.md[확인] - Instagram — 결합 형태 3종(2020 곱셈 / 2023 덧셈+음수항 / 2025 곱셈 페널티), 가중치는 offline replay/offline tuning + Bayesian optimization, 지면×컴포넌트마다 별도 MTML 모델(
ig_stories_tray_mtml, 프로덕션 1,000개 이상). → instagram.md[확인] - Threads — 헤드 10종은 공개했는데 결합 방식·가중치 정보가 0이고 부정 헤드도 0이다. 같은 회사 안에서도 지면마다 공개 수준이 다르다는 가장 선명한 증거. → threads.md
[확인] - Netflix —
Σ w·P아님. 밴딧 + 프록시 보상r=f(play, complete, thumb)+ 지연 피드백 예측. retention이 north star. → netflix.md[확인] - 그 외 서비스 — 미조사. YouTube의 multi-gate MoE(2019 RecSys), Pinterest 계열이 같은 축에 있을 가능성이 높지만 이 저장소에서 아직 1차 출처로 확인하지 않았다. 열린 질문.
출처
공개 소스코드
- xai-org/x-algorithm — 2026, 공개 소스코드 (Apache 2.0).
home-mixer/scorers/,phoenix/. - twitter/the-algorithm — 2025-09-03 커밋
c54bec0, 공개 소스코드.home-mixer/. - twitter/the-algorithm-ml — 2023-04-05
projects/home/recap/README.md. 가중치 숫자가 나오는 유일한 1차 출처.
Meta 엔지니어링 블로그 (결합 수식의 1차 출처)
- How machine learning powers Facebook's News Feed ranking algorithm — 2021, 블로그.
Vijt = Σ w·Y와 3-pass. - Designing a Constrained Exploration System — 2020, 블로그. 곱셈형 value model + Bayesian optimization. ⚠ How Instagram suggests new content와 동일 글, 다른 제목.
- Scaling the Instagram Explore recommendations system — 2023, 블로그. 덧셈형 + 음수항, Bayesian optimization + offline tuning.
- A New Ranking Framework for Better Notification Quality on Instagram — 2025, 블로그.
Score = R×D곱셈 페널티. - Journey to 1000 models: Scaling Instagram's recommendation system — 2025, 블로그.
ig_stories_tray_mtml명명 규칙.
Meta Transparency Center (규제 대응 1차 문서)
- Our Approach to Facebook Feed Ranking — 2025-06-11 갱신. 예측의 사용 빈도 3단계.
- fb-feed · fb-feed-recommendations · ig-threads-feed — AI system card, 지면별 예측 헤드 목록.
Netflix
- Recommending for Long-Term Member Satisfaction at Netflix — 2024, 블로그. 보상 함수 프레임의 1차 출처.
- Foundation Model for Personalized Recommendation — 2025, 블로그. 다중 헤드·가중 목적함수.
- GenRec — 2026, 블로그. reward-weighted loss.
- Goodbye Stars, Hello Thumbs — 2017, 발표. % Match 표시용.