S-DPO:推荐里的 DPO,不只要更多 negative,还要决定这些 negative 是逐对比较还是共同竞争

背景

补完 DRPOSPRecCausalDPORosePO 之后,站里对推荐里的 DPO 已经能分出不少问题位:

  1. pairwise preference 是怎么构造出来的
  2. rejected 到底是谁供给的
  3. 环境混杂会不会被一起对齐进去
  4. helpfulness 和 harmlessness 是否需要分轴处理

但这一轮继续回头看 SDPO / RW / D3 这组还没补完的邻近路线时,我发现这里还缺一个更底层、也更容易被忽略的损失位:

当推荐里不止一个 negative 时,这些 negative 在目标函数里到底是独立 pair,还是共同竞争同一个 chosen

如果不把这层单独记出来,后面就很容易把下面几类方法继续混成同一种“推荐里的 DPO 变体”:

  1. DPO4Rec 这种仍以 pairwise chosen/rejected 为主的对齐
  2. SPRec 这种重点改 rejected owner 的 self-play 路线
  3. RosePO 这种重点改 value-axis-specific rejected sampling 的路线
  4. S-DPO 这种重点改 multiple negatives 在 loss 里如何耦合的路线

这一轮我直接用 arXiv 摘要页、HTML、NeurIPS 官方 poster 页、会议 PDF、GitHub API 与中文网页检索做定向核验,最终锁定:

  1. On Softmax Direct Preference Optimization for Recommendation
  2. 2406.09215 arXiv HTML
  3. NeurIPS 2024 Poster
  4. NeurIPS 2024 官方 PDF
  5. chenyuxin1999/S-DPO

核完之后,我更愿意把它记成:

推荐里的 DPO,不只要更多 negative,还要决定这些 negative 是逐对比较还是共同竞争

核心判断

这条线真正新增的,不是“再加几个 negative”,而是 comparison unit

SPRec 问的是:

rejected 到底应该由随机采样、外部规则,还是模型自己上一轮输出供给

RosePO 问的是:

rejected 应该围绕哪条人类价值轴去构造

S-DPO 问的则更底层:

一旦我们手里已经有多个 negative,它们在目标函数里到底应该被看成几对独立比较,还是一个耦合的竞争集合

这件事很关键,因为推荐任务天然不是普通的单 pair 判断。

真实问题更接近:

在一组候选里,chosen 相对多个 negatives 的排序关系应该怎样被共同写进 loss

因此这篇 paper 真正补出的不是 another DPO trick,而是一个此前站里还没单独命名的位:

comparison unit

如果不把这层单独拆出来,后面就会继续把“多负样本”只理解成数据量变多,而看不见:

同样是 K 个 negatives,把它们拆成 K 个 pairwise DPO,和把它们写成一个 softmax 竞争目标,并不是一回事

它修的问题不是抽象的“DPO 不够强”,而是 pairwise decomposition tax

这篇 paper 最值得留下来的第一层判断,是作者没有只说:

pairwise DPO 在推荐里效果一般

它更具体地指出:

当 recommendation 本身是排序问题时,把多个 negatives 全都拆成彼此独立的 pairwise DPO,会损失 ranking geometry

论文 1 / 3.1 / A.2 把这件事说得很清楚:

  1. 传统 DPO 更接近 Bradley-Terry 风格的 pairwise preference
  2. 推荐场景里更自然的是 partial ranking
  3. 因此作者把目标函数扩到 Plackett-Luce,让 chosen 和多个 negatives 一起形成相对排序

也就是说,这条线真正修的不是“negative 不够多”,而是:

multiple negatives 被 pairwise 拆开之后,推荐原生的排序结构被削弱了

这会逼着 Story Lab 后续在 DPO / preference alignment 图里再补一个此前没有单独记开的观察位:

pairwise decomposition tax

否则后面再整理 DPO4Rec / S-DPO / SPRec / RosePO / CausalDPO 时,还是会把“谁来造 pair”和“多个 negatives 是否被耦合进同一个 ranking target”混成同一件事。

它给出的系统答案,不是普通 multi-negative DPO,而是 negative coupling geometry

S-DPO 最核心的方法判断,不是简单把 K 个 negatives 逐个喂给 DPO。

它真正做的是:

把 multiple negatives 写成 softmax-coupled ranking objective

论文摘要、Section 3.1 和官方 NeurIPS poster 都明确写到三层关键动作:

  1. 从 pairwise DPO 扩到 partial-ranking Plackett-Luce
  2. 让 chosen 对多个 negatives 的关系在同一个目标里被联合建模
  3. 再把这条目标和推荐里更熟悉的 sampled softmax / contrastive loss 连接起来

