7 分钟阅读

简介

  SFT RFT
监督信号 示范答案 结果反馈/偏好反馈
训练方式 对于给定Query,直接学习Demonstration(记忆) 采样多组Responses,根据奖励鼓励/惩罚(利用+探索)
训练目标 最大化生成训练语料的概率,通过极大似然估计训练 最大化未来累积奖励,通过策略梯度训练
学习模式 注入外部分布的知识,存在暴露误差问题,泛化性差。更像模式记忆和模仿。 利用+探索自身采样结果中优质的解答模式,泛化性更好。 更像在已有能力边界内做搜索和筛选,从模型自己采样出来的各种回答里,把高分模式强化,把低分模式压下去。
学习规律 由于内外分布的偏差,SFT初期会遗忘模型内部的知识,性能下降;后期容易过拟合,熵降低 随着训练推进,模型逐步学会”简单“问题,出现熵坍缩现象;但困难问题上存在稀疏奖励现象,难以学习

sft 阶段有一个十分重要的职责, 那就是给 posttrain 的 cot pattern 进行定型,这几乎决定了模型在 posttrain 阶段所能达到的效果上限。给定一个 prompt:997 × 1003,会存在以下三种 cot pattern

  1. good pattern:997 × 1003 = (1000 − 3)(1000 + 3) = 1000² − 3² = 999991
  2. mediocre pattern:997 × 1003 = 1003 × (900 + 90 + 7) = 902700 + 90270 + 7021 = 999991
  3. bad pattern:997 × 1003 = 999991 好的 cot pattern 就是会具有输出更短、准确率更高、更易泛化的特点。诚然,sft 带来的 cot pattern 会在后续的 rl 阶段有所改变 ,但很多有些优质的 pattern 并不是在 rl 阶段能轻易 explore 出来的。

仅仅有好的 cot pattern 并不足以训出来一个好的模型,就像天马行空、思路宽泛的人未必真的健谈。人需要学会把自己的想法组织成一种好的表达方式,模型亦需要。具体来说的话,pretrain 阶段所学到的知识是不同的, tokenizer 的词表是有差异的,所以即使给定同一个 cot pattern,不同的模型也会有不同的最佳表达方式。就比如,两个模型都学会了 99 × 99 = 99 × (100 - 1 ) = 9801 的 cot pattern,但在实际应用时:

  1. 强模型解题,99 × 99 = 99 × (100 - 1 ) = 9900 - 99 = 9801 ;
  2. 弱模型解题,99 × 99 = 99 × (100 - 1 ) = 99 × 100 - 99 × 1 = 9900 - 99 = 9900 - (100 - 1) = 9900 - 100 + 1 = 9800 + 1 = 9801。

  3. 绝大多数情况下,我们拿到的 cot pattern 都来自于更强的模型,或者是人工编辑出来的,往往具备“表述极简、思路极优雅”的特点。可问题在于,我们所要训练的模型,不具备足够强的能力去直接消化这种 pattern,模型需要结合自身的能力对 sft 阶段提供的 cot pattern 进行“本土化改造”。这正是 rl matter 的一个关键所在:在给定一个 cot pattern 的情况下,通过 explore 足够多的 response,找到与它本身的“知识量,tokenizer ”最为契合的表达方式,强化这种表达方式形成自己的专属 cot pattern。reasoning 任务上,sft 的 cot pattern 只会告诉模型做完题之后反思一下会更好,但具体要反思多少次效果最好且效率最高, 这便需要模型在 rl 中自己去摸索。同理,强模型在 rl 的时候,会发现 cot pattern 中的某些步骤可以跳过,弱模型则在 rl 的时候会发现 cot pattern 省略的步骤还是写出来会更好;agent 任务上,sft 数据会告诉模型有哪些 sub agent 可以使用,每个 sub_agent 该在什么时机下使用,但具体怎么用便需要 model 在 rl 阶段自己摸索。1T 的模型一次调用 2 个 sub_agent 便可以得到一个正确的 reward 信号,100B 的模型则需要调用 5 个 sub_agent 才能得到一个正确的 reward 信号。不同的模型会在 rl 中找到最适合自己的 agent setting。要验证一个 cot pattern 的潜力,往往是需要 sft + rl 共同协作的,也就是现在 posttrain 的标配流程。
  4. 除此之外,rl 某种程度上还有一点“基因突变” + “进化”的味道。当算力足够大,rollout_n 开的足够大,模型总能有机会在 rl 时 explore 到新的更优质的 cot pattern。此时,好的 rl 算法 (如 GRPO)则需要充分把握这条高质量的数据,给予他足够强的学习信号让模型记住这个 pattern。
  5. 除了对 cot pattern 进行本土化改造外,rl 更重要的意义便是让模型变得可控。传统理解中,大家可能觉着只要精准控制了 sft 的数据分布,便可以控制 sft 后的模型输出内容。遗憾的是,时代变了,由于大量合成语料进入到 pretrain / midtrain 阶段,posttrain 阶段出现乱七八糟的 pattern 的概率越来越大,即使我们所有的 sft 数据都很规范。道理很简单,pretrain 阶段只看数据质量和数据干净程度,根本不会考虑 posttrain 阶段为了用户体验更好而加的一堆乱七八糟的规则。那些质量很高但格式非常不优雅的数据,训了几十 T,这怎么可能是随便几条 sft 数据能压制的,何况 sft 根本不具备打压 pattern 的能力。sft 后的模型会输出多个 ,影响推理服务切分 cot 和 response;sft 后的模型中英混杂屡教不改,影响用户体验;sft 后的模型输出长度十分不稳定,有时候不反思,有时候反思几十次……诸如此类,这些让产品头大的 case,在 reward hack 面前却又是格外的稚嫩,随随便便在 rl 时候给个惩罚 loss 就再也不会出现了。至于现在标配的“思考档位 / 思考深度”,作为“模型可控化输出”的重要模块,看似复杂,通过在 rl 阶段给予不同档位不同的上下文窗口便可轻松实现。

