对比偏好训练 CPO:从对比学习视角实现对齐
FreeGuideOnline
最新
2026-06-29
L_DPO = -log σ( β * ( log(π_θ(y_w|x)/π_ref(y_w|x)) - log(π_θ(y_l|x)/π_ref(y_l|x)) ) )
这里 `β` 控制 KL 散度惩罚的强度。DPO 必须使用一个固定的参考模型来约束策略,否则目标将退化为单纯扩大 preferred 和 rejected 的差距,可能导致模型遗忘之前的知识或产生奖励欺骗 (reward hacking)。
### 3.3 CPO 损失函数设计
CPO 提出一个**仅依赖于策略模型 π_θ 自身**的损失函数,将偏好学习与表示质量统一优化:
L_CPO = -log σ( β * ( log π_θ(y_w|x) - log π_θ(y_l|x) ) ) ← 偏好优化项 + λ * L_uniform ← 均匀性正则项
接下来我们拆解这个公式的每个部分。
#### a) 偏好优化项
与 DPO 的核心差异在于:**直接使用策略模型对 chosen 和 rejected 的对数概率差,作为偏好奖励信号**,不再除以参考模型概率。这样做的直观理解是:
- 我们希望模型对 `y_w` 输出的概率远高于 `y_l`。
- 用 sigmoid 函数 σ 将这个概率差转化为偏好概率,并用交叉熵损失最大化它。
- 当两个回答的概率差距较小时,损失较大;差距足够大时,损失趋近于 0。
**优点**:没有参考模型的牵制,优化目标更干净,且模型可以从零开始学习对齐,无需预先的 SFT 步骤(虽然实践中 SFT 初始化效果更好)。
#### b) 均匀性正则项 L_uniform
如果仅优化上述偏好项,模型可能很快将所有概率质量集中在少数 token 序列上,导致生成多样性崩溃,甚至可能输出无意义的固定模式。
CPO 引入**均匀性正则项**,灵感来自对比学习中的特征均匀性目标 (Uniformity)。该正则项鼓励模型在给定提示下,对不同回答的概率分布更加平坦:
L_uniform = E_{y_i ~ p(y|x)} [ log π_θ(y_i|x) ]
即,对于从模型当前分布中采样的回答(或通过某种方式获得的额外样本),最大化其负对数似然的相反操作,实际上是最小化该均匀性损失。常见的实现是**最小化模型在额外采样回答上的对数概率的平方和,或最大化分布的熵**。论文中提出的形式为:
L_uniform = - E_{y_i ~ π_old} [ log π_θ(y_i|x) ] (实际使用时取负,作为最小化项)
结合后的效果:模型一方面被迫使 chosen 明显优于 rejected,另一方面又要保证对多种合理回答保持足够的概率覆盖率,从而**避免过拟合和模式坍塌**。
#### c) 超参数 λ 与 β
- **β**:控制偏好差距的缩放因子,类似于 DPO 中的 β,值越大,要求 chosen 与 rejected 之间的概率差距越大。
- **λ**:平衡偏好优化和均匀性正则的强度。通常 λ 较小(如 0.01 ~ 0.1),只需轻微正则化即可保持多样性。
## 4. CPO 算法步骤
**输入**:偏好数据集 D = { (x, y_w, y_l) },初始模型参数 θ(可以是预训练 LLM 或 SFT 后的模型)。
1. **采样一批数据**:从 D 中采样一个 batch。
2. **前向传播**:用策略模型 π_θ 计算给定提示 `x` 下,`y_w` 和 `y_l` 的对数概率。
3. **计算偏好损失**:根据公式计算 `L_pref`。
4. **计算均匀性正则**:对每个提示,从当前策略模型(或使用历史版本的模型)采样一个回答 `y_extra`,计算 `L_uniform`。有时直接使用 `y_w` 和 `y_l` 自身近似均匀性损失。
5. **总损失**:`L = L_pref + λ * L_uniform`。
6. **反向传播更新参数 θ**。
7. **重复**直到收敛。
**关键细节**:生成 `y_extra` 需要从模型中采样,这会带来额外计算开销。实践中可定期采样并缓存,或直接使用当前 batch 中的 chosen 和 rejected 序列来近似均匀性目标。
## 5. 与传统方法的比较:为什么 CPO 更好?
| 维度 | DPO | CPO |
|------|-----|-----|
| **依赖参考模型** | 必须,需计算 ref 概率 | 不需要 |
| **内存占用** | 需同时加载两个模型 | 仅需一个模型 |
| **训练稳定性** | 依赖参考模型避免退化 | 通过均匀性正则内在稳定 |
| **对齐性能** | 好 | 与 DPO 相当或更优 |
| **理论基础** | 隐式奖励与 KL 约束 | 对比学习框架,目标更解耦 |
| **对SFT初值的依赖** | 强依赖(ref 通常为 SFT 模型) | 弱依赖,甚至可从预训练模型开始 |
CPO 通过移除参考模型,大幅简化了训练管线,特别适合资源受限的微调场景,也为解释对齐过程提供了新的视角。
## 6. 代码实现要点 (伪代码)
虽然我们无法提供完整库,但以下 PyTorch 风格的伪代码有助于理解:
```python
def cpo_loss(pi_model, batch, beta=0.1, lam=0.05):
prompt = batch['prompt']
chosen = batch['chosen']
rejected = batch['rejected']
# 计算对数概率
logp_chosen = pi_model.log_prob(prompt, chosen)
logp_rejected = pi_model.log_prob(prompt, rejected)
# 偏好损失
logits = beta * (logp_chosen - logp_rejected)
loss_pref = -F.logsigmoid(logits).mean()
# 均匀性正则项:直接用 chosen 和 rejected 近似
# 或者从模型采样 extra 序列
logp_all = torch.cat([logp_chosen, logp_rejected], dim=0)
loss_uniform = -logp_all.mean() # 最小化负对数概率 => 最大化均匀
total_loss = loss_pref + lam * loss_uniform
return total_loss