RLHF调参实战手册:实用Trick、现象排查与解决思路(持续更新)
文章目录
- 前言
- 通用原则与核心思想
- 实用Trick
- 现象排查与解决思路
前言
最近大半年的时间,我基本都泡在大模型的RLHF训练里,反复跑了很多轮实验。这个过程中,遇到了各种各样的问题和现象,光看论文理论往往不够,很多时候还是要靠实际调试来解决。我把这段时间踩过的坑、网上查到的资料以及自己摸索总结出来的一些调参思路和解决方案整理了一下。下边就分享给大家,希望能给同样在做对齐工作的朋友们提供一些有用的参考,避免重复踩坑。
当然,分享的经验不一定完全准确,欢迎大家指正。同时文章会动态更新,如果你遇到不同情况,也欢迎留言或我来添加~
通用原则与核心思想
在具体分享之前,我想有几个核心思想是通用的,这也是解决一切问题的原则。
- 奖励模型是基石: 奖励模型的质量直接决定了RLHF的天花板。如果奖励信号本身有噪声或不准确,后续的微调很难达到理想效果。在开始RLHF之前,务必保证RM在验证集上有足够好的准确性和泛化能力。
- KL散度是缰绳: 在RLHF中,我们既要让模型学习新的偏好(由奖励模型定义),又要防止它偏离预训练模型或者SFT模型太远,以免产生一些不正常的回复或遗忘通用能力。KL散度就是这根“缰绳”,控制着新旧模型策略的距离。几乎所有的RLHF算法都在优化这个带约束的目标。
- 深度学习通用经验:RLHF本质上是一个深度学习过程,因此深度学习的很多调参经验,在RLHF中也是适用的。
实用Trick
- 如果使用Base模型进行RL,kl_loss应该去掉,因为kl_loss会限制模型的exploration,而Base-RL前期的探索是非常重要的。
- 如果不是Base-RL,kl_loss系数建议加上,否则会出现各种奇奇怪怪的问题。一般设置为0.001就足够,太大会影响性能。
- 如果Base-RL的效果想要更进一步,可以试试用base-RL拒绝采样一批样本,然后对Base模型进行简单的冷启动微调,随后再继续RL。
- 复杂任务的奖励函数不要太单一,否则很容易reward hacking,对于复杂任务尽量多方面多维度进行reward计算。
- reward始终不上涨,在排除了一切可能的原因后,建议用训练前的模型针对一些case rollout出多个回复(n可以大一点),看下这些回复的奖励是不是都特别低,如果都特别低,那说明基模的能力上限就如此,想要通过探索来提升表现是行不通的,建议换模型或者对SFT模型进行优化。
- RL 阶段学习率建议使用余弦衰减,初始值设为 1e-6~1e-5,避免固定学习率导致后期优化震荡;若奖励长时间不提升,可尝试在衰减后期加入小幅度的线性升温。
- 当出现训练不稳定(如损失值突然飙升),可启用梯度裁剪。
- 关于温度系数:GRPO训练时温度系数建议直接设置为0.95或者1.0,让模型生成更加多样化的探索。
- RLHF 训练数据需覆盖不同场景(如闲聊、专业问答、指令遵循),若数据偏向单一领域(如仅闲聊),可在奖励函数中加入领域覆盖度惩罚(如计算生成内容与训练数据的领域分布 KL 散度)。
- PPO的学习率通常需要比SFT小一个数量级。例如,如果SFT阶段的学习率是2e-5,PPO阶段的初始学习率建议设置为1e-6到3e-6之间,过高的学习率极易导致模式崩溃(Mode Collapse)。
- 为防止能力遗忘,可以在RL的prompt池中混入5%-10%的通用SFT数据。这是一种简单有效的方法,可以在优化特定偏好的同时,通过让模型回顾通用任务来“锚定”其基础能力。
- 奖励模型的输出值应该做裁剪(Reward Clipping)。例如,将奖励模型的输出范围限制在[-2, 2]之间。这可以防止某些异常高的奖励信号主导梯度,从而提高训练稳定性。
- DPO对偏好数据的“偏好差距”很敏感。如果数据中大量的“chosen”和“rejected”样本质量相差无几,DPO很难学到有效信号。因此,数据清洗阶段应确保偏好对的区分度足够明显。
- PPO中的clip参数(裁剪范围)通常设为0.2即可,0.2是一个非常鲁棒的默认值。除非训练极度不稳定,否则一般不需要调整它。
- 如果价值损失(Value Loss)不下降或爆炸,可以尝试降低价值函数的学习率,或者增加其损失系数,让模型更专注于学好价值估计。
- PPO中,Critic模型的学习率通常可以设置得比Actor模型的学习率更高。 例如,Actor学习率为1e-6,Critic学习率可以设置为5e-6或1e-5。因为Critic需要更快地拟合奖励值,为Actor提供准确的Advantage估计。
- 在PPO训练前,务必对RM的输出进行归一化处理。这可以防止因奖励模型打分范围不固定而导致的梯度爆炸或消失,极大提升训练稳定性。
- RLHF阶段的batch_size宁大勿小。 更大的批次可以提供更稳定的梯度估计,尤其对于PPO。如果显存不足,应优先使用Gradient Accumulation来等效扩大批次大小。
- 在RLHF中可能经常碰到Reward Hacking,解决方案是在奖励函数中加入惩罚项,或者调低某个reward的权重系数,或者将这些作弊样本作为负例,重新训练奖励模型。
- GRPO算法比DPO更适合处理“噪声大”或“次优”的偏好数据。 如果你的数据集中,很多“chosen”样本其实质量也一般,或者与“rejected”样本区分度不大,GRPO的鲁棒性会更强。
- 在初始化PPO时,Critic模型的权重应该从SFT模型加载,而不是随机初始化。
- GRPO的一个trick是:初始阶段可以使用较小的Group Size(如8),随着策略收敛逐步增大,因为小Group Size能加速冷启动,而大Group Size适合后期精细化调整,避免局部最优。
- 模型保存:RLHF最好每隔多少个step保存一下优化器参数等,这样可以随时恢复训练,尤其是多机多卡场景下,可能更容易出现一些通信等问题导致模型训练停止。
现象排查与解决思路
- Reward持续上升,并且KL散度爆炸式增长
- 可能原因:没有进行kl penalty或者系数过低。模型为了追求高奖励生成了与原始模型风格迥异但能“骗过”奖励模型的内容。
- 解决方案:增加KL惩罚项的权重,通常建议从一个较小的值(如0.001)开始,逐步增加。
- KL散度很低,奖励几乎不增长或者增长缓慢
- 可能原因:KL惩罚太过了,模型被过度束缚
- 解决方案:调低系数,同时可以检查下学习率,如果学习率非常低,模型更新步子太小,可能也会导致reward增长缓慢。
- 模型训练初期就输出大量重复或者无意义的内容
- 可能原因:学习率过高。过大的学习率可能导致模型参数更新过于剧烈,跳出了有效的参数空间,导致“模式崩溃”(mode collapse)。
- 解决方案:降低学习率。对于大模型微调,学习率通常设置得非常小,例如 1e-6 到 1e-5 之间。可以从一个保守的值开始尝试。同时,使用warmup和decay策略通常是个好主意,我一般推荐cosine策略。
- 模型响应的长度变得非常短或非常长
- 可能原因:奖励模型可能存在length bias。比如,奖励模型可能无意中给更长(或更短)的回答更高的分数,导致在优化时利用了这个“漏洞”。
- 解决方案:修正奖励模型:在RM训练数据中加入不同长度的优质样本,消除长度偏见。或者在RL阶段加入长度惩罚/奖励.
- 训练过程非常不稳定,loss和reward上下剧烈波动
- 可能原因:这个感觉原因特别多,大概有这么几点:(1)batch_size太小导致梯度估计不准;(2)Reward没有进行归一化;(3)PPO Clip范围过大,策略更新步长失控。
- 解决方案:增加 batch_size:在显存允许的情况下,使用更大的 batch_size 可以让梯度更稳定。 对reward进行clipping和norm;调低clip范围,一般推荐0.2。
- 生成的文本质量在某个点后开始下降 (过拟合)
- 可能原因:训练步数过多 或 KL约束失效。模型可能在后期过度优化奖励模型,而奖励模型本身是不完美的,导致最终生成效果变差。
- 解决方案:Early Stopping,当性能开始下降时停止训练。 检查KL散度:确保KL散度在一个合理的范围,如果KL散度过大,说明模型已经偏离太远。
- reward持续上涨,但人类评估发现生成内容存在事实错误或逻辑混乱
- 可能原因:RM过拟合或偏好数据存在偏差,导致模型学习到“欺骗性策略”。
- 解决方案:根据你的具体任务,把奖励拆分多个独立维度,分别标注并加权融合。
- Critic的Value Loss波动剧烈,难以收敛
- 可能原因:reward方差过大,导致Critic难以准确估计长期价值。
- 解决方案:对reward或者advantage进行归一化
- 策略熵快速下降,生成内容同质化严重
- 可能原因:entropy_coef过低,导致策略过早收敛到局部最优,探索能力不足。
- 解决方案:增大熵系数;或者采用DAPO的Clip-Higher策略:解耦PPO的clip上下界,放宽低概率token的提升空间,缓解熵崩溃。最近也有很多论文研究这块,感兴趣的可以看看之前的一些文章。
- 模型在测试集表现优于训练集,但实际部署效果差
- 可能原因:与真实场景存在分布差异,导致过拟合(当然前提是训练正确)
- 解决方案:在SFT和RL阶段加入更多领域/风格的数据,提升模型泛化能力;使用迭代优化的策略模型生成新样本,更新RM以匹配最新策略分布
- 梯度范数爆炸,训练中断或参数失效
- 可能原因:学习率过高,导致梯度更新超出参数稳定范围;未启用梯度裁剪(Gradient Clipping),或裁剪阈值设置过大;奖励函数波动剧烈,导致策略梯度方差过大。
- 解决方案:降低学习率(如从1e-5降至5e-6),并配合小批量梯度更新。启用梯度裁剪;对奖励信号进行标准化(如减去均值、除以标准差),减少梯度方差。
- 模型对 chosen 和 rejected 的概率差增长缓慢
- 可能原因:beta 值过高。DPO中的 beta 参数扮演着类似PPO中KL散度惩罚的角色,它控制着隐式奖励模型的温度。beta 过高意味着策略更新过于保守。
- 解决方案:调低 beta。降低 beta可以让模型更大胆地学习偏好,拉开 chosen 和 rejected 的差距。
- DPO训练损失下降很快,但生成效果差,甚至不如SFT模型
- 可能原因:beta 值过低 或 学习率过高。beta 过低导致模型过于激进,偏离SFT模型太远,丢失了通用能力。学习率过高同样会破坏预训练模型的结构。
- 解决方案:调高 beta:增加对SFT模型的约束。 降低学习率:使用更小的学习率(如 1e-7 到 5e-6)进行微调。
未完待续,欢迎各位评论区留言补充~