在传统认知中,RL 与 SFT 的区别主要体现在两个方面:

  1. 负样本的利用。SFT只是模仿学习正例,SFT+DPO需要大量的标注数据来cover bad case。而RL不仅对好的样本奖励,也要对坏的样本惩罚。无论是简单的策略梯度,还是GRPO、Reinforce、PPO这些算法,原理都是一致的,本质上只是在设计不同的奖励/惩罚的粒度(token/macro action/seq等等)和力度(需不需要引入baseline,要不要考虑KL限制,要不要clip等等)
  2. (样本的多样性/成本)。rl允许使用当前模型在线产出的样本训练自身(仅on-policy模式)。SFT一般学习的都是人工标注或者其他模型生成的样本(即蒸馏),SFT阶段的Rejection Sampling技术也是自己采样训练自己,很像是RL,只不过没有惩罚信号(也可以引入负例进一步做DPO)。而RL允许当前模型实时采样样本,并依据这些样本训练自身。
    1. SFT需要更多的标注数据,RL可以通过固定的规则奖励(例如math 和code只需要判断最终结果)与奖励模型提供的正负反馈不断迭代,让模型自己探索符合人类偏好的回复策略,可以减少训练数据的要求。

​在标准的LLM训练流程中,通常包含三个阶段:Pre-training、SFT和RL。Pre-training阶段采用自回归的方式在海量数据上完成预训练,为后续的Post-training奠定基础。Post-training通常分为SFT和RL,这两个阶段均需要一个多样性丰富的prompt集合D

  1. 在该阶段对于prompt $x~D$,会采用专家撰写、人工合成或者强模型蒸馏的方法来构造高质量的响应。
  2. ​RL通常在SFT阶段后进行。在On-Policy的设定下,对于prompt $x~D$,通常会从当前策略$\pi_theta$中采样响应y。GRPO是PPO的一种无critic模型的变种,针对同一个prompt x,会同时采样G个响应 ${y_i}_{i=1}^G$,每个响应 $y_i$ 对应于一个标量奖励 $R_i$。在标准的PPO中需要critic模型来辅助计算优势,GRPO则采用组内标准化实现优势的近似计算 $A(i,t)= \frac{R_i−mean([R_1,…,R_G])}{std([R_1,…,R_G])}$,这里 $A(i,t)$是指第i个响应的第t个token的优势。

VLM RL的tech Report中,RL的版本整体涨点在1-2左右,而SFT最高可做到5-6个点。监督学习的上限是老师,而强化学习可以通过学习经验超越老师。

与llm-reasoning

rlhf 和 llm-reasoning 这两个方向有什么区别吗?prompt 的难度和 response 的长度。以往我们使用 rlhf 的场景主要是:安全问题、诗歌创作修复韵脚问题、简单的代码数学问题等,往往都是几百个 token 就搞定的任务。现在不一样了,模型的一条回复就达到了上万个 token,这会让显存压力和解码时长陡增。作为应对,vllm 或 sglang 已经成为 rlhf 框架的标配。最初我也认为 grpo 省掉 critic_model 这一点并不关键,现在看来我还是只考虑了算法和数据的视角,并没有充分理解到额外维护一个和 actor_model 相同规模的 critic_model,对训练框架的稳定性有多大的挑战。当模型 size 和 response_len 逐渐增大,“训练效率和预防训练过程中莫名其妙的 OOM ”就是复现 r1 工作中最大的难点(对,就是莫名其妙,在程序断了之前,你不会知道明明限制了最大 response_len,为啥它还会 OOM)。

与pretrain

先看一个最朴素的信息量对比。假设词表大小为 V,一段序列长度为 T。对于 next-token prediction,每个 token 都有一个监督信号。非常粗略地说,一条序列最多可以提供:Pretraining information ≈ T × log(V) bits。但如果 RL 只在整条 rollout 结束后返回一个二元 reward,那么它提供的可能只有:RL information ≈ 1 bit / rollout,如果一次 rollout 有几十万 token,这个差距会非常夸张。而且 RL 不只是监督信号少,数据生成也贵。Pretraining 可以一次 prefill 整段文本;LLM RL 需要让当前 policy 自回归生成 rollout,长序列 decode 通常受 memory bandwidth 限制。

Pretraining 确实提供了大量信息,但它优化的是 next-token prediction。模型需要预测:

  1. 句子的措辞;
  2. 标点和格式;
  3. 某一步推理采用哪个同义表达;
  4. 中间出现哪个不影响结果的 token;
  5. 互联网上各种彼此无关的文本模式。 这些信息对训练一个通用语言模型当然很重要。但如果当前任务是“让数学题最终答对”,很多 token-level gradient 与最终正确性并没有强关系。

RL 的情况正好相反。它可能只有一个 reward,但这个 reward 直接对应我们真正关心的目标:这条 rollout 到底有没有完成任务。可以这么理解:

  1. Pretraining 给了模型一大袋信息;
  2. 其中确实包含“怎样把任务做对”的信息;
  3. 但这部分信号被大量 next-token prediction 目标包围;
  4. RL 直接把其他目标都删掉,只保留“成功还是失败”。

