从DSSM到美团双塔:聊聊推荐系统召回阶段那些‘负样本’的坑与实战经验
从DSSM到美团双塔:推荐系统召回阶段的负样本工程实战
在推荐系统的战场上,召回阶段如同一位不知疲倦的侦察兵,它的任务是从海量候选物品中快速筛选出用户可能感兴趣的几百个目标。而决定这位侦察兵作战能力的核心要素,往往不是模型结构有多复杂,而是训练时喂给它的"食物"——特别是那些被称为"负样本"的反面教材。
1. 负样本:召回模型训练的隐形指挥官
2013年微软提出的DSSM模型开启了双塔架构的工业级应用,但很快工程师们发现:模型表现对负样本选择的敏感度远超模型结构本身。美团技术团队在2021年的实证研究表明,仅优化负采样策略就能带来线上CTR提升17.6%,这比增加5层神经网络的效果更为显著。
负样本之所以关键,是因为它定义了模型需要学习的"边界"。想象一位正在学习辨认猫狗的小孩:
- 如果只给他看猫的照片(正样本)和汽车的图片(负样本),他很快能区分猫和汽车
- 但这种能力无法帮助他区分猫和狗这种更细微的差异
- 这就是推荐系统中"样本选择偏差"问题的生动比喻
2. 主流负采样策略的战场地图
2.1 全局随机采样:基础但危险的起点
# 典型全局随机采样实现 def global_negative_sampling(user_items, item_pool, num_negatives): negatives = [] for _ in range(num_negatives): neg_item = random.choice(item_pool) while neg_item in user_items: # 避免将用户正样本误采为负样本 neg_item = random.choice(item_pool) negatives.append(neg_item) return negatives优势:
- 实现简单,计算成本低
- 严格符合物品的真实分布
缺陷:
- 采样效率低下(约90%的负样本与正样本差异过大)
- 容易导致模型陷入局部最优(仅学会区分明显不相关物品)
实践提示:当物品库超过百万量级时,建议采用基于流行度的加权随机采样,避免长尾物品被过度采样。
2.2 Batch内负采样:效率与质量的平衡术
| 指标 | 全局随机采样 | Batch内采样 | 混合采样 |
|---|---|---|---|
| 训练速度 | 1x | 3.2x | 1.8x |
| 线上NDCG@100 | 0.42 | 0.51 | 0.56 |
| 长尾覆盖率 | 78% | 65% | 72% |
美团2022年分享的实践经验表明:
- 纯Batch内采样会导致热门物品被过度打压
- 最佳实践是采用7:3的全局与Batch内混合采样
- 需配合动态温度系数调整样本权重
2.3 困难负样本挖掘:模型进化的磨刀石
困难负样本是指那些与正样本相似度高,但用户最终没有交互的物品。这类样本如同让拳击手与势均力敌的对手较量,能显著提升模型的判别能力。
主流挖掘方法:
- 召回漏斗法:用上一版模型召回Top200结果,剔除正样本后作为困难负例
- 向量聚类法:在embedding空间寻找邻近非正样本
- 行为图谱法:利用用户跳过/快速滑过的曝光记录
# 基于向量相似度的困难负样本挖掘 def find_hard_negatives(user_embed, item_embeddings, pos_items, k=10): similarities = np.dot(item_embeddings, user_embed) sorted_indices = np.argsort(-similarities) hard_negs = [] for idx in sorted_indices: if idx not in pos_items and len(hard_negs) < k: hard_negs.append(idx) return hard_negs3. 流行度偏差:推荐系统的阿喀琉斯之踵
物品流行度与负采样策略存在微妙博弈。我们观察到三个关键现象:
- 马太效应:过度打压热门物品会导致推荐多样性下降
- 冷启动困境:完全忽略流行度会使新物品失去曝光机会
- 用户感知偏差:用户对热门物品的期待阈值更高
平衡策略对比:
| 策略类型 | 实现方式 | 优点 | 缺点 |
|---|---|---|---|
| 热度降权 | 1/(1+log(popularity)) | 简单可控 | 需要调参 |
| 对抗学习 | 增加流行度判别器 | 自动平衡 | 训练不稳定 |
| 两阶段采样 | 先按热度分组再采样 | 分布可控 | 实现复杂 |
美团在公开技术分享中透露,他们在短视频推荐中采用动态流行度门控:
- 新用户倾向更多热门内容建立认知
- 老用户逐渐增加长尾内容比例
- 通过贝叶斯平滑动态调整采样权重
4. 样本权重调参:被忽视的艺术
大多数论文聚焦于采样方法本身,却鲜少讨论不同负样本该如何赋予不同权重。实际上,这是一个堪比炼丹的精细工艺:
- 困难样本加权:对模型预测得分接近正样本的负例增加权重
def dynamic_weight(score, positive_score, temperature=0.1): return torch.exp((score - positive_score)/temperature) - 时间衰减系数:对老旧负样本逐步降低权重
- 曝光补偿:对多次曝光未点击的物品适当增加权重
某电商平台AB测试数据显示,精细化的样本权重调整能带来:
- 人均GMV提升9.3%
- 商品详情页停留时长增加22%
- 跨类目购买率提高15%
5. 线上效果监控:负样本的终极审判
再完美的离线实验也需要接受线上AB测试的检验。我们建议监控以下核心指标:
基础指标组:
- 召回率@100
- 点击通过率
- 首屏点击深度
高级诊断指标:
- 负样本预测得分分布(应与正样本有明显间隔)
- 困难负样本的混淆矩阵
- 用户行为序列的连贯性分析
在模型部署后,还需要建立负样本的动态淘汰机制:
- 每周分析被误判严重的"假负样本"(实际用户可能喜欢)
- 对连续多周高预测得分的负样本进行人工审核
- 建立负样本质量评分卡系统
6. 前沿探索:负样本的智能进化
在美团最新公开的专利中,我们看到了几个值得关注的方向:
课程学习式采样:
- 训练初期使用简单负样本建立基础能力
- 逐步引入困难样本提升判别力
- 最终加入对抗样本增强鲁棒性
图结构负采样:
# 基于知识图谱的负采样示例 def kg_aware_negative_sampling(user, pos_item, kg_graph, n_negs=5): same_category = kg_graph.get(pos_item, 'category') neighbors = kg_graph.get_relations(pos_item) candidates = [] for item in neighbors: if kg_graph.get(item, 'category') != same_category: candidates.append(item) return random.sample(candidates, min(n_negs, len(candidates)))多模态对比学习:
- 利用图像/文本相似度构造语义负样本
- 通过跨模态对齐发现潜在困难样本
- 美团外卖团队实测此方法提升新商家曝光量37%
在实际业务中,我们发现一个有趣现象:当负样本策略优化到一定程度后,模型对架构变化的敏感度会显著降低。这或许印证了业界那句老话:"推荐系统的艺术,八成在数据,两成在模型。"
