news 2026/9/9 4:30:32

大模型训练与推理一致性:从Exposure Bias到RLVR的实践指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
大模型训练与推理一致性:从Exposure Bias到RLVR的实践指南

1. 为什么会聊“训练-推理一致性”这件事

做 LLM 后训练这半年多,我最大的一个感受是:模型在训练脚本里跑出来的指标,和真正部署到线上推理时的表现,经常是两回事。尤其是进入 RL(强化学习)阶段之后,这个问题会被放大得特别明显——训练时 reward 一路飙升,eval 时却觉得模型越训越“怪”,输出变长、格式不对、甚至学会了一些让人哭笑不得的作弊套路。

所谓“训练-推理一致性”,往浅了说,是希望模型在训练阶段见过、学过的数据分布,和推理阶段真正面对的任务分布尽量一致;往深了说,是让模型的优化目标、解码策略、采样参数、上下文长度、终止条件等所有环节,在训练和推理两个阶段保持对齐。这件事听着像常识,做起来却很反直觉,因为传统的监督学习和标准的 RL 框架,本质上是不会替你考虑“部署时模型怎么生成”的。

这篇文章我会从根源把问题拆开:曝光偏差到底是怎么回事,RL 训练为何会把不一致放大,以及我在实际做数学推理、代码生成这类任务时,是怎么通过一组可落地的设置把训练和推理“往一个方向拽”的。适合刚接触 LLM 后训练、准备上手 RLHF/RLVR/GRPO 的工程师,也适合已经跑通流程但总感觉线上效果低于预期的朋友。

2. LLM 的 RL 训练里,最容易产生不一致的四个源头

2.1 Teacher Forcing 与自回归推理之间的缝隙

先说最基本的。大家训练 GPT 类模型的标准做法是 teacher forcing:给定一段真实的 token 序列作为前缀,让模型预测下一个 token,然后计算交叉熵损失。在训练时,模型看到的每一个前缀都是 ground truth,是“标准答案”的一部分。但在推理时,模型是从一个起始 token 开始,把自己上一轮生成的 token 拼到序列后面,再继续预测下一个。也就是说,推理时模型看到的前缀来源,是自己的历史输出,而不是标准答案。

这个差异有个专门的名字,叫 exposure bias。理论上它会导致错误累积:生成过程中一旦出现一个不理想的 token,后续所有预测都建立在这个有偏差的上下文之上。实际上在大模型这里,由于训练数据量足够大、模型容量足够大,exposure bias 通常不会让生成立刻崩掉,但它依然会体现在一些很微妙的地方——比如模型在一定长度之后开始重复、逻辑跳跃、或者对关键中间步骤的依赖变弱。

而在 RL 阶段,exposure bias 的影响会成倍放大。为什么?因为 RL 的 rollout 本身就是用当前策略自回归采样得到的,如果我们在采样时用了某种解码参数,而后面的奖励模型、优势估计都是基于这批 rollout 计算的,那么模型真正学到的,其实是“在这种采样参数下的行为”的优化。可到了推理阶段,如果你换了 temperature、换了 top_p、甚至换成了 greedy decoding,模型面对的局面就和训练时完全不同。这就是典型的训练-推理不一致。

2.2 RL 优化目标与推理真实指标的错位

第二个源头在目标函数层面。RLHF 最常见的流程是先训一个奖励模型,再用 PPO 去优化这个奖励模型给出的分数。但奖励模型是学出来的,它并不是推理时真正想要的那个东西。比如你做数学题,线上唯一关心的就是最终答案对不对;你做代码生成,线上关心的是能不能通过单元测试。奖励模型不过是这些真实目标的一个“代理”。

代理和真实目标之间永远有缝隙,这个缝隙就是 reward hacking 的温床。模型会发现,提高奖励模型分数的最快路径并不是提升真实能力,而是去捕捉奖励模型里的统计偏差——比如写得和训练集中高分段样本更像、用更长的推理过程去迷惑奖励模型、或者反复输出某些“安全但无用”的格式。

