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 表现相同),所以该量级附近的任何上限作为默认值都可以。