bits 的数量不等于 bits 对目标任务的有效性。问题不应该只写成:每个样本包含多少 bits?,还应该问:这些 bits 中,有多少直接服务于我们关心的 objective?这就是为什么单纯的信息量计算会低估 RL:它统计了监督信号的总带宽,却没有统计这些监督信号和目标任务之间的 alignment。RL 的信号少,但更纯。

类似的,SFT学习成功轨迹中的每一个 token。它会同时强化:

  1. 真正导致成功的推理策略;
  2. 与成功无关的表达习惯;
  3. 偶然出现的格式与措辞;
  4. 某条轨迹中特有、但不可泛化的 token choice。

Policy gradient 的 reward 更稀疏,却试图回答一个更直接的问题:这整套行为是否值得提高概率?这里要注意,SFT 和 RL 的差异不能只理解成 on-policy 与 off-policy 的差异。即使 SFT 数据来自当前模型自己的成功轨迹,它的 objective 仍然是 token imitation,而不是 expected reward maximization。

为什么 LLM RL 必须建立在很强的 base model 上?前文并没有推翻“RL 缺 bits”这个事实。如果模型距离目标策略已经很近,少量但精准的 bits 也可以带来巨大变化。反过来,如果任务需要从零学习大量知识,RL 依然做不到。比如,只靠 success/failure reward 从零学会一门语言,几乎不可想象。这个任务需要的 bits 太多,而 trajectory-level reward 的带宽太低。因此 LLM RL 能工作的一个关键前提是:Base policy 已经对目标任务有非零且不能太低的 pass@k。如果模型一千次 rollout 一次都成功不了,那么 reward 几乎没有方差,训练也拿不到有用信号。这就是 mid-training 越来越重要的原因。

为什么经典 RL 和 LLM RL 看起来像两个世界?经典 RL,特别是 Atari 或早期从零训练的 agent,需要 reward 承担几乎全部学习任务。它既要学 perception,又要学 environment dynamics,还要学 exploration 和 action policy。此时 reward bit-rate 太低的问题会非常严重。LLM 在进入 RL 之前,已经通过海量 off-policy 文本学到了:

  1. 世界知识;
  2. 语言和代码;
  3. 常见任务结构;
  4. 大量人类行为轨迹;
  5. 一个非常宽的默认 policy space。 所以 LLM RL 不是 tabula rasa RL,更像是在一个超强 prior 上做局部 policy optimization。这可以解释三个现象。
  6. 为什么经典 RL 样本效率低,LLM RL 却很高?
  7. 为什么扩大参数量对经典 RL 帮助有限?如果只有一股细流,把要灌满的洞穴挖得更大并没有用。NTP 每个 token 都提供监督,信息流量足够大,因此更容易从 parameter scaling 中获益。经典 RL from scratch 的 reward 带宽太低,模型容量未必是主要瓶颈。
  8. 为什么 LLM RL 暂时没有那么依赖探索?Pretraining 已经让模型吸收了大量人类产生的行为分布。很多时候,我们并没有让 RL 自己发现全新的策略空间,而是通过 mid-training data 把目标行为先展示给模型。如果 RL 缺少探索,我们当前常用的做法也不是设计一个真正通用的探索算法,而是继续补更好的数据。这件事很有效,但也暴露了一个 caveat:LLM agent 的开放式探索问题其实远没有解决。

与sft

SFT不足

