X 推荐算法 Phoenix 重评分机制详解
前言
Phoenix 是 X(原 Twitter)推荐系统中的新一代机器学习模型,用于更准确地预测用户行为。Phoenix 重评分(Phoenix Rescoring)是一个可选步骤,使用 Phoenix 模型的预测分数来调整最终排序分数。本文将深入解析 Phoenix 重评分的机制和工作原理。
一、Phoenix 模型概述
1.1 什么是 Phoenix?
Phoenix 是 X 推荐系统的新一代预测模型,相比传统模型有以下特点:
- 使用用户行为序列:以用户的历史行为序列(UserActionSequence)作为主要输入
- 更准确的预测:通过深度学习技术提供更准确的用户行为预测
- 实时推理:支持实时推理,可以快速响应用户请求
- 多任务学习:同时预测多种用户行为
1.2 Phoenix vs 传统模型
| 特性 | 传统模型(Navi) | Phoenix 模型 |
|---|---|---|
| 输入特征 | 静态特征 + 聚合特征 | 用户行为序列 + 静态特征 |
| 模型架构 | 传统 ML 模型 | 深度学习模型 |
| 预测精度 | 较高 | 更高 |
| 计算成本 | 较低 | 较高 |
| 实时性 | 好 | 好 |
1.3 Phoenix 的预测目标
Phoenix 模型预测以下 13 种用户行为:
| 序号 | 行为类型 | Phoenix 特征 | 对应动作 |
|---|---|---|---|
| 1 | 点赞 | PhoenixPredictedFavoriteScoreFeature |
SERVER_TWEET_FAV |
| 2 | 回复 | PhoenixPredictedReplyScoreFeature |
SERVER_TWEET_REPLY |
| 3 | 转发 | PhoenixPredictedRetweetScoreFeature |
SERVER_TWEET_QUOTE, SERVER_TWEET_RETWEET |
| 4 | 优质点击(V1) | PhoenixPredictedGoodClickConvoDescFavoritedOrRepliedScoreFeature |
CLIENT_TWEET_PHOTO_EXPAND |
| 5 | 优质点击(V2) | PhoenixPredictedGoodClickConvoDescUamGt2ScoreFeature |
CLIENT_TWEET_CLICK |
| 6 | 个人资料点击 | PhoenixPredictedGoodProfileClickScoreFeature |
CLIENT_TWEET_CLICK_PROFILE |
| 7 | 视频质量观看 | PhoenixPredictedVideoQualityViewScoreFeature |
CLIENT_TWEET_VIDEO_QUALITY_VIEW |
| 8 | 分享 | PhoenixPredictedShareScoreFeature |
CLIENT_TWEET_SHARE_VIA_COPY_LINK, etc. |
| 9 | 停留时间 | PhoenixPredictedDwellScoreFeature |
CLIENT_TWEET_RECAP_DWELLED |
| 10 | 打开链接 | PhoenixPredictedOpenLinkScoreFeature |
CLIENT_TWEET_OPEN_LINK |
| 11 | 截图 | PhoenixPredictedScreenshotScoreFeature |
CLIENT_TWEET_TAKE_SCREENSHOT |
| 12 | 收藏 | PhoenixPredictedBookmarkScoreFeature |
CLIENT_TWEET_BOOKMARK |
| 13 | 负反馈 | PhoenixPredictedNegativeFeedbackV2ScoreFeature |
CLIENT_TWEET_NOT_INTERESTED_IN, etc. |
二、Phoenix 重评分的三种模式
2.1 模式概览
Phoenix 在推荐系统中有三种使用模式:
┌─────────────────────────────────────────────────────────┐
│ 模式1: Phoenix 直接评分 │
│ PhoenixScorer → PhoenixScoreFeature │
│ 使用 Phoenix 分数作为最终分数 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 模式2: Phoenix 重排序 │
│ PhoenixModelRerankingScorer → PhoenixScoreFeature │
│ 使用 Phoenix 模型进行重排序 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 模式3: Phoenix 重评分(本文重点) │
│ PhoenixRescoringFeatureHydrator │
│ 使用 Phoenix 分数调整已有分数 │
└─────────────────────────────────────────────────────────┘
2.2 模式对比
| 模式 | 评分器 | 输出特征 | 使用场景 |
|---|---|---|---|
| 直接评分 | PhoenixScorer |
PhoenixScoreFeature |
完全使用 Phoenix 模型 |
| 重排序 | PhoenixModelRerankingScorer |
PhoenixScoreFeature |
使用 Phoenix 模型重新排序 |
| 重评分 | PhoenixRescoringFeatureHydrator |
ScoreFeature |
使用 Phoenix 分数调整已有分数 |
三、Phoenix 重评分详解
3.1 什么是 Phoenix 重评分?
Phoenix 重评分 (Phoenix Rescoring)是一个后处理步骤,使用 Phoenix 模型的预测分数来调整已经经过多模型融合和启发式重评分的分数。
3.2 使用条件
scala
val usePhoenixRescoring =
query.params(EnablePhoenixScorerParam) && // 启用 Phoenix Scorer
query.params(EnablePhoenixRescoreParam) && // 启用 Phoenix 重评分
!query.params(EnablePhoenixScoreParam) // 未启用 Phoenix 直接评分
条件说明:
- 必须启用 Phoenix Scorer
- 必须启用 Phoenix 重评分参数
- 不能同时启用 Phoenix 直接评分(否则直接使用 Phoenix 分数)
3.3 重评分算法
scala
val score = candidate.features.getOrElse(ScoreFeature, None).getOrElse(0.0)
val weightedModelScore = candidate.features.getOrElse(WeightedModelScoreFeature, None).getOrElse(0.0)
val phoenixScore = candidate.features.getOrElse(PhoenixScoreFeature, None).getOrElse(0.0)
if (score == 0.0 || weightedModelScore == 0.0) {
0.0
} else if (usePhoenixRescoring) {
phoenixScore * (score / weightedModelScore)
} else {
score
}
公式:
finalScore = phoenixScore × (currentScore / weightedModelScore)
其中:
- currentScore: 当前分数(经过启发式重评分后)
- weightedModelScore: 原始融合分数(多模型融合后的分数)
- phoenixScore: Phoenix 模型预测的分数
3.4 工作原理
Phoenix 重评分通过比例缩放的方式调整分数:
-
计算比例 :
ratio = currentScore / weightedModelScore- 这个比例反映了启发式重评分对原始融合分数的调整程度
-
应用 Phoenix 分数 :
finalScore = phoenixScore × ratio- 使用 Phoenix 分数乘以这个比例,保持启发式调整的相对关系
设计理念:
- 保留启发式重评分的调整效果
- 使用更准确的 Phoenix 分数作为基础
- 平滑过渡,避免分数突变
3.5 实际示例
假设一个推文的完整评分过程:
步骤1:多模型融合
WeightedModelScoreFeature = 10.0
步骤2:启发式重评分
RescoreOutOfNetwork = 0.8
RescoreReplies = 1.0
RescoreMTLNormalization = 0.95
scaleFactor = 0.8 × 1.0 × 0.95 = 0.76
ScoreFeature = 10.0 × 0.76 = 7.6
步骤3:Phoenix 重评分
假设:
currentScore = 7.6weightedModelScore = 10.0phoenixScore = 12.0
计算:
ratio = 7.6 / 10.0 = 0.76
finalScore = 12.0 × 0.76 = 9.12
结果:
- 原始融合分数:
10.0 - 启发式重评分后:
7.6(衰减 24%) - Phoenix 重评分后:
9.12(使用 Phoenix 分数,但保持 24% 的衰减比例)
3.6 为什么使用比例缩放?
原因1:保留启发式调整
- 启发式重评分包含重要的业务规则(如多样性、内容过滤等)
- 直接替换会丢失这些调整
原因2:平滑过渡
- 比例缩放确保分数变化平滑
- 避免 Phoenix 分数和传统分数差异过大导致的突变
原因3:A/B 测试友好
- 可以逐步迁移到 Phoenix 模型
- 支持灰度发布和回滚
四、Phoenix 模型评分流程
4.1 Phoenix 直接评分(PhoenixScorer)
4.1.1 工作流程
用户请求
↓
检查条件(是否有 UserActionsFeature)
↓
调用 Phoenix 服务
↓
获取预测分数
↓
存储到 PhoenixScoreFeature
4.1.2 代码实现
scala
case class PhoenixScorer @Inject() (
@Named("PhoenixClient") channelsMap: Map[PhoenixCluster.Value, Seq[ManagedChannel]],
statsReceiver: StatsReceiver
) extends Scorer[PipelineQuery, TweetCandidate] {
override def onlyIf(query: PipelineQuery): Boolean = {
// 必须有用户行为序列
query.features.flatMap(_.getOrElse(UserActionsFeature, None)).isDefined
}
override def apply(
query: PipelineQuery,
candidates: Seq[CandidateWithFeatures[TweetCandidate]]
): Stitch[Seq[FeatureMap]] = {
// 1. 调用 Phoenix 服务获取预测
// 2. 提取预测分数
// 3. 存储到 PhoenixPredictedScoreFeatures
}
}
4.1.3 使用条件
- 必须有
UserActionsFeature(用户行为序列) - 必须启用
EnablePhoenixScorerParam
4.2 Phoenix 重排序(PhoenixModelRerankingScorer)
4.2.1 工作流程
候选列表
↓
提取 Phoenix 预测分数
↓
计算加权融合分数(类似 WeighedModelRerankingScorer)
↓
存储到 PhoenixScoreFeature
4.2.2 代码实现
scala
case class PhoenixModelRerankingScorer @Inject() (
statsReceiver: StatsReceiver
) extends Scorer[PipelineQuery, TweetCandidate] {
override def apply(
query: PipelineQuery,
candidates: Seq[CandidateWithFeatures[TweetCandidate]]
): Stitch[Seq[FeatureMap]] = {
val scoresAndWeightsSeq = candidates.map { candidate =>
PhoenixPredictedScoreFeatures.map { feature =>
val predictions = feature.extractScore(candidate.features, query)
val isEligible = feature.isEligible(candidate.features)
val score = if (predictions.nonEmpty && isEligible) predictions.max else 0.0
val weight = query.params(feature.modelWeightParam)
(score, weight)
}
}
val transformedScoresAndWeightsSeq = getScoresWithPerHeadMax(scoresAndWeightsSeq)
val featureMaps = transformedScoresAndWeightsSeq.map { transformedScores =>
val finalScore = aggregateWeightedScores(query, transformedScores, ...)
FeatureMapBuilder()
.add(PhoenixScoreFeature, Some(finalScore))
.build()
}
Stitch.value(featureMaps)
}
}
4.2.3 与多模型融合的区别
| 特性 | 多模型融合 | Phoenix 重排序 |
|---|---|---|
| 模型来源 | Navi 服务(传统模型) | Phoenix 服务(新模型) |
| 输入特征 | 静态特征 + 聚合特征 | 用户行为序列 + 静态特征 |
| 输出特征 | WeightedModelScoreFeature |
PhoenixScoreFeature |
| 融合方式 | 相同(加权融合) | 相同(加权融合) |
五、Phoenix 重评分的完整流程
5.1 在推荐 Pipeline 中的位置
候选生成
↓
特征提取
├─ 提取静态特征
└─ 提取用户行为序列(UserActionsFeature)⭐
↓
模型评分
├─ Navi 模型评分(多模型融合)
│ └─ WeightedModelScoreFeature
└─ Phoenix 模型评分(可选)⭐
└─ PhoenixScoreFeature
↓
启发式重评分
└─ ScoreFeature = WeightedModelScore × scaleFactor
↓
Phoenix 重评分(可选)⭐
└─ ScoreFeature = PhoenixScore × (ScoreFeature / WeightedModelScore)
↓
多样性重评分(可选)
↓
最终排序
5.2 三种模式的执行顺序
5.2.1 模式1:Phoenix 直接评分
PhoenixScorer
↓
PhoenixScoreFeature = Phoenix 预测分数
↓
HeuristicScorer(使用 PhoenixScoreFeature)
↓
最终分数
5.2.2 模式2:Phoenix 重排序
Navi 模型评分
↓
启发式重评分
↓
PhoenixModelRerankingScorer
↓
PhoenixScoreFeature = Phoenix 融合分数
↓
最终分数(使用 PhoenixScoreFeature)
5.2.3 模式3:Phoenix 重评分
Navi 模型评分
↓
启发式重评分
↓
PhoenixRescoringFeatureHydrator ⭐
↓
最终分数(调整后的 ScoreFeature)
六、Phoenix 模型的特点
6.1 用户行为序列输入
Phoenix 模型的核心输入是用户行为序列(UserActionSequence):
scala
override def onlyIf(query: PipelineQuery): Boolean = {
query.features.flatMap(_.getOrElse(UserActionsFeature, None)).isDefined
}
用户行为序列包含:
- 用户最近的行为历史
- 行为类型(点赞、回复、转发等)
- 行为时间戳
- 行为上下文
6.2 多预测输出
Phoenix 模型同时预测多种用户行为:
scala
val PhoenixPredictedScoreFeatures: Seq[PhoenixPredictedScoreFeature] = Seq(
PhoenixPredictedFavoriteScoreFeature, // 点赞
PhoenixPredictedReplyScoreFeature, // 回复
PhoenixPredictedRetweetScoreFeature, // 转发
PhoenixPredictedGoodClickConvoDescFavoritedOrRepliedScoreFeature, // 优质点击V1
PhoenixPredictedGoodClickConvoDescUamGt2ScoreFeature, // 优质点击V2
PhoenixPredictedGoodProfileClickScoreFeature, // 个人资料点击
PhoenixPredictedVideoQualityViewScoreFeature, // 视频质量观看
PhoenixPredictedShareScoreFeature, // 分享
PhoenixPredictedDwellScoreFeature, // 停留时间
PhoenixPredictedOpenLinkScoreFeature, // 打开链接
PhoenixPredictedScreenshotScoreFeature, // 截图
PhoenixPredictedBookmarkScoreFeature, // 收藏
PhoenixPredictedNegativeFeedbackV2ScoreFeature, // 负反馈
)
6.3 与生产模型的兼容性
Phoenix 模型支持回退到生产模型:
scala
def extractScore(features: FeatureMap, query: PipelineQuery): Option[Double] = {
if (query.params(useProdFeatureParam)) {
// 使用生产模型(PredictedScoreFeature)
prodScoreFeature.extractScore(features, query)
} else {
// 优先使用 Phoenix 预测,如果没有则回退到生产模型
features.getOrElse(this, None)
.orElse(prodScoreFeature.extractScore(features, query))
}
}
优势:
- 渐进式迁移:可以逐步从生产模型迁移到 Phoenix
- 容错性:如果 Phoenix 预测失败,回退到生产模型
- A/B 测试:可以对比 Phoenix 和生产模型的效果
七、Phoenix 重评分的优势
7.1 更准确的预测
- 用户行为序列:Phoenix 使用用户的历史行为序列,能更好地理解用户偏好
- 深度学习:使用深度学习技术,预测更准确
- 实时推理:支持实时推理,响应速度快
7.2 保留业务规则
- 启发式调整:保留启发式重评分的业务规则
- 平滑过渡:通过比例缩放实现平滑过渡
- 兼容性:与现有系统完全兼容
7.3 灵活部署
- 可选启用:可以通过参数控制是否启用
- 渐进式迁移:支持逐步迁移到 Phoenix
- A/B 测试:支持 A/B 测试和灰度发布
八、Phoenix 重评分的局限性
8.1 依赖用户行为序列
- 必要条件 :必须有
UserActionsFeature - 新用户问题:新用户可能没有足够的行为序列
- 回退机制:需要回退到生产模型
8.2 计算成本
- 模型复杂度:深度学习模型计算成本较高
- 延迟影响:可能增加推理延迟
- 资源消耗:需要更多的计算资源
8.3 比例缩放的假设
- 假设:启发式调整的比例适用于 Phoenix 分数
- 可能问题:如果 Phoenix 分数和传统分数差异很大,比例缩放可能不准确
- 注释说明:代码注释提到"可能不总是准确的列表式启发式"
九、实际应用场景
9.1 场景1:渐进式迁移
目标:从传统模型逐步迁移到 Phoenix 模型
步骤:
- 启用 Phoenix 重评分(小流量)
- 监控效果(CTR、参与度等)
- 逐步扩大流量
- 最终完全迁移到 Phoenix
9.2 场景2:A/B 测试
目标:对比 Phoenix 和传统模型的效果
方案:
- 实验组:启用 Phoenix 重评分
- 对照组:使用传统模型
- 对比指标:CTR、参与度、用户满意度
9.3 场景3:特定用户群体
目标:对特定用户群体使用 Phoenix 模型
方案:
- 高活跃用户:启用 Phoenix 重评分
- 新用户:使用传统模型(回退)
- 低活跃用户:使用传统模型
十、代码位置
10.1 Phoenix 重评分
- 文件 :
home-mixer/server/src/main/scala/com/twitter/home_mixer/functional_component/feature_hydrator/PhoenixRescoringFeatureHydrator.scala - 关键方法 :
apply
10.2 Phoenix 直接评分
- 文件 :
home-mixer/server/src/main/scala/com/twitter/home_mixer/functional_component/scorer/PhoenixScorer.scala - 关键方法 :
apply
10.3 Phoenix 重排序
- 文件 :
home-mixer/server/src/main/scala/com/twitter/home_mixer/functional_component/scorer/PhoenixModelRerankingScorer.scala - 关键方法 :
apply
10.4 Phoenix 预测特征
- 文件 :
home-mixer/server/src/main/scala/com/twitter/home_mixer/model/PhoenixPredictedScoreFeature.scala - 内容:定义所有 Phoenix 预测特征
十一、总结
11.1 核心要点
- Phoenix 模型:新一代预测模型,使用用户行为序列作为输入
- Phoenix 重评分:使用 Phoenix 分数调整已有分数,保留启发式调整
- 比例缩放 :
finalScore = phoenixScore × (currentScore / weightedModelScore) - 三种模式:直接评分、重排序、重评分
11.2 关键公式
Phoenix 重评分公式:
finalScore = phoenixScore × (currentScore / weightedModelScore)
其中:
- currentScore: 经过启发式重评分后的分数
- weightedModelScore: 多模型融合后的原始分数
- phoenixScore: Phoenix 模型预测的分数
11.3 使用条件
scala
usePhoenixRescoring =
EnablePhoenixScorerParam &&
EnablePhoenixRescoreParam &&
!EnablePhoenixScoreParam
11.4 设计理念
- 更准确的预测:使用用户行为序列提供更准确的预测
- 保留业务规则:通过比例缩放保留启发式调整
- 平滑过渡:支持渐进式迁移和 A/B 测试
- 灵活部署:可选启用,支持回退机制
参考文件:
home-mixer/server/src/main/scala/com/twitter/home_mixer/functional_component/feature_hydrator/PhoenixRescoringFeatureHydrator.scalahome-mixer/server/src/main/scala/com/twitter/home_mixer/functional_component/scorer/PhoenixScorer.scalahome-mixer/server/src/main/scala/com/twitter/home_mixer/functional_component/scorer/PhoenixModelRerankingScorer.scalahome-mixer/server/src/main/scala/com/twitter/home_mixer/model/PhoenixPredictedScoreFeature.scala