[讨论] torch rollout 下 GRPO/CISPO 的 importance ratio 恒等于 1,clip 分支从不生效 #848
a0917-cell
started this conversation in
Ideas
Replies: 1 comment
|
sglang 路径上 ratio ≠ 1 还有一个和 rollout 用 和你写的 dropout 那条是同一类:clip 触发的理由是 temperature,不是策略位移,同一个 另外,方向 2 可以直接引 DeepSeekMath 原文的 GRPO 训练设置:"The policy model only has a single update following each exploration stage." torch 默认路径就是论文本身的设定。 |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
读
trainer/train_grpo.py时发现的一个现象,先说结论:在默认的--rollout_engine torch路径下,importance ratio 位元级恒等于 1,所以 PPO clip 与 CISPO 的 clamp 都不会生效,--loss_type这个开关也没有任何作用。 实际优化的目标等价于带 KL 惩罚的 REINFORCE。这不是 bug(数学上仍然是正确的 on-policy 更新),但它和代码读起来的样子不一样,对照着学 GRPO/CISPO 的人容易误以为自己看到的 clip 在起作用,所以想提出来讨论一下。
为什么恒等于 1
TorchRolloutEngine.rollout()里的old_per_token_logps是用当前这组权重、在同一次调用中算出来的(compute_per_token_logps(self.policy_model, ...)),而optimizer.step()发生在之后。所以到ratio = torch.exp(per_token_logps - old_per_token_logps)这一行时,分子分母来自同一组权重、同一段输入。--accumulation_steps也不改变这一点:权重只在 step 边界更新,而old_logps是每个 batch 重新算的,窗口内两者始终同步。rollout_engine.update_policy(model)对 torch 引擎而言只是把同一个对象重新绑定一次。实测
RTX A2000 12GB,bf16 autocast,
num_generations=6、max_new_tokens=32,走仓库自己的TorchRolloutEngine:MiniMindConfig默认dropout=0.0,所以默认就是第一行:不是「近似为 1」,是差值精确为 0。第二行更值得注意:
dropout>0确实能让 ratio 散开,但散开的原因是两次 forward 抽到了不同的 dropout mask,而不是策略发生了位移。此时 clip 在 75.5% 的 token 上被触发,触发的理由却是噪声——这比恒等于 1 更容易误导。三种 loss 的梯度是同一个
把
train_grpo.py里两个分支照抄出来,在 ratio ≡ 1 的前提下比较对per_token_logps的梯度:CISPO 相对 GRPO 的核心差别,是对 ratio 很大的 token 保留梯度而不是把它裁成 0;ratio 恒为 1 时这个差别无从体现。
对照:
train_ppo.py里 clip 是真的在工作同一个仓库里 PPO 那支有
--ppo_update_iters外加 minibatch 内循环,第一个 minibatch 更新之后权重就和old_resp_logp分离了,所以 clip 与clipfrac都有意义——代码里甚至已经有--debug_log_ratio专门盯这个量。GRPO 这支缺的正是这个内循环开关。--rollout_engine sglang是另一种情况:权重要靠update_policy()落盘再让 SGLang 重载,而这个调用只在step % save_interval == 0(默认 10)时发生,所以那条路径上 ratio 确实不为 1,但落后的步数是被save_interval顺带决定的,不太像是有意设计的 off-policy 程度。(这一段是读代码得到的,没有实跑 SGLang。)想讨论的方向
--ppo_update_iters的内循环开关?一份 rollout 更新多次,clip 才有约束对象,也顺带提高样本利用率。--loss_type是为可扩展性保留的结构。教程性质的仓库里,这句话可能比代码本身更重要。dropout > 0与 ratio 的相互作用建议也写一句——它不会修复恒等,只会把噪声灌进 importance ratio。复现
All reactions