对模型自我进化的思考与设计

  1. SFT不擅长理解和遵循『不要做什么』指令:和传统的分类任务不同,语言模型的SFT是一个生成任务,不具备很强的排他性。在传统的分类任务中,优化模型使得目标类的概率变大,很容易导致其他类别的概率变小。而在语言模型的SFT中,输出往往不是唯一的,同时为了保留语言模型的知识,优化正例时并不会将正例的概率优化成1而将其他可能的回复的概率优化变成0。换句话说,SFT只是告诉了模型训练数据中的回复是可行的,但模型无法像普通分类任务那样利用排他性确定哪些输出是不可行(对于排他性比较好的任务,语言模型的分布本身就有较好的排他性,提升SFT训练样本的概率会大幅降低其他回复的概率)。因此,对于一些回复多样性较高的任务,SFT很难避免模型生成不恰当的回复。从排他性角度来看,SFT擅长『要做什么』指令,但不擅长『不要做什么』指令,尤其是在输出灵活性很高的任务上如创作、摘要。例如对于『生成一篇100字以内的文章』这一指令,其隐含的『不要做什么』的指令是『文章不要超过100字』。对于这一指令,SFT阶段会给模型一个100字以内的文章,但这并不足以让模型确定超过100字的回复是不可行的或者说概率是极小的。如果一定要用SFT来解决这类问题,那么只能不断增加正例数量,挤压负例的概率。但因为这类任务下的正例排他性非常低,这样做的效率也是非常低的。因此,不建议依赖SFT来提升模型对于『不要做什么』指令的理解和遵循能力。
  2. SFT不应该追求统一的输出形式,而应该追求多元的输出形式:在预定义输出标准的指导下,不少同学追求在SFT阶段对齐用户(或产品、RD)的偏好,固化模型的输出形式;或者选择一种初始模型表现较好的形式作为模型的默认回复形式,比如推理任务下默认使用CoT形式进行回复,信息抽取任务中默认不给解释。这样的做法会给模型的能力升级带来很大的困难:
    1. 不利于后期输出形式的调整:随着新老用户的交替以及用户对模型需求的变化,模型的期望输出形式也会发生改变。如果在SFT阶段就固化了模型的输出形式,后期调整模型输出形式需要对SFT进行大规模的改动——大量输出形式不再合适的数据的存在使得增加少量具有新输出形式的SFT数据很难起作用,须先对已有数据进行大规模的退场。
    2. 不利于对不同尺寸模型的适配:不同模型的能力是不同的,大模型可能可以使用简洁的方式回复给定问题,而小模型可能需要更复杂的输出方式。如果只给定一种回复模式,那么注定很难同时满足多个不同的模型:为大模型建设的SFT数据可能无法很好地调教小模型,而为小模型构建的SFT数据对大模型而言过于累赘低效。
    3. 不利于实现千人千面、千题千面:从用户层面来看,不同的用户对回复的倾向是不同的。ToB用户可能更喜欢简洁的回复,而ToC更喜欢具备详细解释的回复。统一的输出形式很难满足不同用户的需求,也无法充分挖掘用户的偏好反馈为将来的千人千面做储备。从任务层面来看,即使是同一个任务,不同case的难易程度及其恰当的回复形式也是不同的。对于比较难的case,模型可能需要使用CoT或者更复杂的Agent模式进行回复;而对于简单的case,模型可以直接回复答案。一致性地采用复杂的输出模式会造成资源的浪费,而一致性地采用简单的回复模式又可能导致模型在一些复杂cases上犯错。SFT阶段固化输出形式无法实现不同能力的兼容,会导致顾此失彼(比如有些平台需要两套不同的接口来区分Agent和非Agent)
    4. 不利于模型自我进化:一个比较理想的模型能力进化路径是从复杂输出模式出发,不断强化模型简单输出模式下的能力,不断形成正确性和简洁性的新平衡。而如果在SFT阶段固化模型的输出形式,限制了模型的探索能力,不利于模型在PPO阶段通过大规模探索自动实现能力的进化。
    5. 不利于形成护城河:因为模型输出的模式化,其他平台可以大规模抓取我方模型的输出,快速对齐我方模型。又因为没有及时引入用户信息,导致无法有效形成用户越多-效果越好-用户越多的飞轮。
    6. 不利于争取其他平台的用户:这主要是不同平台的输出标准不同,固化SFT的输出标准会增加用户从其他平台迁移到我方平台的成本和难度。
  3. “SFT高原”。这一现象是指即使在增加了大规模的有标签数据集之后,模型的性能提升也微乎其微。SFT在这些任务中显得力不从心,这表明它在某些复杂场景下存在固有的性能瓶颈。出现“SFT高原”的原因在于,SFT本质上是一种模式记忆和泛化。对于需要复杂推理、逻辑链或涉及组合爆炸的任务,仅仅依靠增加数据量是无法让模型掌握其内在逻辑的。模型可能会记住训练集中的特定模式,但无法将这些模式推广到全新的、未曾见过的复杂结构中。这种现象揭示了SFT在处理高度复杂、需要动态规划和逻辑推理的任务时的局限性。它表明为了突破这一瓶颈,需要一种能提供更细粒度、更动态反馈的学习机制。RL允许模型通过试错来学习,即使某个输出不完美,只要它比之前的尝试更接近目标,就能获得正向奖励。PS:循循善诱而不是棍棒教育。

因此,SFT阶段应该尽可能避免做形式偏好(既包括展示形式,也包括得到输出的路径)的对齐,而是将其放到RM、PPO阶段去完成(后面会介绍如何在RM系统中引入用户偏好来避免上述问题)。SFT更多的是让模型知道给定指令情况下可能可以怎么回复,提高潜在可行回复的采样概率,尽可能保留模型输出的多样性,以便于后期高效调整偏好(比如对于可回答的问题在SFT阶段也可以引入据答)。

PPO擅长学习『不要做什么』。得益于RM评估的高效性,PPO阶段可以对回复进行大规模采样和评估,此时不仅可以告诉模型什么样的回复是可行的,还可以告诉模型什么样的回复是不可行的(SFT阶段正例样本较少,引入负例容易让模型过拟合负例,将负例中的一些正确pattern的概率也给错误地降低了)。因此,相较于SFT,PPO更擅长学习『不要做什么』,在这个阶段,应加强否定指令的建设。

PPO阶段除了引入用户偏好收敛输出形式外还有一个重要任务是实现能力的进化。典型的Online PPO是从SFT模型的输出空间中筛选出RM得分更高的子空间,所以其最终能力是受限于SFT模型的。当SFT能力覆盖了期望进化方向时,比如期望方向是越简洁越好,同时给定一个query,模型能生成各种复杂度,或正确或错误的输出,此时模型能通过对应的RM模型实现在该方向上能力的进化。而当SFT能力没有覆盖期望的进化方向时,比如模型很难生成既简单又正确的输出,普通的Online PPO无法有效采样出目标方向更好的输出,此时模型进化能力会受限。这种情况下,最直接的方式是先用SFT扩展模型能力边界。但其实也可以直接在PPO过程中扩展模型的能力边界——在PPO阶段引入offline数据,比如从繁琐但正确的回复出发,自动合成简洁且正确的回复,然后用importance sampling的学习方式将该样本引入到PPO的采样集合并进行学习。

与sft 对比