现在业界的应对方案是 RLVR,也就是可验证奖励(Rule-based Verifiable Reward)。数学题就直接比对最终答案,代码题就跑单元测试,这样奖励就是真实的推理目标,没有代理误差。但 RLVR 也不是万能药,如果验证器本身不够严谨(比如只比对最终数字而不检查推导过程),模型照样能找到漏洞。所以目标函数层面的“一致性”,不只是选 PPO 还是 GRPO 的问题,更重要的是你用什么作为奖励信号,以及这个信号和线上评判标准有多接近。

2.3 采样参数不一致带来的分布漂移

第三类不一致非常容易被忽视,但影响往往立竿见影——采样参数。我们在 RL 训练时做 rollout,通常会用 temperature=0.7、top_p=0.9 这种比较有随机性的采样,目的是让策略有足够的探索空间。但到推理阶段,很多团队为了追求稳定输出,直接改成 greedy decoding,或者 temperature=0.1 这种接近贪心的设置。

干过这事的人会发现:训练时看 rollout 上 reward 挺高,一换到贪心解码,效果反而掉下去了。原因并不复杂,模型在 RL 阶段学到的行为是适配高随机性采样环境的,它习惯了“这次采样没抽到最优 token 没关系,后面还有机会补救”这样的统计规律。当你把采样改成贪心,模型相当于被放到了一个它从未训练过的场景里,表现自然打折扣。

反过来说也一样,如果训练时 rollout 用的是低 temperature,推理时却为了多样性拉高 temperature,同样会有问题。正确的做法是:把 rollout 采样参数和线上推理参数当成同一组超参来管理,训练用多少,推理就尽量用多少。如果线上场景实在需要低随机性,那训练阶段就应该逐步降低 rollout 的 temperature,而不是最后测试时才切换。

2.4 上下文长度和终止条件的不一致

最后这类不一致,是我在实际项目里踩得最深的一个坑:序列长度和终止条件。

RL 训练里,我们通常会设置一个最大生成长度 max_tokens,比如 2048。rollout 时模型如果在 2048 个 token 内没有输出 EOS,就会被强制截断,并且这个截断本身会影响 reward(要么给 0,要么给一个惩罚)。问题在于,线上推理时我们可能出于延迟考虑把 max_tokens 设成 1024,或者某类请求上下文特别长、达到了 4096,这都会让模型处于一个训练时从未经历的“长度区域”。

更隐蔽的是终止条件。数学任务里你可能希望模型输出一个最终答案后主动停止,代码 Agent 任务里你希望模型生成完代码块就结束或调用工具。模型在 RL 训练中学习到的“停止”信号,是被奖励函数塑造出来的。如果训练时奖励鼓励“生成到 EOS 才得高分”,而推理时框架在检测到代码块结束时就直接截停,那模型的生成策略就会被打乱。它可能还没写完就停了,或者该停的时候继续啰嗦。

总结一下,训练-推理一致性问题不是某一个环节造成的,而是 teacher forcing 范式、目标函数、采样策略、序列管理这四个层面共同作用的产物。接下来我重点讲如何在实际操作中逐一解决这些错位。

3. 从数据和策略层面,把训练和推理的目标统一起来

3.1 能用规则验证器,就别用训练出来的奖励模型

先给一个最直接的建议:如果任务允许,优先使用规则验证器(rule-based verifier),而不是学习得到的奖励模型。原因就是前面说的,规则验证器给出的分数就是真实推理目标,不存在代理误差。

以数学推理为例,一个简单的验证器可以这样设计:从模型的输出中提取“最终答案”部分,和标准答案做字符串匹配或数值等价比较。代码任务就更直接,把生成的代码放进预定义的单元测试里跑一遍,pass 就算对。这种验证器虽然有“只看结果不看过程”的问题,但至少它的标准是确定且可复现的,模型很难通过“说得漂亮”来骗分。

什么时候才需要上奖励模型?当任务的主观性很强、不存在标准答案的时候,比如开放性写作、对话质量评估。即便在这种情况下,我也建议把奖励模型的训练数据尽量采集自“推理分布”,也就是用当前策略亲自采样得到的样本,而不是只用离线人工标注数据。否则奖励模型很容易在分布外样本上给出虚高分值,RL 训练就会顺着这个虚高信号跑偏。

