跳转至

CISPO

CISPO(Chen et al., 2024;Khatri et al., 2024)是策略梯度的一种变体。它对重要性比率限幅,再将结果作为策略梯度的系数。因此,限幅只约束权重,不会像 PPO 截断目标函数那样,将某个 token 的梯度置零。

目标函数:

[ \mathcal{L}{\text{CISPO}}(\theta) = \mathbb{E}\right)\right) \cdot \log p_\theta(x) \cdot A(x)\right] ]}\left[\mathbf{sg}!\left(\text{clip}\left(\frac{p_\theta(x)}{q(x)},\, 1-\epsilon_{\text{low}},\, 1+\epsilon_{\text{high}

其中 (\mathbf{sg}) 表示停止梯度传播(stop-gradient):限幅后的比率会从计算图中分离,不对这个系数求导。

等价代码:

prob_ratio = torch.exp(target_logprobs - sampling_logprobs)
clipped_ratio = torch.clamp(prob_ratio, clip_low_threshold, clip_high_threshold)
cispo_objective = clipped_ratio.detach() * target_logprobs * advantages
loss = -cispo_objective.sum()

Inputs

  • target_tokens: array[(N,), int] —— 由 (q) 采样的 token ID。
  • logprobs: array[(N,), float] —— sampling_logprobs。
  • advantages: array[(N,), float] —— 逐 token 的 advantage。

Outputs

  • logprobs —— target_logprobs。

Diagnostics

  • loss:sum —— CISPO 损失总和。

如何选择截断范围

限幅后的比率作为不参与求导的系数,对 (\log p_\theta) 加权。由于它没有像 PPO 那样直接截断目标函数,上下界的作用也不同,尤其需要注意下界。

默认只设置上界。 Mint Recursive 的 clip_low_threshold 为 0.0,上界 clip_high_threshold=4.0。不传配置时也会使用这组值;也可以显式设置:

fb = training_client.forward_backward(
    data=data,
    loss_fn="cispo",
    loss_fn_config={"clip_low_threshold": 0.0, "clip_high_threshold": 4.0},
)
result = fb.result()

不设下界时,系数可以衰减到普通的重要性采样权重,保持原有的稳定性。设置正下界(例如 0.8)后,即使某个 token 的比率已远低于 1,权重也无法继续减小。对于采样器已经偏离的旧 token,这会消除离策略训练所需的自然衰减。同策略训练通常不受明显影响;离策略训练时(例如异步训练中,(q) 落后于 (p_\theta)),正下界可能形成反馈循环:采样器与训练器之间的 KL 增大,更多 token 的比率落到区间外,偏差随之增大,KL 继续上升。

这与两篇源论文的做法一致。MiniMax-M1 关闭了下侧 IS 界限、只调上限;ScaleRL 发现 CISPO 对上限几乎不敏感(4、5、8 表现相同),所以该量级附近的任何上限作为默认值都可以。