这件事的重要性在于,它把一个此前常被借来借去的 LLM alignment loss,重新接回了 recommendation-native objective 家族。

因此这条线最值得单独记住的一句话不是:

DPO 也能用多个 negatives

而是:

multiple negatives 在推荐里不只是更多监督,而是 loss geometry 本身

这会逼着 Story Lab 再补至少两列:

  1. negative coupling geometry
  2. objective bridge

否则后续很容易继续把下面这些路线都写成“推荐里的 DPO”:

  1. DPO4Rec:pairwise alignment
  2. SPRec:self-play negative supply
  3. RosePO:value-axis-specific rejected sampling
  4. S-DPO:softmax-coupled multi-negative ranking

Table 1 最值得留下来的,不只是涨点,而是 objective-level tailoring 真能赢

Table 1 给出的最强信号,不是 S-DPO 在三库上都比 baseline 强,而是:

只改 recommendation-specific objective,就已经能稳定超过更早的 LM-based recommender 路线

论文在 Goodreads / LastFM / MovieLens 上给出的 S-DPO 主结果分别是:

  1. GoodreadsHR@1 = 0.6609ValidRatio = 0.9900
  2. LastFMHR@1 = 0.6628ValidRatio = 0.9992
  3. MovieLensHR@1 = 0.5263ValidRatio = 0.9895

对照第二名 baseline:

  1. Goodreads 相对 LLaRA 0.5292 提升 24.89%
  2. LastFM 相对 LLaRA 0.4508 提升 47.03%
  3. MovieLens 相对 LLaRA 0.4737 提升 11.10%

这件事很重要,因为它说明推荐里的 LLM alignment 不一定每次都先靠:

  1. 更复杂的 reward
  2. 更多外部 teacher
  3. 更长的 reasoning trace

它也可以先靠:

把 objective 本身从 language modeling / pairwise DPO,重新写成 recommendation-native ranking geometry

这也是为什么我觉得 S-DPO 值得单独落盘。它补的不是又一条工程分支,而是:

objective-level tailoring as a first-class owner

Table 2 更关键:这条线修的不是 negative 数量,而是 multi-negative aggregation

我觉得 S-DPO 最容易被误读的地方,就是看完题目后只记住:

它用了多个 negatives

Table 2 恰恰说明,主角不是数量本身,而是 aggregation 方式。

论文在相同 K = 3 negatives 下,对比了:

  1. DPO-1 negative
  2. DPO-K negative
  3. S-DPO-K negative

结果是:

  1. LastFM 上,DPO-KHR@1 / ValidRatio0.6413 / 0.9964S-DPO-K0.6477 / 0.9980
  2. MovieLens 上,DPO-K0.4947 / 0.9474S-DPO-K0.5263 / 0.9895
  3. Goodreads 上,DPO-K0.6628 / 0.9900S-DPO-K0.6661 / 0.9950

也就是说,这篇 paper 真正证明的不是:

给 DPO 多几个 negatives 一定会更好

而是:

即便 negative 个数相同,pairwise multi-negative DPO 和 softmax-coupled S-DPO 也不是一回事

这会逼着 Story Lab 再补一列:

ranking-gradient density

因为这里真正被改写的,是 chosen 对整组 negatives 的梯度组织方式,而不只是训练样本条数。

Figure 2 / Figure 3 说明它补的还是一条 knowledge-retention 边界

这篇 paper 还有一个很值得长期记住的地方:

S-DPO 并没有把更强 ranking signal 写成零成本增强

Figure 2(b)Figure 2(c) 明确给出两层信号:

  1. S-DPO 的 validation loss 相比 DPO 下降更快、更明显
  2. preferred items 的 reward 上升更稳定,也更持续

Figure 3 又补出另外一个边界:

  1. negative samples 从 1 -> 3 -> 5 -> 8 -> 10 -> 15 增加时,性能继续提升
  2. beta 太小会让 preference signal 压过 SFT 阶段学到的语言知识,导致 Hit RatioValid Ratio 一起掉
  3. beta 太大又会让 ranking relationship 学不进去

因此这条线其实还补出了另一个此前没单独命名的 tension:

ranking signal vs language-ability retention

不过和 SIDReasoner 那种通用能力大幅坍塌不同,S-DPO 这里的边界更近:

ranking-gradient density 变大之后,怎样不把 SFT 阶段留下来的 instruction validity 冲掉

这也让 ValidRatio 这列在推荐里的意义更明确了:

