工业级推荐系统的核心矛盾很简单:候选物品可能有上亿规模,而留给一次请求的时间预算只有几十到一两百毫秒。你不可能用一个复杂模型把每个物品都打一遍分。所以现代推荐系统几乎都长成同一个形状——漏斗。
直觉:为什么要分层
设想线上有 个候选物品,最终只需返回 个。如果只用一个模型,单次打分耗时 ,那么总耗时是 。哪怕 ,乘上 也是 100 秒,完全不可接受。
漏斗的思想是用计算复杂度换数据规模:在候选多的阶段用便宜的模型,在候选少的阶段用昂贵的模型。典型分层是:
1 | 亿级物品 --[召回 Recall]--> 千级 --[粗排 Pre-rank]--> 百级 --[精排 Rank]--> 十级 --[重排 Re-rank]--> 展示 |
每一层都在做"在保证不漏掉好物品的前提下,尽量减少候选数"。这里有个关键的非对称性:漏斗上游的目标是高召回率(别漏),下游的目标是高精度(排准)。上游错杀一个好物品,下游再强也救不回来。
召回:双塔与近似最近邻
召回阶段要从亿级里捞出千级,时间预算意味着不能做用户-物品的两两交叉计算。主流方案是双塔模型(two-tower):用户塔把用户特征编码成向量 ,物品塔把物品特征编码成向量 ,相关性用内积近似:
双塔的工程价值在于物品向量可以离线全量预计算并建索引。线上只需实时算出一个用户向量,然后在向量库里做近似最近邻(ANN)检索。常见的 ANN 算法是 HNSW(分层可导航小世界图),它把暴力检索的 降到约 ,代价是少量召回精度损失和额外内存。
训练上,双塔通常用 in-batch negative sampling:一个 batch 内,其它用户点击的物品就当作当前用户的负样本,配合 softmax 或 sampled softmax loss。这里有个经典踩坑——热门物品采样偏差。热门物品作为负样本出现的概率天然高,会被模型过度惩罚。工业实践常用 logQ 校正(log-correction),在打分时减去采样概率的对数:
其中 是物品 被采样的概率估计。
另外,召回从来不是单路。实际系统会并行跑多路召回:双塔向量召回、协同过滤 itemCF、热门召回、地理位置召回、新品探索召回……然后取并集。多路召回保证了多样性和兜底,单路挂了不至于开天窗。
粗排:轻量交叉的过渡层
粗排是个容易被忽视但很关键的环节。它接收千级候选,要在更紧的算力下削到百级。粗排不能像双塔那样完全不交叉(精度不够),又不能像精排那样全特征交叉(太慢)。
常见做法是轻量级双塔 + 少量交叉,或者用精排模型蒸馏出的小模型。粗排和精排之间存在一个微妙的一致性问题:如果粗排的打分分布和精排严重不一致,粗排会把精排本来会选中的好物品提前筛掉,造成样本选择偏差(sample selection bias)——精排模型只在粗排放行的样本上训练,但线上要对全量打分。缓解手段之一是让粗排去蒸馏精排的输出分数,使二者排序尽量对齐。
精排:特征交叉与多目标
精排是整个系统模型最复杂的地方,只需处理百级候选,可以上重模型。这里允许用户、物品、上下文特征做充分交叉。一条主线是显式特征交叉的演进:
- FM(因子分解机):把二阶交叉写成隐向量内积,,解决了 one-hot 高维稀疏下交叉项参数过多、样本稀疏学不动的问题。
- Wide & Deep / DeepFM / DCN:deep 侧用 MLP 学高阶隐式交叉,wide 侧或 cross 网络保留显式低阶交叉,互补。
精排另一个核心是多目标。推荐很少只优化点击率(CTR),往往还要时长、点赞、转化、完播等。常用 MMoE(Multi-gate Mixture-of-Experts):多个 expert 子网络共享底层,每个目标有独立 gate 决定如何加权 expert 输出,缓解多任务之间的"跷跷板效应"。
多目标的分数最终要融合成一个排序分。一种常见的乘法融合:
1 | # pCTR/pCVR/p_time 分别是各目标预估值 |
指数 通常通过线上 A/B 实验调,而非纯离线学习——因为最终目标是业务指标,不是单个 loss。
工程权衡与边界
几个反复出现的取舍:
- 特征时效性。用户实时行为序列(刚点了什么)信息量极大,但拉取和拼接实时特征会增加延迟。很多系统用单独的特征服务 + 缓存来平衡。
- 离线在线一致性。训练用离线特征,线上用实时特征,一旦同一特征在两侧计算口径不同(train-serving skew),模型线上表现会莫名其妙地崩。这是推荐系统最常见、最难排查的 bug 之一。
- 位置偏差。日志里排在前面的物品天然点击多,直接拿来训练会让模型学到"它在前面所以好"。常用做法是把位置作为特征喂进去,预测时置零。
- 新物品/新用户冷启动。向量召回对没有交互历史的新物品几乎无能为力,需要内容特征召回和探索机制兜底。
小结
推荐系统不是一个模型,而是一条算力与候选数互相博弈的漏斗流水线。理解它的关键不在于某个网络结构有多花哨,而在于每一层的目标定位(上游保召回、下游保精度)、层与层之间的一致性(粗排蒸馏精排、离线对齐在线),以及把模型分数翻译成业务收益的多目标融合。把这条数据流想清楚,再去看具体的网络结构,才不会只见树木。