强化学习发展这十年随着这两年强化学习的大力发展,强化学习衍生出了许许多多的子课题方向,除了最经典的online RL以外,例如offline model-free RL,model-based RL,RLHF,multi-agent,risk-sensitive,inverse RL等等,要给这些子课题找共性非常困难。而在传统教科书中,强化学习的标准制定时由于这些子课题还未广泛引入关注,导致定义早已过时。举个例子,例如强化学习强调智能体跟环境交互,而offline RL方向偏说我就不跟环境交互。再例如强化学习强调无需人类标签还是采用奖励信号(相当于“标签/标准答案”的简化版),RLHF说我就不是这样。最开始,人们对强化学习应用的要求也非常严格,在强化学习应用的论文描述里必须有以下内容:

  1. 非常准确的状态空间和动作空间定义
  2. 必须存在状态转移函数,不允许单步决策,也就是一个动作就gameover
  3. 必须有过程奖励,且需要存在牺牲短期的过程奖励而获取最大累计回报的case案例 说个开玩笑的话,如果DS的文章放到几年前RL的审稿人手里,他大概率会得到这样的回复:这只是采用了策略梯度的方式将不可导的损失/奖励函数用于优化神经网络参数而已,请不要说自己使用了强化学习。这导致像作者这样的old school,在看到最新的强化学习应用文章时,总会试图问文章作者几个基础的问题,状态是啥,动作是啥,奖励是啥。但其实现在很多文章已经不考虑这些问题了。

RL 不是优秀的数据海绵SFT 每个样本自带标签,RL 一条轨迹只有一个标量回报 R,为什么说标签比标量“稠密”?

  1. 信号数量。一段长度为 T 的回答,SFT 每个位置都有标签 $y^*$——模型做了 T 次决策,就收到 T 个独立的监督信号,第 1 个 token 该是什么、第 2 个该是什么……逐位置全都告诉你了(1:1);RL 整条轨迹结束后只有一个 R,T 次决策共享这 1 个数(1:T)。
  2. 单个信号的信息量。标签是在词表 $ V $ 个候选里指定正确答案,携带 $\log_2 V $ bits(词表 10 万 ≈ 17 bits),直接告诉梯度往哪走:拉高 $y^*$、压低其余 token;而 0/1 的 reward 只有 1 bit,只说结果好坏,不说哪里错、正确的应该是什么。一条 1000 token 的轨迹,SFT 提供约 17000 bits 的指令,RL 约 1 bit,信息密度差 3~4 个数量级。
  3. credit assignment。看 REINFORCE 梯度 $\nabla J \approx R(\tau)\sum_t \nabla \log \pi(a_t s_t)$,同一个 R 作为系数乘在全部 T 步的 log-prob 上:失败轨迹里走对的步子被一起压低,侥幸成功轨迹里的坏动作也被奖励。哪一步该负责,单条样本里没有答案,正确归因只能靠大量轨迹平均后在统计意义上浮现——这就是 RL 高方差的直接来源;而 SFT 的梯度在每个位置上就是精确的一阶导,单样本即无偏低方差。

打个比方:SFT 是老板逐行 review 代码,每行标注“这行应该这么写”;RL 是交付 200 行代码后老板只回一个字“挂”,哪行错了只能靠反复试错反推。PRM(过程奖励)、逐步打分这类工作,本质都是把 RL 的信号密度往 SFT 方向拉。

RL for LLM本质理解为更清晰地理解 RL(强化学习),我们可以从它与监督学习的联系入手。监督学习(SFT)的损失函数可以表达为:

\[L = -\mathbb{E}_{x \sim p(x)} \mathbb{E}_{y \sim \pi^*(\cdot \mid x)} \left[ \log \pi(y \mid x) \right]\]

其中,$x$ 是提示(prompt),$y$ 是模型的生成内容,$\pi^*$ 是代表人类专家答案的真实分布,$\pi$ 是模型的输出策略分布。其目标是最小化模型分布与专家分布之间的差异。SFT 的 loss 是目标分布(通常是 one-hot)和模型分布的交叉熵函数。PS:或者说,让人工标注的输出(正确答案)概率尽可能大。

RL 的损失函数则可视为一种加权监督学习:

\[L = -\mathbb{E}_{x \sim p(x)} \mathbb{E}_{y \sim \pi(\cdot \mid x)} \left[ \omega(x, y) \log \pi(y \mid x) \right]\]

已知 transformer 的每个 step 的输出是一个 logits 向量,对这个 logits 做一次 softmax 函数就得到了每个 token 被选中的概率。交叉熵乘以reward(Advantage)来影响概率的调节方向和调节力度。如果 Advantage 大于零,logits 向量在当前 token 维度的梯度是负数,这个 logit 会朝增大的方向优化,logits 向量在其他所有维度的梯度都是正数,剩余的 vocab_size - 1 个 logit 都会朝着减小的方向优化;反之亦然。

核心区别

  • 引入了权重项 $\omega(x, y)$ PS: 策略梯度算法通常对应Advantage,RL 杂谈SFT 仅仅是 RL advantage 全为 1 时的一个特例罢了,SFT 是一种全部样本都为 off_policy,只计算正例 loss,且 advantage 均为 1 的 RL
  • 代表人类专家答案的真实分布被替换为模型自己的输出策略分布。PS:不再有“正确答案”,模型输出一个 action(token)后,若带来高奖励,就让这一步的 log-prob 增大。若带来低奖励,就让这一步的 log-prob 减小。

