Chapter 11

常见错误:reference 不冻、KL 爆炸

📌 commit 8221a9fRLHF 训练里能踩的坑都在这

RLHF 训练比 SFT 难调 10 倍。本章汇总在 TRL 上踩过的高频坑,按"现象 → 原因 → 处理"分类。

11.1SFT 阶段

现象原因处理
loss 一直在 ln(vocab) 附近tokenizer EOS / pad 没对tok.pad_token = tok.eos_token
chat template 报错tokenizer 没 chat_template显式 tok.chat_template = "..." 或换支持的模型
训完模型不会 EOSassistant_only_loss 没开,EOS 在 user 部分被 mask 了开 assistant_only_loss=True
packing 后 loss 异常低不同样本之间 attention 串了padding_free=True 用 flash-attn 的 cu_seqlens
多轮对话效果差每个 assistant 都算 loss 时数据分布偏向短回复只对最后一轮算或加 length normalize

11.2DPO / KTO / IPO 阶段

现象原因处理
训完模型乱码lr 太大;DPO 应 1e-6 / LoRA 5e-6降 lr 10×
chosen / rejected reward 都涨跑偏;正常应只有 chosen 涨降 lr;查偏好数据是否搞反
训完 hardly 改变policy 离 ref 太近;beta 太大beta 从 0.1 → 0.05
训完只回答短句length bias:长 sequence log-prob 求和值大SimPO(length norm)或减 max_length
偏好准确率比训前还低偏好数据噪声 >= 30%换数据;或开 label_smoothing=0.1

11.3PPO / GRPO 阶段

现象原因处理
reward 飙升但答案质量崩典型 reward hacking加大 KL(kl_coef ×2-5);或加 reward whitening
KL 散度一直涨KL 惩罚不够kl_coef 0.05 → 0.2
policy collapse(只输出一种回答)entropy 太低加 entropy bonus(PPO 自带);或加大 KL
policy 训丢了 chat 格式没用 SFT 模型初始化;reference 不是同一个 SFTpolicy 和 ref 必须从同一 SFT ckpt 起
rollout 训完吐空字符串EOS 立刻被采样missing_eos_penalty;或调 sampling temperature
GRPO 的 advantage 全是 NaNgroup 内 reward 完全一样 (std=0)提高 sampling temperature;或换 reward fn
RM 训完后 PPO 不收敛RM 输出范围太大RM 训时开 center_rewards_coefficient

11.4显存类问题

现象处理
SFT OOMgradient_checkpointing=True;改 LoRA / QLoRA
DPO OOM(双倍)用 LoRA + ref_model=None(自动用 disable_adapter)
PPO OOM(四倍)LoRA + ref_model=None + ZeRO-3
GRPO rollout OOMvllm_gpu_memory_utilization;降 num_generations

11.5多卡 / 分布式

现象处理
accelerate 报"world_size mismatch"accelerate config 设的 num_processes 跟 --nproc_per_node 不一致
DeepSpeed ZeRO-3 + LoRA 报错需要 transformers ≥ 4.45 + peft ≥ 0.10
多机训 RM 慢RM 内部 batch 翻倍;调 gradient_accumulation
多机 GRPO vLLM 启动慢每张卡都启一个 vLLM;用 server 模式集中起一份

11.6调试技巧

开 verbose 日志

export TRANSFORMERS_VERBOSITY=info
export ACCELERATE_DEBUG_MODE=1
export TORCH_DISTRIBUTED_DEBUG=DETAIL

看 trainer 状态

trainer.train()
print(trainer.state.log_history[-5:])  # 最近 5 条 metrics

Sanity check:1-step overfit

用 1 个样本反复训 50 step,loss 应该接近 0。如果不能 overfit,说明 trainer / data / model 有 bug。

11.7实用配方(按场景)

场景建议起点
SFT 7B 单卡LoRA r=16,bf16,packing,2e-4
DPO 7B 单卡LoRA + ref_model=None,beta=0.1,5e-6
GRPO 7B 4 卡vLLM colocate,G=8,beta=0.04,1e-6
PPO 7B 8 卡LoRA,kl=0.1,cliprange=0.2,1e-6

11.8v0 → v1 升级常见坑

2026-03 发布的 TRL v1 带来一组静默默认值变更,老代码移植过来跑不出预期结果时先查这张表(完整列表见 repos/trl/MIGRATION.md):

症状真实原因修复
GRPO 训练莫名占用一组 GPU 却不出现 vLLM 进程 vllm_mode 默认从 "server" 改成 "colocate"显式写 vllm_mode="server" 多机场景
RLOO 同上 同上 同上
SFT 训练 log 出现 packing="bfd-requeue" is deprecatedv0 字符串名 改成 packing="bfd_split"(或直接 True
训练 batch 出现莫名长度 0 / Tensor None 报错 v0 自动剔除 dataset 里 None 值,v1 不剔了 预处理 dataset.map(trl.trainer.utils.remove_none_values)
导入 from trl import PPOTrainer 报警 "experimental"PPO 被挪到 trl/experimental/ppo/ 正常,可 TRL_EXPERIMENTAL_SILENCE=1 关掉警告
OnlineDPO / Nash-MD / XPO 也都报警 这几个 trainer 也在 experimental 区 同上

11.9trl env:报 issue 必贴

调试卡住时第一步:跑 trl envtrl/scripts/env.py)。它一次性吐出:

GitHub issue / discord 提问都建议直接贴它的输出 —— 比手写"我的版本是 ..."准确 100%。

11.10v1 之后日常踩的几个新坑

现象原因修复
colocate 模式启动几秒后 CUDA OOM vLLM 占的 GPU 和训练抢同一张卡 错开 CUDA_VISIBLE_DEVICES 或调小 vllm_gpu_memory_utilization
多 reward function 时 group advantage 全 0 所有 reward 在 group 内方差为 0(题目太简单 / 太难) 过滤 dataset 或加扰动
chat template 训练时 token 数对不上 generate 时 没用 *_training.jinja 训练模板 SFT/GRPO 显式 chat_template_path
DPO loss=NaN 第一步 ref / policy 完全相同(没传 ref,也没装 PEFT) 必须二选一:传 ref_model 或传 peft_config
GRPO reward function 抛异常但训练没停 函数返回 None TRL 会跳过该样本,不报错 显式 try/except 打日志

11.11这章你需要带走的