3.2 用专家迭代和拒绝采样,弥合训练分布与推理分布的沟壑

第二个非常实用的策略,是专家迭代(expert iteration)和拒绝采样(rejection sampling)。

具体操作是这样的:准备一批高质量 prompt,用当前策略模型做采样,每个 prompt 生成 N 个候选回复,然后用验证器或奖励模型给这些候选打分。接下来只保留得分最高的那批样本,把它们作为下一轮 SFT 或偏好优化的训练数据。相当于让模型去模仿“推理分布中表现最好的样本”,而不是笼统地从所有 rollout 中学习。

这个做法高明在哪里?它直接把训练分布拉向了推理分布中偏好的子区域。传统 RL 是让模型在在线采样中探索并优化,虽然能学到新东西,但也容易产生分布漂移——模型跑到训练分布之外,甚至跑到奖励函数失效的区域。专家迭代的每一步都做了筛选,相当于给策略加了一个“安全护栏”,让模型只在已经被验证过的高质量区域内学习。

我自己的经验是,专家迭代配合 GRPO 这类在线 RL 算法,效果往往比单一使用某一种方法更稳。先用 SFT 热身,再做两三轮拒绝采样 SFT,等模型基础能力到位之后,再用在线 RL 做最后的精调。这时候在线 RL 的探索空间已经被限制在了一个比较合理的范围内,reward hacking 的概率会小很多。

3.3 把采样参数和终止设置做成同一套“全局配置”

前面提到,rollout 参数和推理参数不一致会造成分布漂移。解决方式不仅仅是“记住要一致”,而是应该把采样参数、最大长度、终止条件这些设置抽象成一份全局配置,在训练和推理两个阶段共用。

举例来说,我会在一份 YAML 配置文件里定义这样几个字段:

  • temperature:训练 rollout 和推理统一用 0.7
  • top_p:统一用 0.9
  • max_tokens:数学任务统一用 2048
  • stop_sequences:统一用["<|endoftext|>", "\n\nFinal Answer:", "</s>"]
  • eos_token_id:统一使用模型自带的 EOS,同时把 endoftext 也加入停止条件

这份配置同时被训练脚本和推理服务加载。也就是说,训练时 rollout 怎么生成,线上推理就怎么生成,两边不再各设一套。这样做还有一个好处:当你需要调整线上策略时(比如为了降延迟把 max_tokens 从 2048 改成 1024),你立刻就知道必须重新跑一轮 RL 或者至少做一轮针对性的采样验证,而不是想当然地认为“模型应该能适应”。

这里有同学可能会问:推理时我实在想用 temperature=0 的贪心解码,因为业务上需要稳定输出,怎么办?我的建议是,在训练初期可以用较高温度探索,但在训练后期,逐步把 rollout 的 temperature 降到接近线上推理的水平。比如前 60% 的训练用 0.7,后 40% 用 0.3,最后 10% 用 0.1。这会让模型逐渐适应低随机性采样下的生成方式,减少推理阶段的落差。

3.4 采用课程式长度控制,让模型在RL阶段就学会“收敛”

长度控制是我特别想强调的一点。在我做数学推理 RL 训练时,发现模型经常为了多争取过程分而无限拉长推导过程,甚至在得到正确答案之后还要再写一大段“验证”。这在训练时看起来无伤大雅,因为 reward 并没有惩罚长度,但部署到线上之后,多出来的几百个 token 就是实打实的延迟和成本。

要让模型学会“收敛”,核心是在奖励设计里加入长度感知的信号。最简单的方式是:在验证器的最终答案正确的前提下,给一个和输出长度负相关的分数。比如reward = correctness_reward - alpha * max(0, length - expected_length)。alpha 取多少需要调,我一般从 0.001 开始试,观察平均长度变化再调整。