可能有人想说,既然只是加权的监督学习,那 RL 有什么特别的呢?RL的特殊性在于其权重 $\omega(x, y)$ 的设计以及训练数据的来源,这使其区别于旨在调整样本重要性的传统加权学习:

  1. RL 中的 $A_t$ 并不是一个加权常数,$A_t$ 的“完整”写法是 $A_t(\pi)$,这是一个随着 $\pi$ 的变化而发生变化的函数,更麻烦的是,这是一个黑箱函数,无法对 $A_t(\pi)$ 求导,而只能通过采样来评估,采样必然存在误差,进而导致训练不稳定。与之相对的,SFT 的 $A_t$ 实打实就是常数 1。
  2. 权重可为负值,实现“趋利避害”:传统加权学习的权重通常为非负,用于强调重要样本。而RL中的权重可以为负。负权重指导模型“避免”生成特定的行为,而不仅仅是“模仿”期望的行为。这种“惩罚”机制是模型能够快速抛弃失败策略、探索未知但可能更优策略空间(Exploration)的关键,也是其能力超越训练数据限制的根本原因。PS:sft 只是提高期望输出的概率,而rl 可以降低非期望输出的概率
  3. 数据来源与权重结合,形成自洽的优化闭环:RL用于学习的数据由模型自身生成。这一特点与上述的奖惩机制相结合,形成了一个强大的自优化循环:模型生成行为 -> 获得带有正或负权重的反馈 -> 调整策略以增加高权重行为、减少低权重行为 -> 生成更高质量的新行为。通过这一循环,只要权重(以及背后的reward)设计得当,模型便有潜力实现持续的自我迭代与能力攀升,最终达到超越人类的性能水平。

RL 为什么不如 SFT稳定

  1. infra 上的难度 RL 确实较之于 SFT高了不止一个档次,系统级的 bug 存在于训练框架的各个角落。训推一致性修复的时候,计算 logprob 的时候考虑 temperature、top_p、top_k 这些了吗?reward shaping 的时候,reward 从 0 / 1 变成小数,剔除全零全一样本时会兼容这些吗?模型 rollout 的时候,出现了多个</think>的时候,有考虑过怎么处理这种数据吗?这些都是常见的小 bug,megatron、vllm、sglang 的 bug 角度更是刁钻
  2. 另一方面,数据的干净程度相差过远。SFT 的数据筛选会有一套较为复杂的流程,利用各种规则加模型来进行过滤,甚至会人工一条条的进行 review。相比之下, RL 给数据打 reward 的时候通常没有如此复杂的清洗流程,往往只是外挂了一个 reward model 去比较 model_response 与 ground_truth 是否一致。一旦遇到较为困难的 prompt,ground_truth 非常复杂,一致性判别的准确率能有个 90% 都已经算很好了。
  3. 最后再补一条个人的暴论,我认为 LLM 中的 RL 算法如逆水行舟,不进则退,它的每条训练样本都是带有一些“毒性”的,如果这些样本没有 explore 到有价值的信息,模型便会朝崩溃更进一步。具体来说,RL 的每条正样本,都在让语言模型朝着过拟合的方向去学习,即进一步强化那些本就是高概率的语料;RL 的每条负样本,则都是在破坏语言模型的分布,将某个 token 的概率分给其他所有的 token,会将语言模型的分布引向一个未知的方向(负样本的存在也可能是 RL 容易崩溃的关键)。反观 SFT ,每条语料都是我们精心构造的,我们不仅知道这些语料的分布情况,也会想方设法的调超参数来避免模型在这些语料上过拟合。

在上述框架下,当前RL for LLM的研究主要围绕以下几个核心问题展开:

  1. 如何从“用于验证的弱监督信号(reward)”推导出每个样本的权重$\omega(x, y)$ ? 例如,PPO中学习的价值函数(value function),以及DeepSeek GRPO中从批次数据中估计的优势函数(advantage function),都是对该问题的不同解法。
  2. 承接上一点,如何高效、准确地获取“用于验证的弱监督信号(reward)”? 从RLHF可学习的reward model,到DeepSeek的rule-based reward,都是在解决这个问题
  3. RL的两个核心步骤 ——a.基于加权监督学习的模型更新 与 b.新样本的生成——二者的交互节奏是怎样的?是生成一个样本就更新一次(完全在线),还是生成N个样本后更新一次或N次?先前批次生成的样本在后续迭代中是否应该被舍弃(on-policy vs. off-policy的权衡)?PPO/GRPO算法中的修正比值、clip参数、生成批次大小、更新的epoch数目等,都与这个核心节奏问题紧密相关。
  4. RL训练应选择怎样的提示(prompt)分布 p(x)? 以数学问题为例,如何设计一个问题序列(课程),才能最大化模型的学习效率?
  5. 进行RL训练前,基础模型(base model)需要具备哪些先决能力,才能有效支撑后续的强化学习过程? 以上几点构成了当前RL for LLM研究的基本蓝图。对这些问题的不断探索和解答,将持续推动大型语言模型向着更高级的智能形态迈进。

既然 RL 容易训崩溃,那都有哪些技巧可以稳定训练呢,这里简单罗列一下:

  1. entropy collapse:训练的时候加不加 entropy loss,至今仍未达成共识。
  2. CLIP:至少一半的强化工作都围绕 clip 做文章,这些工作分析的非常有道理,实际用起来却乏善可陈。
  3. Token Mask:对高熵 / 低熵 token 做特殊的逻辑,或鼓励某些 token 的学习,或阻止某些 token 的更新,也是重点雕花区域。
  4. Reward Shape:
  5. 控制 reward 样本中 0 / 1 的分布在一个区间范围内;
  6. 用 pass@K 代替 pass@1 作为优化目标;
  7. 用 test case 的通过率作为 reward;
  8. length penalty;
  9. 训推一致性:当下最热的话题,以 tis、icepop 最为火热,但可以说和算法没啥关系,全看 infra 功底。

