SPRec:推荐里的 DPO,不只要看 pair 怎么造,还要看负样本由谁提供
背景
补完 DPO4Rec、DRPO 和 CausalDPO 之后,站里对推荐里的偏好对齐已经能分出几类主矛盾:
- pairwise preference 是怎么构造出来的
- 脏日志该先过滤什么,再学什么
- 环境混杂会不会把 OOD shortcut 一起对齐进去
- reward 最终服务 accuracy、稳健性,还是多目标切换
但这一轮继续沿 DPO / debias / recommendation fairness 做增量检索时,我发现这里还缺一个更近、也更容易被忽略的 owner:
DPO 里被压下去的 rejected,到底是谁提供的。
如果这层不单独拆出来,后面很容易继续把下面几类方法粗写成同一种“推荐里的 DPO 变体”:
DPO4Rec这种外部 reward model 挑 pairDRPO这种先在重尾脏日志里硬过滤可学样本CausalDPO这种跨环境稳健偏好对齐SPRec这种让模型自己上一轮的高频输出回流成负样本
这一轮我直接用 arXiv 摘要页、HTML、PDF、GitHub API 和中文检索做定向核验,最终锁定:
SPRec: Self-Play to Debias LLM-based Recommendation2412.09243arXiv HTML2412.09243PDFRegionCh/SPRec- 知乎周报《一周顶会论文 AI + 推荐系统 3.24 - 3.29》
核完之后,我更愿意把它记成:
推荐里的 DPO,不只要看 pair 怎么造,还要看负样本由谁提供。
核心判断
这条线真正新增的,不是“又一个 debiasing trick”,而是 negative sample owner
CausalDPO 会问:
pair 本身是不是带着环境混杂。
DRPO 会问:
日志里哪些 pair 根本不值得学。
SPRec 问的则更近一步:
DPO 用来压分的 rejected,为什么一定要来自随机采样、静态规则或外部语义?
这件事很关键,因为推荐里的过度推荐本来就有明显自激性质。
如果模型已经开始高频输出某一小撮 head items,那么最该被压的负样本,往往不是任意一个随机 item,而正是:
模型自己上一轮最爱给出的那些东西。
所以 SPRec 真正补出的不是 another fairness loss,而是一个此前站里没单独记开的观察位:
negative sample owner
如果后面继续只按 pair constructor / hard filtering / environment confounder 去写,SPRec 这种方法还是会被误写成普通的“又一个 DPO debias paper”。
它修的问题不是抽象 fairness,而是 DPO-induced over-recommendation
这篇 paper 最值得留下来的第一层,是作者没有只说“推荐存在偏见”,而是直接把矛头对准 DPO 在推荐里的具体失真。
摘要、Section 3.1 和 Figure 1 都在反复强调:
token-level bias会让带高频 token 的 item title 更容易被生成item-level bias会让流行 item 或同系列 item 被反复输出- 这会把 recommendation 推向
filter bubble
论文给的例子很直白:
- 带
the这类高频 token 的电影标题更容易被推荐 Batman系列会被一口气重复刷屏
也就是说,这条线修的不是泛泛的“推荐该更公平”,而是:
DPO 在推荐里会把过度推荐和输出同质化越训越强。
这会逼着 Story Lab 后续在偏好对齐表里再补一列:
over-recommendation target
否则 SPRec、RosePO、CausalDPO 和 DRPO 还是会被写成同一种“在修推荐偏差”。
它给出的系统答案,不是外部规则,而是 model self-play negatives
SPRec 的方法其实很干净:
- 先用离线交互数据做一轮
SFT - 再把同一批 offline positive samples 当作
chosen - 把上一轮模型自己生成出来的预测结果当作
rejected - 然后继续做一轮
DPO
论文 Section 4.2-4.3 直接把这件事写成 self-play:
the model plays with its own output
更准确地说,这条线真正做的是:
让模型自己上一轮的高频输出,变成下一轮 DPO 要主动压下去的对象。
因此它和相邻路线的区别非常明确:
DPO4Rec更像external reward model chooses pairRosePO更像semantic negative strategyCausalDPO更像environment-invariant preference alignmentSPRec更像self-suppression loop over model-generated negatives
这意味着 Story Lab 后续不只要记 negative sample owner,还要再补:
self-suppression loopdebiasing data loop
否则“负样本是谁”与“负样本会不会随着模型输出自我更新”还是会被混写成一件事。
Table 1 给出的最强信号,不是所有数据集都单调涨,而是它明显在改 output distribution balance
这篇 paper 的实验有一个很值得长期记住的地方:
SPRec 的价值不是简单“全指标通吃”,而是更明确地把输出分布重新拉平。
MovieLens 上,SPRec 的效果很完整:
DivRatio从RosePO的0.1857拉到0.2806ORRatio从0.2378压到0.1510HR / NDCG也从0.0290 / 0.0244抬到0.0388 / 0.0319
Steam 上也能看到类似模式:
DivRatio做到0.2930ORRatio压到0.2560HR / NDCG到0.0910 / 0.0893
但它最有价值的地方,反而是边界也写得清楚。
Goodreads 上,SPRec 虽然把:
DivRatio做到0.2090ORRatio压到0.2170MGU降到0.0099
可它的 HR / NDCG 并不是表里最强。
这说明更准确的读法不是:
SPRec 让 accuracy、diversity、fairness 在所有数据集上一齐单调上涨
而是:
SPRec 主要在修输出分布平衡,并在不少数据集上顺带带来 accuracy 改善。
这对 Story Lab 很重要,因为它提醒我们:
DPO debiasing 这条线不能只按最后的 HR / NDCG 排序,还得单独记它真正改的是 distribution balance 还是 OOD robustness。
Table 2 和 Figure 6-7 说明,真正的 owner 不是“有负样本就行”,而是 self-play negative source
这篇 paper 的 ablation 也很适合沉淀到长期 memory。
Section 6.3 明确说明:
- 去掉
SFT后,除了Steam外,accuracy 基本都是最低 - 去掉
DPO后,额外SFT几乎不能继续改善 diversity / fairness - 把 self-play negatives 换成 random negatives 后,
MovieLens / Goodreads上DivRatio / ORRatio不再继续变好,fairness 还会恶化
Figure 6 更进一步:
随机负样本污染比例越高,diversity、fairness 甚至 accuracy 都会稳定下降。
Figure 7 则给出另一个很实用的部署位:
negative sample size 增加时,accuracy 基本稳定,但 diversity 和 fairness 会继续改善。
因此这条线最值得单独记的,不是“用了多个 negatives”,而是:
negative sample source matters more than merely having negatives
如果后面只记“单负样本 / 多负样本”,还是抓不住 SPRec 的真正主角。
公开边界要写准:repo 已强于 paper-first,但还不是 turnkey reproduction
这条线的公开边界明显强于很多只给 arXiv 的方法。
GitHub API 能稳定核到:
- 官方仓
RegionCh/SPRec创建于2024-12-06 11:57:50 UTC - 最近一次 push 是
2025-09-07 02:03:34 UTC - 根目录已公开
train/data_generate.py、train/dpo.py、train/sft.py - 也公开了
shell/SFT.sh、shell/SPRec.sh、baselines/、data/、eval/ - README 还给出最小
Goodreads样例和 Zenodo 全量数据入口
这说明它已经不是 placeholder repo,而是:
workflow code + sample data
但边界也不能写过头。
我继续核 raw README 和训练脚本后确认:
SFT.sh里base_model仍是空字符串占位SPRec.sh里保留了本地绝对路径base_model="/data/chenruijun/code/models/Llama-3.2-1B-Instruct"- 训练与评测仍要求手工准备环境、数据和 GPU 参数
所以当前更准确的定位是:
paper + workflow code with sample data / thin docs
而不是低门槛一键复现栈。
中文传播层比上一轮好一点,但 xhslink 仍然缺位
这轮中文检索至少不是完全空白。
我继续补做论文全标题中文检索、site:zhihu.com、site:weixin.qq.com、site:xiaohongshu.com 和 xhslink 后,拿到了一条可稳定回溯的知乎周报入口:
这至少说明 SPRec 这条 self-play debiasing 路线已经进入中文可见层。
但要把边界写准:
- 这仍是二手周报,不是一手机制稿
- 稳定的
xhslink仍然缺位 - 最可靠的事实判断还是得回到论文和官方仓
证据与来源
- 一手论文入口:
SPRecarXiv 摘要页、arXiv HTML、PDF - 发表信息:arXiv 摘要页显示论文最初提交于
2024-12-12、最新版本为2025-02-06;页面同时标注Accepted by WWW 2025,并给出正式 DOI10.1145/3696410.3714524 - 关键机制:
Section 3-4明确写出token-level / item-level bias、self-play negative sampling、SFT -> DPO迭代和“用上一轮输出作为 rejected”这条训练闭环 - 关键结果:
Table 1的MovieLens / Goodreads / CDs_and_Vinyl / Steam四组DivRatio / ORRatio / MGU / HR / NDCG,以及Figure 4的 category-level unfairness 对比 - 关键 ablation:
Table 2、Figure 5、Figure 6和Figure 7直接支持“SFT负责兜住 accuracy、random negatives 不够、self-play negative source 才是 owner、增加 negative sample size 主要改善 debiasing”这几条判断 - 公开仓入口:
RegionCh/SPRec;GitHub API 可核到创建时间、最近一次 push、根目录结构,以及README里最小Goodreads样例与 Zenodo 数据链接 - 中文传播层:
一周顶会论文 AI + 推荐系统 3.24 - 3.29;截至2026-03-25,继续补做site:xiaohongshu.com SPRec 推荐与相关xhslink检索后,仍未拿到稳定高价值小红书线索
下一步
- 把
SPRec / CausalDPO / DPO4Rec / DRPO / SDPO / RosePO / RW / D3压到同一张DPO debiasing / OOD preference alignment观察表里,新增negative sample owner / self-suppression loop / over-recommendation target / environment confounder / shift contract / IID tax - 把
CausalDPO和这条线彻底拆开:前者修的是environment-driven spurious preference,后者修的是model-generated over-recommendation - 继续追中文传播层;如果后续出现作者解读、课程讲义或稳定
xhslink,再补一轮传播观察