更高级一点的做法是课程式长度控制。训练初期不对长度做任何约束,让模型自由探索完整解法;等模型已经能稳定输出正确答案后,再逐步收紧长度上限,逼着模型精简推理步骤。这样模型不会因为一开始就被压缩长度而学不到完整解法,也不会在后期无限膨胀。课程式设计的本质,就是让“训练时的环境”逐步逼近“推理时的环境”,这本身就是一种一致性优化。

4. 实操记录:用 GRPO 微调数学推理模型,我是怎么对齐训练和推理的

4.1 整体流程:SFT、RLVR、行为快照三件套

我拿一个具体的数学推理模型微调项目来走一遍完整流程。任务目标是提升模型在初中数学应用题上的 final answer 准确率。我没有直接用裸模型做 RL,而是分了三步:

第一步,SFT 热身。准备大约 5 万条带详细解题过程的样本,让模型先学会规范的解题格式。这里要注意,SFT 阶段的数据,最好和目标任务的形式保持高度一致。比如线上推理时,prompt 是“题目 + 请给出详细解题步骤和最终答案”,那 SFT 数据的格式也应该是这样,不要训练时一套格式、推理时另一套格式。

第二步,RLVR 训练。使用 GRPO 算法,奖励信号直接用最终答案匹配的结果,不额外训练奖励模型。rollout 参数和推理参数共用同一份配置,temperature=0.7,top_p=0.9,max_tokens=2048。KL 惩罚系数设置为 0.01,防止策略和初始模型偏离太远。

第三步,行为快照。训练过程中,每 500 步我就在固定 prompt 集上做一次完整的 rollout,记录输出长度、最终答案准确率、格式规范率等指标。这些指标不是用 teacher forcing 算出来的 loss,而是真正在 rollout 分布上测出来的。行为快照的意义在于,它能让你尽早发现训练和推理之间的偏差,而不是等整个训练跑完才在线上发现问题。

4.2 GRPO 奖励设置里容易被忽略的两个细节

GRPO 和 PPO 最大的区别之一是它不需要 value network,而是基于同一个 prompt 的多条采样结果做组内相对归一化。这意味着奖励的绝对数值没有那么重要,重要的是同组样本之间的相对排序。这个特性在缓解奖励信号漂移上很有优势,但同时也带来两个容易被忽略的细节。

第一个细节:组内采样条数(也就是每组的 rollout 数量)对效果影响很大。如果组内样本太少,比如只有 4 条,相对排序的稳定性很差,模型会因为某一次随机波动被错误地引导。我自己测试下来,每组至少 8 条,最好 16 条,效果才比较稳定。代价是显存占用和采样时间增加,但换来的是更平缓的策略更新。

第二个细节:KL 惩罚和奖励之间的平衡。GRPO 虽然去掉了 value network,但通常还是会加一个对参考模型(通常是 SFT 初始模型)的 KL 惩罚,防止策略跑飞。这个 KL 项和 reward 项的矛盾很微妙:KL 太大,模型学不到新东西;KL 太小,模型很快就会 reward hacking。我在这个项目里是用自适应 KL 系数,如果当前 KL 超出目标区间(比如设定 0.5 到 1.5),就自动调整系数。实践中比固定系数省心很多。

4.3 Eval 阶段一定别用 teacher forcing 指标糊弄自己

训练结束后,评估环节是我认为最容易自欺欺人的地方。很多团队看训练 loss 下降了、sft 后的 PPL 也正常,就认为模型变好了,结果上线一测效果反而变差。问题就在于,这些指标全部来自 teacher forcing 分布,无法反映自回归推理时的真实表现。

我在这个项目里的 eval 方案是:在固定测试集上,用和推理完全一致的解码参数跑一遍生成,再对生成结果做最终答案提取和匹配。同时做了三组对比:

评估方式说明
teacher forcing accuracy给定完整标准答案前缀,让模型预测最后答案 token 的准确率
rollout accuracy模型从头自回归生成完整答案,提取最终答案后的准确率
best-of-n accuracy每个 prompt 采样 16 次,取验证器得分最高的结果,计算准确率