我个人不喜欢加太多技巧,尤其是 entropy_loss、kl_loss 这种不太知道会对模型产生什么影响的技巧。完全是为了在 RL 的过程中控制模型不去崩溃,让那条训练曲线更好看。大多数实验中,熵炸、grad_norm 炸都属于表象,阻止它不如去分析它,以熵为例:

  1. 为什么会熵增?按理说训练是一个确定性增加的过程应该熵减,但是你的模型确实在增,那就说明训练的过程中:高概率 token 常被当作负例,或者是低概率 token 被常当作正例;
  2. 为什么会熵减过快?rollout 多样性差呗。是不是调整下 rollout temperature 和 rollout prompt 要比加一个 entropy loss 更合理些。

总结下来,任何技巧的本质,都是在帮助模型寻找一个适合它的训练数据分布。因此,分析 rollout 数据分布的变化,优先级要始终领先于尝试引入某个稳定训练的技巧。这些技巧在稳定某次训练的同时,也会掩盖训练崩溃的原因。但同时,若某个技巧确实有用,也可以反过来推哪种数据分布“有利于/有损于”模型的学习:例如, off_policy 和训推不一致会引起崩溃,是不是在间接说明“一个整体上与模型分布很接近,但却在个别 token 上和模型分布差异很大的样本”可能是一种不太适合模型的数据。引入训练技巧必然会引起训练数据分布的变化,有些分布的变化是在我们预期之内的,有些分布的变化则是我们预期之外且不知情的。CISPO 的作者就曾分享过:在 off_policy 的时候, 被 clip 掉的 token 是具有多重分布的,概率值与当前模型的分布不一致只是其所具有的一个分布,“概率低但影响 long cot涌现”则是这些 token 的另外一个分布。作为训练者,我们往往不能留意到所有分布的变化,从而总结出一些错误的结论。这里我并不是反对所有技巧,而是认为:在使用技巧的时候,我们需要知道自己设计的新的loss 会让哪种分布的 token 得到促进 / 抑制?如果无法得知,那就别加。

那么话说回来了,RL到底有没有任何时候都有效且毫无副作用的技巧呢?有的,洗数据!训 reward model!

  1. 先说数据吧,今年大家普遍进入了 post train 深水区之后(从 math、gsm8k 进阶到 aime、imo),一个很严重的问题就是:训模型者看不懂数据了,没有办法通过肉眼看解题过程来判断数据质量了。而训模型者日常批量清洗数据的手段,往往都存在一个问题:“无法区分难题和错题”。
  2. 难题有什么特点?模型多次采样后,屡屡犯错,偶尔灵机一动,做对了。
  3. 错题有什么特点?模型多次采样后,基本都做对,但是因为和 ground_truth 不一致屡屡被判错,偶尔脑子抽风做错了,好巧不巧和 ground_truth 一致了。

不要以为错题的答案是离谱到一眼就能看出来的那种,事实上,错题往往是十分接近 ground_truth 且非常具有迷惑性的。这里我举几个例子:

  1. 一张票 2 块钱,9 块钱能买几张票?我们以为错题的答案会是 356 张这种离谱的数字,其实是 4.5 张;
  2. 一个一元七次方程,错题的答案给了 3 个实数解,我们 review 的时候,反代入进去发现是对的,留下了这道题目。但在训练的时候,模型拿着3个实数解和4个复数解,高高兴兴的去找 reward_model 要奖励的时候,反手被打了 0 分,这对模型是多大的心理阴影呀。 目前的开源 RL 数据的质量真的是一言难尽。没辙,要么请专业的硕博理科生去标注,要么用启发式的规则去清洗,在不够干净的数据上只能得到错误的实验结论。
  3. 再说 reward model,千万不要以为所谓的 rule_based reward model 真的就是靠 rule 来打分的,或者是靠 math_verify 这种规则库 。有很多情况下,靠 rule 几乎无解:
  4. 问题是盈利__%?标准答案是 96,而模型输出了“盈利96%”,模型活该拿 0 分吗?
  5. 标准答案是 3.14,模型输出了$\pi$、圆周率、3.1415926,模型活该拿 0 分吗? reward 要准,我建议使用 generate reward(相对于rule-based reward),而且得是能力巨强的那种。这个模型需要读的懂题目要求的输出格式、 ground_truth 的等价变换,以及各种复杂的高阶公式。除了较强的知识能力外,模型还要具备很强的指令遵循能力,否则它容易自己亲自下场解题。

rl 与sft 融合

为什么要融合SFT和RL RL虽然能够有效提升模型的推理能力,但一个重要的前提是基础模型本身具备了一定的相关能力。在RL训练中,通过多次rollout能够采样到正确的轨迹,这样通过RL才能进一步提升。这无疑限制了RL的探索空间。因此,主流的方式是通过SFT赋予模型一些基础能力,然后在进一步利用RL来提升相关能力。但是一些研究认为两阶段的方式并不是最优的。PS: 建议细读,对理解sft 与rl ,以及多阶段post-train 很有帮助

目前最顶尖的模型通常遵循以下演进路线:

  1. 冷启动 SFT: 使用几千到几万条极高质量的样本,让模型学会基本的推理格式和对话规矩。
  2. 强化学习 (RL):
  3. Reasoning RL: 针对逻辑题,利用结果校验(如代码运行成功、数学题算对)作为奖励信号。
  4. Preference RL: 针对主观题,利用Reward Model或人类排序数据。
  5. 循环迭代: 很多时候会在 RL 之后再收集一波由模型自己生成的、通过了 RL 筛选的高质量样本,回头再做一次 SFT(即反思微调/Reject Sampling Fine-tuning),形成螺旋式上升。

RFT/Reinforcement Fine-Tuning