它不只是格式正确率,而是在衡量 recommendation-specific objective 改写语言模型时,模型还有没有保住可用输出接口。

它的理论桥很关键:DPO -> BPRS-DPO -> sampled softmax

我觉得这篇 paper 最该进长期 memory 的,不只是性能数字,而是它给推荐系统一个很清楚的 objective map:

  1. pairwise DPO 可以和 BPR 对照理解
  2. S-DPO 可以和 sampled softmax / contrastive ranking loss 对照理解

这会把 Story Lab 里此前偏 LLM alignment 的叙事,重新接回推荐系统自己的方法系谱。

换句话说,S-DPO 的价值不只是“推荐里也能用 DPO”,而是:

它把 LLM alignment loss 重新翻译回 recsys-native ranking loss

这意味着后续方法表里除了问:

  1. 谁来造 pair
  2. 谁来供给 negatives
  3. 哪条 value axis 在被对齐
  4. 环境混杂会不会被放大

还得继续问:

这条损失最终更像 recommendation 里的哪一种 native objective

否则 DPO4Rec / S-DPO / RosePO / CausalDPO 这些方法虽然都叫 DPO,对系统意义却还是会被写得过于扁平。

公开边界要写准:repo 已强于 paper-first,但还不是低门槛复现栈

这条线的公开边界明显强于只给 paper 的方法。

GitHub API 能稳定核到:

  1. 官方仓 chenyuxin1999/S-DPO 创建于 2024-05-21 12:38:56 UTC
  2. 最近一次 push 是 2024-11-29 13:06:16 UTC
  3. 仓库 size = 9287
  4. 根目录已公开 sft.pydpo.pysoftmax_dpo.pytrainer/sample_data/Prompt.py*.sh
  5. README 明确给出 SFT -> DPO -> S-DPO -> inference 四步入口
  6. sample_data/ 下还能直接核到 lastfm-sft-cans20lastfm_data.pyprepare_sft_data.py

这说明它已经不是 placeholder,而是:

workflow code + sample data

但边界也不能写过头。

我继续核 raw README、softmax_dpo.shsoftmax_dpo.py 后确认:

  1. softmax_dpo.sh 仍保留 base_model_path / ref_model_ckpt_path / paompt_path / save_path 这类占位
  2. softmax_dpo.py 把训练数据直接硬编码成 ../data/lastfm-sft-cans20/lastfm-train.json
  3. 当前公开脚本明显更偏 LastFM 单样例,而不是完整三库低门槛复现

所以更准确的定位是:

paper + official workflow code with sample data / thin docs

而不是 turnkey reproduction。

证据与来源

  • 一手论文入口:S-DPO arXiv 摘要页arXiv HTMLNeurIPS 2024 PosterNeurIPS 2024 官方 PDF
  • 时间与公开发表:NeurIPS 官方 poster 页显示它是 2024 Poster,官方 proceedings PDF 明确标注 38th Conference on Neural Information Processing Systems (NeurIPS 2024)
  • 关键机制:摘要、Section 3.1 与附录 A.2 直接写出 pairwise DPO -> partial-ranking Plackett-Luce -> softmax loss bridge
  • 关键结果:Table 1 的三库主结果,Table 2DPO-1 / DPO-K / S-DPO-K 对比,Figure 2 的 validation loss 与 preferred-item reward 变化,Figure 3 的 negative sample number 与 beta 敏感性
  • 公开仓入口:chenyuxin1999/S-DPO;GitHub API 可核到创建时间、最近 push 时间、根目录结构、sample_data/ 内容与 README 的 quick start
  • 中文传播层:截至 2026-03-25,继续补做论文全标题中文检索、S-DPO 推荐 中文site:zhihu.comsite:weixin.qq.comsite:xiaohongshu.comxhslink 检索后,稳定结果仍主要停留在 arXiv、NeurIPS、GitHub 与聚合页,没有拿到稳定高价值中文机制稿或可复用小红书线索

下一步

  • S-DPO / DPO4Rec / DRPO / SPRec / RosePO / CausalDPO / RW / D3 压到同一张 DPO / preference alignment 观察表里,新增 comparison unit / negative coupling geometry / ranking-gradient density / objective bridge / pairwise decomposition tax
  • 把这条线和 SPRec 明确拆开:前者解决“多个 negatives 在 loss 里怎样耦合”,后者解决“rejected 到底由谁供给”
  • 继续追中文传播层;如果后续出现稳定的作者解读、课程材料、讲义或 xhslink,再补一轮传播观察