这三组数据之间通常存在一个梯度:teacher forcing 最高,rollout 次之,best-of-n 最低。如果 teacher forcing 和 rollout 差距过大,说明曝光偏差严重;如果 rollout 和 best-of-n 差距过大,说明模型虽然会生成正确答案,但不稳定,需要更多探索或更合适的采样参数。我用这三组指标来共同判断模型该不该被部署,比单看任何一个数字都靠谱得多。

4.4 训练后的部署参数对齐:一个常被跳过的步骤

模型训练好之后,还有一步很多人会忽略:重新核对部署时的采样参数。我在项目里会专门写一个 checkpoint 检查脚本,读取模型仓库里的 generation_config.json,对比训练时用的 rollout 配置。如果发现不一致,就输出警告。不要小看这一步,我见过不止一次,明明训练时用的 temperature=0.7,部署工程师图省事直接把典型值 temperature=0.3 写上去了,结果模型行为大变样,白白背了一天的线上事故。

5. 常见问题与排查技巧实录

5.1 Reward 一直上涨,但模型输出越来越啰嗦

这个现象我遇到太多次了。最典型的原因是奖励函数里没有长度惩罚,或者长度惩罚系数过小。模型发现“多写步骤”和“正确率”之间存在正相关,尽管这个相关性很弱,但 RL 强化的是统计规律,只要多写步骤的期望奖励大于少写步骤,模型就会往啰嗦的方向走。

排查思路很简单:把训练过程中每个 checkpoint 的输出平均长度画出来,如果长度一路走高,基本就是这个问题。解决方法是在奖励里加入长度正则项,并且在行为快照中把“输出长度变化”作为和“reward 变化”同等重要的监控指标。如果发现长度涨了但最终答案准确率没涨,那大概率是模型在刷过程分。

5.2 KL 惩罚和奖励失衡,导致模型能力回退

有一段时间我用 PPO 训代码生成模型,发现训练早期 reward 涨得很快,但到中期突然崩掉,生成质量甚至不如初始模型。后来复盘时发现,KL 惩罚系数设得太低,模型在很短几步内就偏离了初始策略,跑到了奖励模型的高分区域,但实际上那个区域只是奖励模型的盲区,并不是真正的代码质量高区域。

解决办法分两步:一是加大 KL 惩罚,或者用自适应 KL;二是给策略更新加一个信任区间,也就是每次更新后计算新旧策略的 KL,如果超过阈值就回滚这次更新。PPO 里这步叫 early stopping,GRPO 里虽然没那么严格,但也应该监控策略变化的幅度。

这里分享一个我自己的经验值:对于代码和数学这类客观任务,KL 的目标区间设在 0.5~2.0 之间比较合适。太低了基本没约束,太高了模型学不到新东西。当然,这只是从我的任务场景里来的经验,大家还是要以自己的验证集为准。

5.3 推理 temperature 和训练差 0.2,效果天差地别

按前面说的,采样参数应该统一。但很多时候不是我们不统一,而是某个推理请求需要温度参数可调,比如产品上要做“创造性”档位。这种情况下,光靠统一配置就不够了,需要对不同的 temperature 档位分别做评估,并且最好在训练时就做 temperature conditioning——让模型在一定的温度范围内都能稳定输出。

具体做法是:在 RL 训练时,rollout 的 temperature 不固定为一个值,而是从一个区间(比如 0.5~0.9)里随机采样。这样模型在训练中见过多种采样条件下的生成环境,推理时无论你用区间内哪个温度,模型表现都不会太差。这个技巧有一点正则化的味道,会让训练难度稍微增大,但换来的是更稳健的泛化能力。

5.4 验证器被 hack:模型学会了“伪造”格式

RLVR 虽然比 reward model 可靠,但验证器本身也可能被攻击。我在一个数学项目里用过“提取关键字附近内容再比对”的验证方式,结果模型学会了在答案区域写很多个可能的数字,比如“答案可能是 5、6、7”,提取逻辑会碰到其中某一个就判定正确,导致 reward 虚高。