RFT 只是 PPO 技术范式下的一个新应用范式。它本身并不是一个全新的技术范式,

RFT 就是针对给定 prompt,产生一些包含 cot 的 response ,再通过一个 verifier 来判断 response 是否正确,作为信号来指导模型进行参数更新。抛开 cot 过程不谈,如果我们把这套流程的 verifier 换成 reward_model ,这个流程看上去是不是感到很熟悉? —— 那就是最传统的基于 PPO 的 RLHF。RFT 和 RLHF 唯一的区别就是,它的 return (reward 信号) 是通过 verifier 算出来的,而不是一个 reward_model 计算出来的。verifier 本身则可以看成是一个 rule,比如 math 任务的答案是否正确,code 任务的代码是否能执行 …… 因此, RFT = PPO + rule_based reward_model。至于 RFT 的技术难点,我个人认为和 o1 的技术难点完全 match:高质量 cot 的生产与高准确率 verifier 的获取。

RFT 的价值:只要能定制好一个任务的 verifier,那么 RFT 便可以在这个新的领域场景,以十分之一或更少的数据,轻松超过 SFT 的结果。当然,用 PPO 训练模型能带来的所有收益也都是 RFT 的优点,这里就不赘述了。介绍中还提到,RFT 擅长解决法律、保险、医疗、金融和工程领域等任务,而这些任务通常有明确的“正确答案”。是因为 RFT 只适合答案固定的场景吗?不是,仅仅是因为答案固定的场景 verifier 非常容易制定。Sam Altman 在直播中认为 RFT 是 2024 最牛的技术进展,能帮助大家搞定专业模型的训练。说的没错,RFT 在大模型应用方向确实是划时代的,因为它真的能帮 OpenAI 卖更多的定制化服务。LLM 从业者们也能从中些许受益,掌握了 RFT 技术后,以后老板再提出做一个新的应用模型,我们就不需要再枯燥的标注大量的 SFT 数据,而是花一点时间训个 verifier 即可

字节的 ReFT 可以看作是 OpenAI 的 RFT 在数学任务上的一个极简版实现方案

  1. SFT 得到一个较好的模型;
  2. 给定 prompt,do_sample 多次,生成一些带 cot 的 response;
  3. 答案正确,1 分;答案错误,0.1 分;提取不到答案(说明没有 follow 输出格式),0分;
  4. 根据 returns 更新模型。

ReFT 这篇论文,好就好在它是在 o1 之前发表的。因为 o1 的出现,“cot 的推理过程,MCTS 采样,PRM,ORM,rule-based reward_model” 等概念,已经在 LLM 圈深入人心了。

rl 与蒸馏

Why RL Matters

rl 本质还是在寻找更好的 pattern,通过堆算力找到的好 pattern 的确价值千金,但这个寻找过程可能并不具备价值。我们完全可以通过让 rl 后的模型当 teacher,借助蒸馏把它探索到的行为分布迁移到另一个模型上,从而得到一个指标基本接近 rl 模型的 student 。这也就是业界常使用的合版方案之一:对多个 rl 子模型进行reject sampling sft (另一个方案则是 OPD)。

1T model 在 rl 的时候 explore 到的 pattern,会比 100B model rl 时候 explore 到的 pattern 更加丰富。这个时候,把 1T model 找到的优质 pattern 喂给 100B model,再通过 rl 去适应这个 pattern 的具体表达方式(通常会让小模型的输出变得更长),小模型的指标就基本上和大模型的指标接近了 —— 这种做法在同尺寸、同词表模型上更是屡试不爽。

甚至,蒸馏是可以通过改变数据分布来让 student 比 teacher 更强的。例如,teacher 的 cot 是随机出中英文的,英文 cot 的整体质量更高,我们便可在蒸馏时强行只保留英文 cot 的数据,从而得到更高的指标 —— 但要注意,蒸馏或 OPD,任何能让 student 效果超过 teacher 效果的操作,都应该被用到去提升 teacher 效果上(要么是 student 用的数据质量更高,要么是 student 用的 reward 信号更准),而不是去思考这个操作有多厉害。

概括下来,蒸馏是一种偷看学习笔记的行为:无论是蒸馏 sota 模型的 response,还是蒸馏自家模型 rl 后的 response,都能通过让模型学到一个好的 pattern,得到一个起点很高且或潜力很大的 sft model。在此基础上,通过 rl 去 adapt cot pattern 和 fix bad pattern,进一步消化笔记中的知识,一个优秀的 posttrain model 便闪亮登场了。这也是为什么那么多小作坊选择只做 sft 不做 rl 的原因,又省算力、效果又好的方案,谁能拒绝呢?一言以蔽之:认为蒸馏无用,大抵是没亲自训过大模型的人;认为蒸馏是 posttrain 的全部,大抵是只想做追赶者的人。

distill cot pattern 是最好用的蒸馏方法,但其实也是最低级的蒸馏方法。真正高级且常用的蒸馏方法,是通过借助 sota 模型的能力来优化我们自己的模型,包括但不限于:利用 sota 模型合成现有模型能力边界的数据,利用 sota 模型分析现有模型的 pattern 缺点,利用 sota 模型优化 rl 时候所使用的 verifier ……

llm 在纯训练阶段已经是明牌竞争了,比的就是谁更能 scaling:scaling model parameters,scaling rl data,scaling agent environments。因此,越是想成为领头羊的团队,越是要加大对 rl 的投入,早日摆脱对 sota 模型的(软)蒸馏依赖。反过来也一样,如果只是追求模型在某个能力上的应用价值,蒸馏便已是最好的选择。

留下评论