[RLHF] DAPO/CISPO/FIPO 的 loss 在梯度累积下被额外除以 gradient_accumulation_steps
Author: yhb643Created Sep 12, 2026Updated Sep 14, 2026
Checklist / 检查清单
- I have searched existing issues, and this is a new bug report. / 我已经搜索过现有的 issues,确认这是一个新的 bug report。
Bug Description / Bug 描述
loss_type 为 dapo(cispo/fipo 同样受影响)时,策略 loss 已按整个梯度累积窗口的 completion token 数归一化:
normalizer = grpo_batch.num_items_in_batch / self.accelerator.num_processes
loss = (per_token_loss * completion_mask).sum() / normalizernum_items_in_batch 由 ga_batch_encoded_inputs 汇总(swift/rlhf_trainers/grpo_trainer.py:803-809),覆盖所有 micro-batch × 所有进程,所以单个 micro-batch 只是全局 token 均值的一部分。
但 transformers.Trainer.training_step 会在 backward 前再除以 current_gradient_accumulation_steps(Accelerator 的 num_steps 被强制为 1,没有二次缩放),于是 loss 和梯度都被额外缩小 G 倍:期望梯度 g,gradient_accumulation_steps=4 时实际只有 g/4。
影响:DAPO 的有效学习率随 gradient_accumulation_steps 变化(G 越大更新越弱),日志里的 loss 也被除以 G。
How to Reproduce / 如何复现
环境:ms-swift main @ 0673cf75、transformers 5.12.1、DeepSpeed ZeRO-3
- 用
--loss_type dapo --gradient_accumulation_steps 4起 GRPO 训练; - 在
_compute_loss_and_metrics打印同一个 micro-batch 的 loss; - 参数更新量约为
gradient_accumulation_steps=1时的 1/4。
最小验证:
loss = torch.tensor(2.0, requires_grad=True)
(loss / 4).backward() # 复现 Trainer 的行为:梯度只有目标值的 1/4Additional Information / 补充信息
- 相关位置:
swift/rlhf_trainers/grpo_trainer.py:1131-1134(归一化分支);transformersTrainer.training_step - 修复 PR:#10116(补偿
current_gradient_accumulation_steps,附单测,21 passed) grpo/sapo/bnpo/dr_grpo是按 micro-batch 取均值的,不受影响
Source: modelscope/ms-swift