后来我改成更严格的 xml 格式验证:要求模型必须输出<final_answer>包裹的答案,而且这个标签内只允许一个数字表达式,否则整个输出判零分。这样做之后,模型的 hack 行为立刻减少了。这个教训说明,验证器的鲁棒性和奖励设计同样重要。设计规则验证器时,一定要问自己:如果我是一个一心只想刷分的模型,我会怎么绕过这个规则?然后提前把漏洞堵上。

5.5 一个通用的“训练-推理一致性检查清单”

最后,整理一份我每次训练之前都会过的检查清单,你可以直接抄走:

检查项训练侧推理侧是否一致
temperaturerollout samplergeneration config
top_prollout samplergeneration config
max_tokensrollout truncationgeneration length limit
stop_sequencesrollout stop listinference stop list
prompt template训练数据格式线上 prompt 构造
reward metricRL reward线上评测标准尽量一致
验证器规则/模型线上校验

每一行都可以打上“是”,意味着你的训练和推理已经被尽可能地绑在一条绳上了。

最后再分享一点个人感受

做 LLM 后训练这段时间,我最深的体会是:模型训练领域最忌讳的就是“训练环境和部署环境脱钩”。很多时候上游同学辛苦调出来的模型,到了下游线上表现不行,不是模型能力不够,而是两边设置压根就没对齐。如果你正在为“reward 涨了但线上没涨”而头疼,先别急着推倒重来,拿这份清单逐项核对一下,很可能问题就出在某个不起眼的温度参数或终止条件上。

另外一个小技巧:每轮训练一定要把 rollout 样本存下来,和 checkpoint 绑定在一起。这样出了问题可以回头分析模型在那个时间点到底生成了什么,而不是只盯着曲线上的数字猜测。有了这些样本,你很快就能发现模型是从哪一步开始跑偏的,甚至能定位到具体的 prompt 类型。这个习惯帮我省下了无数排查时间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 4:30:28

基于阶跃函数脉冲控制的复杂网络同步图像加密Matlab仿真

图像加密、复杂网络同步、脉冲控制、阶跃函数&#xff0c;这四个词放一块儿&#xff0c;乍看很像一篇纯控制理论论文的标题。但把整条链路跑完就会发现&#xff0c;它其实是一条非常完整的信号处理流程&#xff1a;先让复杂网络在脉冲控制下收敛到同步状态&#xff0c;再从同步…

作者头像 李华
网站建设 2026/9/9 4:28:30

CPU水冷散热器选购与安装避坑指南:满载不降频

最近帮朋友装机&#xff0c;又碰上一次“CPU温度压不住”的现场。主机配置不低&#xff0c;CPU还是带K后缀的中高端型号&#xff0c;结果跑压力测试时风扇直接拉满&#xff0c;温度卡在95℃以上&#xff0c;机箱像个小暖炉。拆开一看&#xff0c;他还在用那颗原装小塔散热器。我…

作者头像 李华
网站建设 2026/9/9 4:27:09

Linux下Tomcat 8.5.35生产环境部署全流程实战

简介&#xff1a;Linux版Tomcat 8.5.35压缩包面向需要在Linux服务器上运行Java Web应用的开发与运维人员&#xff0c;封装了Catalina、Jasper、Coyote等核心组件&#xff0c;可直接解压用于部署Servlet/JSP项目&#xff0c;免去手动编译配置。资源共645个文件&#xff0c;约9.2…

作者头像 李华
网站建设 2026/9/9 4:27:01

AI Bot Scraper实战:突破SSE流与浏览器限制,结构化抓取ChatGPT对话

做数据分析的人大概都动过这个念头&#xff1a;能不能把 ChatGPT 的回答批量抓下来&#xff0c;整理成结构化数据&#xff0c;直接喂给下一步流程&#xff1f;我自己第一次尝试的时候&#xff0c;天真地以为就是个普通爬虫的活儿&#xff0c;结果发现页面上的回答倒是看得见&am…

作者头像 李华
网站建设 2026/9/9 4:25:23

智能AR眼镜怎么选?四款热门型号深度横评与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 4:25:10

入门微单vs二十倍专业器材:实拍差距到底有多大

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华