如何通过辅助排序损失优化推荐模型在稀疏反馈场景下的性能(KDD‘2024)
1. 稀疏反馈场景下的推荐模型挑战在推荐系统领域我们经常会遇到一个头疼的问题用户的正反馈比如点击、购买实在太少了。想象一下你在运营一个电商平台每天有上百万的商品展示但用户平均点击率可能还不到2%。这就好比在沙漠里找绿洲大部分区域都是干旱的荒漠负样本只有零星几处水源正样本。这种情况下传统的二分类交叉熵损失BCE loss会遇到一个致命问题负样本梯度消失。简单来说模型在训练时对于那些没被点击的商品负样本学到的信息量非常有限。就像老师给全班同学讲课但只关注那几个举手发言的学生其他沉默的同学就被忽略了。具体来说当CTR2%时正样本梯度1-p̂ ≈ 0.98信号强烈负样本梯度p̂ ≈ 0.02几乎消失这种现象会导致两个严重后果模型对负样本的学习不充分整体收敛速度变慢效果打折扣2. 辅助排序损失的工作原理2.1 排序损失的三大门派解决上述问题的一个有效方法就是引入辅助排序损失。这就像给模型请了个私教专门训练它理解物品之间的相对关系。排序损失主要分三种类型Pointwise单兵作战单独评估每个item的预测值典型代表就是BCE lossPairwise两两对比让正样本得分高于负样本常见如RankNet的损失函数def pairwise_loss(pos_score, neg_score): return -torch.log(torch.sigmoid(pos_score - neg_score))Listwise团队作战直接优化整个列表的排序比如ListNet的损失函数def listwise_loss(scores, labels): return torch.nn.CrossEntropyLoss()(scores, labels)2.2 组合损失的协同效应在实际应用中我们发现把BCE loss和排序loss结合起来效果最好。这就好比BCE是基础课保证预测准确度排序loss是专业课提升排序质量Twitter提出的Combined-Pair方法就是个典型例子总损失 α * BCE_loss (1-α) * Pairwise_loss这个组合带来了三个好处负样本获得更大的梯度模型收敛更快最终排序效果更好3. 梯度视角的技术解析3.1 BCE损失的梯度缺陷让我们深入看看BCE loss的梯度问题。对于一个负样本梯度 p̂ (预估点击率)当CTR2%时梯度只有0.02。这就好比用滴灌浇灌沙漠效果微乎其微。而正样本的梯度梯度 1 - p̂ ≈ 0.98明显强得多但这种不平衡会导致模型偏置。3.2 组合损失的梯度增强加入排序loss后负样本的梯度变为新梯度 p̂ σ(z⁻ - z⁺)其中第二项通常远大于第一项。实验数据显示在CTR3.3%时纯BCE的负样本梯度norm≈0.03Combined-Pair的梯度norm≈0.15提升了整整5倍这就把滴灌变成了喷灌大大改善了学习效率。4. 实战中的关键策略4.1 稀疏度与效果关系通过调整正样本权重β_pos我们发现一个有趣现象β_posCTRAUC提升幅度0.820.5%0.020%0.13.3%0.095%结论很明显数据越稀疏组合损失的优势越大。当CTR5%时效果提升尤为显著。4.2 损失权重的黄金比例组合权重α的选择很关键。经过大量实验我们总结出初始建议值α0.7稀疏度越高α可以越小极端稀疏时(CTR1%)α可降至0.5一个实用的调整策略def get_alpha(ctr): base 0.7 if ctr 0.01: return base - 0.2 elif ctr 0.05: return base - 0.1 else: return base4.3 排序损失的选择不同的排序loss各有特点类型计算成本效果适用场景Pairwise中等优大多数推荐场景Listwise较高极优小规模精排Hinge loss低良快速迭代场景对于大多数工业级推荐系统我推荐先用Pairwise试水稳定后再尝试Listwise。5. 进阶优化方案5.1 Combined-Contrastive方法受对比学习启发我们可以加入对比损失contrastive_loss -log(exp(z_i·z_p/τ) / ∑exp(z_i·z_k/τ))其中z_i: 当前样本embeddingz_p: 同label样本embeddingz_k: 所有其他样本embedding这种方法在CTR1%时相比纯BCE能提升AUC达0.12%。5.2 负采样策略合理的负采样可以缓解梯度消失保留所有正样本对负样本随机采样10%-20%对采样样本的loss乘以补偿权重注意采样率不宜过低否则会损失信息。实验表明10%-30%的采样率效果最佳。6. 工程实现要点6.1 TensorFlow实现示例def combined_loss(labels, logits, alpha0.7): # BCE loss bce_loss tf.nn.sigmoid_cross_entropy_with_logits(labels, logits) # Pairwise loss pos_mask tf.cast(labels 0, tf.float32) neg_mask 1 - pos_mask pos_scores tf.reduce_sum(logits * pos_mask) / tf.reduce_sum(pos_mask) neg_scores tf.reduce_sum(logits * neg_mask) / tf.reduce_sum(neg_mask) pair_loss -tf.math.log_sigmoid(pos_scores - neg_scores) return alpha * bce_loss (1-alpha) * pair_loss6.2 训练技巧学习率调整组合损失需要更小的学习率建议初始值设为纯BCE的0.5-0.8倍Batch Size使用更大的batch至少512以获得稳定的pairwise计算早停策略验证集AUC连续3个epoch不提升时停止7. 效果验证与调优在实际项目中我建议按以下流程验证离线评估AUC提升至少0.5%BCE loss下降明显排序指标NDCG提升在线AB测试点击率提升转化率提升用户停留时间增长一个真实的案例在某电商平台应用后CTR提升了1.2%GMV增加了0.8%。关键是要持续监控效果特别是在数据分布变化时及时调整损失权重。