资讯详情

大模型后训练实战:SFT、PPO、GRPO与Reference锚点博弈

📅 2026/11/2 7:34:55 | 华诺云谱 👁 阅读
大模型后训练实战:SFT、PPO、GRPO与Reference锚点博弈
大模型后训练这条线我从去年开始断断续续跟了不少项目从最早只会照着开源脚本跑SFT到后来自己动手改PPO的采样逻辑再到现在GRPO几乎成了默认选项中间踩的坑比想象中多得多。很多人以为后训练就是拿数据喂进去、调个学习率、等loss降下来这么简单但真正上手之后你会发现SFT只是入场券PPO和GRPO才是决定模型最终性格的关键环节而Reference模型这个看似不起眼的锚点往往才是整个训练能不能稳住的命门。这篇内容我打算把SFT的机制、PPO到GRPO的演进逻辑、以及Reference锚点在整个博弈中的角色串起来讲清楚适合已经跑过至少一次后训练流程、想搞明白为什么这么设计的读者也适合正准备从SFT往RLHF方向深入的朋友。1. SFT不是教模型说话而是给它划定输出分布1.1 从next token prediction说起SFT到底在优化什么SFTSupervised Fine-Tuning表面上看就是拿一批问题-答案对继续做自回归的next token prediction。但这里有个容易被忽略的点预训练阶段模型学的是整个互联网文本的分布而SFT阶段你喂进去的数据是经过筛选的、带有明确格式和风格偏好的样本。这两者的分布差异决定了SFT本质上是在做一次分布收窄。我习惯用一个类比来解释预训练像是让一个人读遍了图书馆所有的书他什么话题都能聊但聊天方式五花八门SFT则是给他看几千条标准客服对话记录让他学会在特定场景下用特定方式回应。模型并没有忘记预训练的知识但它输出的概率分布被重新加权了——那些符合SFT数据风格的token序列概率被抬高不符合的被压低。从损失函数角度看SFT的loss就是标准的交叉熵L_SFT -Σ log P(y_t | x, y_t; θ)其中x是输入prompty是目标回答θ是模型参数。这个loss只关心目标回答的每个token概率够不够高并不关心其他可能的回答。这就带来一个直接后果SFT只会告诉模型什么是好的但不会告诉它什么是差的。模型学到的是模仿而不是偏好排序。1.2 数据质量比数据数量重要十倍我做过一个对比实验用5万条精心筛选的高质量SFT数据和用20万条混杂了各种噪声的数据在同一个base模型上跑。结果5万条那组的最终表现明显更好尤其是在指令遵循和格式稳定性上。原因很简单——SFT阶段模型是在模仿数据你喂进去的噪声会被它当成应该模仿的模式。具体来说SFT数据要关注三个维度格式一致性如果你的数据里有的回答用markdown、有的用纯文本、有的带emoji模型会学到这种混乱。我一般会统一成一种格式比如全部用简洁的纯文本加必要的分段。长度分布如果SFT数据里回答长度差异极大有的10个字、有的2000字模型会难以判断什么时候该长、什么时候该短。建议按任务类型分层每层的长度分布尽量集中。拒绝样本的处理有些团队会把模型不该说的话也放进SFT数据里期望模型学会不要这么说。但SFT的机制决定了它只会模仿你放进去的负面样本反而可能被学到。负面约束应该交给后面的RL阶段。提示SFT阶段不要试图教模型不要做什么这个阶段只负责建立基础输出分布。偏好对齐和安全性约束留给PPO/GRPO阶段处理。1.3 SFT的收敛判断loss降了不代表模型变好了这是新手最容易踩的坑。SFT的loss是交叉熵它降下去只说明模型对训练数据的拟合程度提高了但不代表泛化能力在提升。我见过太多人盯着loss曲线降到0.3以下就停结果模型在验证集上表现一塌糊涂。我的做法是在训练过程中定期用一组固定的验证prompt做生成测试人工或用一个轻量评分模型评估输出质量。具体操作是每跑500步就抽10条验证prompt让模型生成回答记录格式正确率指令遵循率回答完整率三个指标。当这三个指标连续两次评估都不再提升时就可以考虑停了而不是等loss降到某个值。另外SFT的学习率通常要比预训练小一到两个数量级。我用过的配置里全量微调一般在1e-5到2e-5之间LoRA的话可以到1e-4到3e-4。学习率太大会导致模型忘掉预训练知识表现为通用能力下降太小则收敛太慢而且容易过拟合到SFT数据的表面模式上。2. PPO在大模型后训练里的真实工作方式2.1 PPO的核心组件Actor、Critic、Reward、ReferencePPOProximal Policy Optimization在大模型场景下其实是一个四模型协同的系统组件角色是否更新参数Actor当前策略模型负责生成回答是Critic价值模型估计当前状态的期望回报是Reward奖励模型给完整回答打分否Reference参考模型通常是SFT后的模型否Actor就是我们要训练的主模型。Critic是一个和Actor同架构但输出标量的模型它负责估计在当前prompt下按照当前策略生成回答预期能拿到多少奖励。Reward模型是提前训练好的输入prompt和回答输出一个标量分数。Reference模型则是SFT结束时的那个模型副本它的作用是提供一个锚点防止Actor在追求高奖励的过程中跑偏太远。这四个模型的关系可以这样理解Actor是学生Critic是学生的自我评估能力Reward是老师给的分数Reference是你原来是什么样的基准线。学生想拿高分Reward但也不能变得和原来的自己完全不一样Reference约束同时还要通过Critic来估计我这么做大概能拿多少分。2.2 PPO的损失函数拆解每个项都在干什么PPO的完整损失函数包含几个部分我把它拆开讲L_PPO L_policy - c1 * L_value c2 * L_entropy其中L_policy是策略损失用的是clipped surrogate objectiveL_policy E[min(r_t * A_t, clip(r_t, 1-ε, 1ε) * A_t)]这里r_t是重要性采样比率即新策略下这个动作的概率除以旧策略下这个动作的概率。A_t是优势函数由Critic估计的value和实际拿到的reward计算得出。clip操作是PPO的核心它限制了每次更新时策略变化的幅度防止一步走太大导致训练崩溃。L_value是Critic的损失就是让Critic估计的value尽量接近实际回报。L_entropy是熵正则项鼓励策略保持一定的探索性防止过早收敛到局部最优。在大模型场景下还有一个关键的KL惩罚项通常写成L_KL β * KL(π_actor || π_ref)这个项直接约束Actor的输出分布不能偏离Reference太远。β是KL系数控制约束的强度。我实测下来β在0.01到0.1之间比较常见具体值要看任务对偏离容忍度的要求。2.3 PPO训练中的四个典型不稳定信号PPO在大模型上训练最容易出现的问题不是不收敛而是不稳定。我总结过四个典型信号KL散度突然飙升说明Actor在某一步更新后偏离Reference太远通常是学习率太大或β太小。我的处理方式是先降低学习率如果还不行就增大β。Reward分数先升后崩这是典型的reward hacking——模型找到了奖励模型的漏洞拿到了高分但实际输出质量很差。解决办法是定期用人工评估校准或者引入多个奖励模型做ensemble。Critic loss不降反升说明Critic跟不上Actor的变化。可以尝试单独给Critic更大的学习率或者增加Critic的更新次数。生成长度异常变化如果模型突然开始生成超长或超短的回答通常是奖励模型对长度的偏好被过度放大了。需要在奖励模型训练阶段就做好长度归一化。注意PPO对超参数非常敏感同一套参数在不同base模型上可能表现完全不同。建议在正式训练前先用小规模数据跑一轮sanity check确认KL散度和Reward曲线都在合理范围内。3. GRPO为什么能取代PPO成为新默认3.1 GRPO的核心改动去掉Critic用组内相对优势GRPOGroup Relative Policy Optimization最直观的变化就是把Critic拿掉了。它不再需要一个单独的价值模型来估计baseline而是对同一个prompt生成一组比如8个或16个回答然后用这组回答的奖励均值作为baseline计算每个回答的相对优势A_i (r_i - mean(r_group)) / std(r_group)这个改动看起来简单但影响很大。首先省掉了一个和Actor同规模的Critic模型显存占用直接降了将近一半。其次Critic本身是一个很难训练的东西——它需要准确估计当前策略下预期能拿多少分但在大模型的高维输出空间里这个估计往往不准反而会给策略更新引入噪声。GRPO用组内实际奖励的均值来代替Critic的估计虽然方差可能大一些但至少是无偏的。我用一个具体例子来说明假设同一个promptGRPO生成8个回答奖励分别是[0.8, 0.6, 0.9, 0.3, 0.7, 0.5, 0.85, 0.4]。均值是0.631标准差约0.21。那么第一个回答的优势就是(0.8-0.631)/0.21≈0.80第四个回答的优势是(0.3-0.631)/0.21≈-1.58。这意味着第四个回答会被明显抑制而第一个会被鼓励。3.2 GRPO的显存账为什么小团队更愿意用它我拿7B模型做过对比测试同样是batch size 64、生成长度512的场景项目PPOGRPOActor参数7B7BCritic参数7B无Reference参数7B7BReward模型单独部署单独部署训练显存估算约4倍模型大小约2.5倍模型大小PPO需要同时加载Actor、Critic、Reference三个7B模型再加上优化器状态和梯度显存压力非常大。GRPO去掉了Critic显存直接省了四分之一到三分之一。对于只有单机8卡的小团队来说这个差距直接决定了能不能跑起来。但GRPO也不是没有代价。它需要对同一个prompt生成多个回答这意味着采样成本更高。如果组大小是8那每个prompt要生成8次推理开销是PPO的8倍PPO通常每个prompt只生成1次。所以GRPO省的是显存费的是时间。实际选择时如果你的瓶颈是显存选GRPO如果瓶颈是采样速度PPO可能更合适。3.3 GRPO的组大小怎么选不是越大越好组大小group size是GRPO最关键的参数之一。理论上组越大baseline估计越准优势计算的方差越小。但实际中我发现组大小超过16之后收益就非常边际了。我做过一组对比组大小分别设为4、8、16、32在同一个任务上跑。组大小4的时候训练波动明显优势估计噪声大8的时候已经比较稳定16的时候和8差别不大32的时候训练时间翻倍但效果没有提升。所以我的建议是默认用8如果训练不稳定再考虑加到16。另外组内的回答要有足够的多样性。如果模型对某个prompt的所有回答都差不多比如都是同一个模板那组内方差会很小优势计算就会变成矮子里拔将军噪声被放大。解决办法是在采样时适当提高temperature或者用top-p采样来增加多样性。4. Reference锚点整个后训练博弈的隐形裁判4.1 Reference模型到底在约束什么Reference模型在后训练里的角色很多人理解成防止模型变傻但这个说法太模糊了。准确地说Reference约束的是输出分布的KL散度也就是Actor在每个token上的概率分布不能偏离Reference太远。为什么要有这个约束因为奖励模型只是一个近似它不可能完美反映什么是真正好的回答。如果完全放开让Actor去最大化奖励它一定会找到奖励模型的漏洞生成一些奖励模型打高分但人类看了摇头的内容。Reference的作用就是拉住Actor让它不要为了奖励而彻底放弃原来学到的语言能力和知识。从数学上看加入KL约束后的优化目标变成max E[r(x, y)] - β * KL(π_actor(y|x) || π_ref(y|x))这个式子的含义是既要拿高奖励又不能偏离Reference太远。β就是这两者之间的权衡系数。β越大模型越保守越接近SFT后的状态β越小模型越激进越容易拿到高奖励但也越容易跑偏。4.2 β的调节从固定值到自适应早期我用的都是固定β比如0.04或者0.1。但固定β有个问题训练初期Actor和Reference差别不大KL自然很小这时候β可以小一点让模型多探索训练后期Actor已经偏离了不少KL变大这时候需要更大的β来拉住它。后来我改用自适应β设定一个目标KL值比如0.01如果当前KL低于目标就减小β如果高于目标就增大β。具体实现上可以用一个简单的比例控制器if KL_current 1.5 * KL_target: β * 1.5 elif KL_current 0.5 * KL_target: β * 0.7这个逻辑我实测下来比固定β稳定很多尤其是在训练步数超过1000步之后固定β的模型往往会出现KL持续上升最终崩溃的情况而自适应β能把KL控制在一个合理区间内。4.3 Reference模型的选择SFT checkpoint还是base模型这是一个容易被忽略但影响很大的决策。Reference模型通常用SFT结束时的checkpoint但也有一些团队尝试用base模型或者SFT过程中的某个中间checkpoint。我的经验是Reference用SFT最终checkpoint是最稳妥的。原因有两个第一SFT checkpoint已经具备了基本的指令遵循能力用它做锚点Actor不会退回到只会续写的状态第二SFT checkpoint的输出分布和后续RL阶段的任务分布更接近KL约束更有意义。如果用base模型做ReferenceKL约束会变得很奇怪——base模型的输出分布和RL阶段期望的输出分布差异太大导致KL一开始就很高β需要设得很小才能让训练进行下去但β太小又失去了约束的意义。我试过一次用base做Reference结果模型在训练早期就出现了严重的格式崩溃后来换回SFT checkpoint才恢复正常。4.4 Reference锚点的博弈本质奖励与约束的拉锯把整个后训练过程看作一场博弈的话Actor是在奖励和Reference约束之间找平衡。奖励模型说你往这个方向走能拿高分Reference说你不能离我太远。β就是这场博弈的裁判它决定了Actor能走多远。这个博弈有一个很有意思的性质奖励模型越不准Reference约束就应该越强。因为奖励模型不准的时候Actor找到的高分路径很可能是错的这时候需要Reference把它拉回来。反过来如果奖励模型非常准比如用大量人工标注数据训练的那β可以小一点让模型更自由地探索。实际中奖励模型的准确率很难做到很高所以我一般会把β设在0.02到0.08之间偏向保守。如果发现训练过程中Reward涨得很快但人工评估没提升那就是奖励模型被hack了需要增大β或者重新训练奖励模型。5. 从PPO到GRPO的迁移实操我踩过的坑5.1 迁移第一步把Critic的代码路径彻底摘干净从PPO迁移到GRPO最直接的操作是去掉Critic相关的代码。但这里有个坑很多开源PPO实现里Critic和Actor是共享底层参数的比如共享embedding层去掉Critic的时候如果不小心会把共享参数也一起改掉。我的做法是先把Critic相关的所有代码路径标记出来包括模型定义、forward逻辑、loss计算、优化器配置然后逐一确认哪些是Critic独有的、哪些是共享的。共享的部分保留独有的部分删除。删完之后跑一次forward确认Actor的输出shape和PPO时一致。5.2 组内采样的实现细节batch维度怎么排GRPO需要对同一个prompt生成多个回答这就涉及到batch的组织方式。我见过两种实现方式A把prompt重复group_size次然后作为一个大batch送进模型生成。这样生成的回答在batch维度上是连续的同一个prompt的回答排在一起。方式B每个prompt单独生成group_size次然后拼起来。方式A实现简单但要注意生成时的attention mask要正确处理否则同一个prompt的多个回答会互相attend。方式B更灵活但代码复杂度高一些。我一般用方式A因为大多数推理框架对batch生成的支持更好。5.3 奖励归一化的坑组内标准化不是万能的GRPO的优势计算用了组内标准化这要求组内奖励有足够的方差。如果组内所有回答的奖励都差不多比如奖励模型对所有回答都打0.7分那标准化之后优势会变成随机噪声。我遇到过一次这种情况奖励模型在某个任务上区分度很低导致组内奖励几乎一样训练完全没效果。解决办法是在奖励模型训练阶段就确保它有足够的区分度或者在GRPO阶段引入额外的奖励信号比如长度惩罚、格式奖励来增加方差。5.4 从PPO到GRPO哪些超参数需要重新调迁移到GRPO后有几个超参数需要重新调整超参数PPO典型值GRPO典型值调整原因学习率1e-6~5e-61e-6~3e-6GRPO梯度方差更大学习率要更保守KL系数β0.01~0.10.02~0.1没有Critic后KL约束更重要组大小不适用8~16需要足够样本估计baseline采样temperature0.7~1.00.8~1.2需要更多样本来增加组内方差PPO clip ε0.1~0.30.1~0.2GRPO对策略变化更敏感这些值不是绝对的但可以作为起点。我一般会先用小规模数据跑100步左右观察KL曲线和Reward曲线再决定是否调整。6. 后训练全流程的工程化建议6.1 数据管线的设计SFT和RL的数据要分开管理SFT数据和RL数据prompt集合最好分开管理因为它们的用途完全不同。SFT数据是问题-答案对RL数据只需要prompt答案由模型自己生成。我见过一些团队把两者混在一起结果在RL阶段不小心把SFT的答案也喂进去了导致模型直接抄答案训练完全失效。我的做法是建立两个独立的数据集SFT数据集包含完整的prompt-response对RL数据集只包含prompt。两个数据集可以有重叠的prompt但RL数据集绝对不能包含response。6.2 训练监控除了loss还要看什么后训练的监控指标比预训练多得多。除了常规的loss我还会重点看这几个KL散度曲线应该在一个合理区间内波动持续上升或突然飙升都是危险信号。Reward均值曲线应该缓慢上升如果上升太快可能是reward hacking如果不动可能是奖励模型区分度不够。生成长度分布应该保持稳定突然变长或变短都说明模型行为异常。验证集人工评分每500步抽一批验证prompt人工打分这是最可靠的指标。6.3 模型保存策略不要只保存最后一个checkpoint后训练过程中模型的表现会有波动。有时候中间某个checkpoint比最后一个更好。我一般会每200步保存一次然后在训练结束后用验证集评估所有checkpoint选最好的那个。保存时要注意同时保存Actor和Reference的状态方便后续复现。另外如果训练过程中出现了KL飙升或Reward崩溃不要直接停掉先回滚到上一个稳定checkpoint调整超参数后继续。我遇到过好几次这种情况回滚之后换个学习率就恢复正常了。6.4 小团队的后训练资源规划如果你只有单机8卡比如8张A100 80G我的建议是7B模型SFT用全量微调或LoRA都可以RL阶段用GRPO组大小8生成长度控制在512以内。13B模型SFT建议用LoRARL阶段用GRPO组大小4到8可能需要梯度检查点来省显存。70B模型单机8卡基本跑不动全量RL建议用LoRA或者考虑多机方案。采样速度是另一个瓶颈。GRPO每个prompt要生成8个回答如果推理框架不够快训练时间会非常长。我一般会用vLLM或者类似的推理加速框架来做生成比直接用HuggingFace的generate快好几倍。7. 一些反直觉的观察7.1 SFT做得太好反而可能限制RL的效果这个观察可能有点反直觉如果SFT阶段模型已经拟合得非常好了RL阶段的提升空间反而会变小。原因是SFT已经把输出分布收得很窄了RL阶段需要在保持这个分布的同时做微调空间有限。我试过用不同SFT程度的模型做RL对比发现SFT loss降到0.5左右的模型RL后的最终表现反而比SFT loss降到0.2的模型更好。我的解释是SFT loss太低意味着模型对SFT数据的拟合过度了输出多样性下降RL阶段很难探索到新的、更好的输出模式。所以SFT阶段不要追求极致低的loss留一点空间给RL。7.2 Reference不是越强越好Reference模型的质量当然重要但太强的Reference也可能有问题。如果Reference本身已经是一个很好的模型那KL约束会非常强Actor很难做出有意义的改变。我试过用一个经过多轮SFT的强模型做Reference结果RL阶段几乎没什么提升因为Actor稍微偏离一点KL就很大β被迫设得很小约束形同虚设。所以Reference的选择要匹配它应该是一个还不错但还有提升空间的模型而不是已经很好的模型。SFT刚结束的checkpoint通常就是这个状态。7.3 GRPO的组内标准化在极端情况下会失效前面提到过组内奖励方差小的问题但还有一个更极端的情况如果组内某个回答的奖励远高于其他比如一个0.95其他都是0.3标准化之后那个高奖励回答的优势会非常大导致模型过度拟合到这个特定回答上。我遇到过这种情况模型开始对所有prompt都生成类似那个高奖励回答的内容多样性急剧下降。解决办法是给优势加一个clip比如限制在[-3, 3]之间防止极端值主导更新。这个技巧在PPO里也有但在GRPO里更重要因为没有Critic来平滑。7.4 后训练的收益递减比想象中来得快很多人以为后训练可以无限提升模型表现但实际上收益递减来得很快。我做过一组实验同一个base模型分别做1轮、2轮、3轮RL训练。1轮到2轮有提升2轮到3轮提升就很小了3轮之后基本不动甚至下降。原因是模型已经找到了奖励模型的高分区域继续训练只是在那个区域里微调没有新的探索。所以我的建议是RL训练不要超过2轮把精力放在数据质量和奖励模型上。与其反复跑RL不如重新审视SFT数据和奖励模型的标注质量。8. 关于Reference锚点博弈的一点个人体会把整个后训练流程走通之后我最大的体会是Reference锚点的设计比PPO还是GRPO的选择更重要。算法层面的改进比如GRPO去掉Critic确实能降低工程门槛但真正决定模型最终表现的是Reference和奖励模型之间的平衡。我见过太多团队在算法细节上花了很多时间却忽略了Reference模型的选择和β的调节结果训练出来的模型要么太保守和SFT差不多要么太激进reward hacking严重。我的经验是在正式训练前先做一轮小规模实验固定其他参数只调β观察不同β下的KL曲线和Reward曲线找到一个Reward在涨但KL没有失控的区间然后再开始正式训练。另外Reference模型不是一成不变的。有些团队会在训练过程中定期更新Reference比如每500步把当前Actor复制成新的Reference这样可以防止KL约束随着训练逐渐失效。我试过这种做法效果确实比固定Reference好但实现复杂度高一些需要仔细处理优化器状态和模型权重的同步。最后说一个实操中的小技巧在GRPO训练时我会把组内奖励的均值和标准差也记录下来如果发现某个batch的标准差特别小比如小于0.01就跳过这个batch的更新。因为这种情况下优势计算基本是噪声更新反而有害。这个过滤逻辑很简单但对训练稳定性帮助很大。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