LLM 强化学习能落地,关键在于预训练和 SFT 已提供初始策略,后续算法负责把偏好与奖励稳定推回 token 概率。
阅读时间:约 8 分钟
LLM 的强化学习容易被讲成一串算法名:SFT、RLHF、Reward Model、REINFORCE、A2C、PPO、DPO、GRPO。
这串名字越背越乱。更稳的读法,是盯住训练信号的变化:
这条线走通以后,很多概念会自然归位。
图:LLM 强化学习训练信号
RLHF 从 SFT 的天花板开始
SFT 做的是最大化似然估计:给模型一组 prompt -> ground truth answer,让模型提高正确答案的生成概率。
它的好处是直接。数据长什么样,模型就学什么样。
问题也在这里:答案是外部给定的,模型没有经历"自己生成多个答案、再分辨哪个更好"的过程。遇到没见过的表达、复杂推理或边界条件时,模型可能只学到表面形式,泛化不稳,幻觉也更容易出现。
所以才有拒绝采样。
同一个 prompt,让模型采样多个答案。人工只负责挑出更好的答案,再拿这些高质量样本继续微调。
prompt
-> 模型生成多个候选
-> 人工筛选高质量答案
-> 用高质量答案继续 SFT
这比从零写标准答案更可扩展。标注者不必完整创作,只需要比较模型已经生成的内容。
OpenAI 早期有一类内部做法被称为 FeedME,核心也是从多个输出中选更好的结果,再用它增强微调数据。它仍然是数据分布层面的改造,还没有真正进入强化学习的损失函数。
奖励模型把人工偏好变成可复用的分数
人工筛选有成本。更自然的下一步,是训练一个 Reward Model(RM),让它替人给模型输出打分。
奖励模型通常从语言模型初始化,然后去掉语言头,换成一个标量头。语言头负责预测词表分布;标量头只输出一个奖励值。
训练 RM 时,绝对分数很难收集。不同标注者对"3 分"的理解不一样,同一个标注者在不同批次也会漂移。相对偏好更稳定:给两个回答 A 和 B,让人判断哪个更好。
奖励模型的对比损失可以写成:
Loss = -log(sigmoid(r(x+) - r(x-)))
其中:
x+是偏好样本x-是较差样本r(x)是奖励模型输出的标量分数
这个目标训练的是相对关系:好答案的分数要高于差答案。模型上线后仍然能给单个回答输出绝对奖励,因为标量头学到的是一个可比较的奖励空间。
绝对奖励很有用。策略优化需要知道当前行为有多好,价值函数也要做数值计算。没有稳定的标量奖励,训练方向会变得含糊,收敛更难。
REINFORCE 把训练目标从"只学好样本"推到"也远离坏样本"
拒绝采样只使用评分最高的样本。低分样本大多被丢掉。
REINFORCE 换了思路:让奖励直接进入损失函数。高奖励样本提高概率,低奖励样本降低概率。
可以把目标简化成:
loss = -(reward * log_prob)
如果 reward > 0,最小化 loss 会提高这段生成的概率。
如果 reward < 0,最小化 loss 会压低这段生成的概率。
所以奖励值不能只落在 0~1。如果差答案只是低正分,模型仍会被鼓励学习它,只是力度小。实际训练里常会对奖励做中心化,让平均值接近 0,把低于平均的输出变成负反馈。
这一步才真正把训练从"改数据"推到了"改目标函数"。
但它还有一个粗糙点:奖励通常给完整回答,难以判断每个 token 对结果的贡献。一个答案可能 60% 合理、40% 有问题,只给整段一个分数,会让信用分配很粗。
A2C 和 PPO 解决 token 级信用分配
在 LLM 场景里,可以把生成过程映射成强化学习问题:
| RL 概念 | LLM 中的对应物 |
|---|---|
| 智能体 | 大模型本身 |
| 环境 | prompt、已生成内容和外部反馈 |
状态 S_t |
prompt + 已生成 token |
动作 A_t |
第 t 步生成的 token |
奖励 R_t |
当前 token 或完整回答对应的收益信号 |
A2C(Advantage Actor-Critic)引入两个角色:
- Actor:目标语言模型,负责按当前策略生成 token
- Critic:价值模型,估计状态价值
V_t
优势函数用来判断当前动作比平均水平好多少:
Adv_t = R_t + gamma * V_{t+1} - V_t
Actor loss 可以简化理解为:
loss = -Adv_t * log_prob(A_t | S_t)
Adv_t > 0 时,提高这个 token 的概率。Adv_t < 0 时,降低这个 token 的概率。
优势还可以引入未来优势的影响:
Adv_t = (R_t + gamma * V_{t+1} - V_t) + gamma * lambda * Adv_{t+1}
这里的 lambda 控制偏差和方差的取舍。
PPO 比 A2C 多了一道更新刹车
A2C 的问题是样本效率低。每批轨迹通常只学习一次,因为策略一更新,旧样本分布就不再严格匹配新策略。
PPO 允许同一批样本多轮更新,关键靠裁剪机制限制策略变化幅度。
它会比较新旧策略对同一动作的概率:
r_t(theta) = pi_theta(a_t | s_t) / pi_old(a_t | s_t)
如果这个比值偏得太多,就用 clip 截住,避免梯度一步把策略推飞。
RLHF-PPO 通常包含四个模型:
| 模型 | 是否训练 | 作用 |
|---|---|---|
| Actor Model | 训练 | 目标语言模型,生成 token |
| Critic Model | 训练 | 预测状态总收益 V_t |
| Reward Model | 冻结 | 给生成内容算即时奖励 R_t |
| Reference Model | 冻结 | 用 KL 约束 Actor,防止模型训歪 |
Reward Model 和 Reference Model 冻结。Actor 与 Critic 更新。
Reference Model 一般从 SFT 模型初始化。它的作用是约束 Actor 不要偏离原有语言能力太远。实现上会比较 Actor 和 Ref 对同一 prompt + response 的 log_prob,用 KL 散度近似做惩罚。
Critic 为什么还要训练?因为真实总收益 V_t 在训练时不可直接观测。我们只能用已知的即时奖励 R_t 和下一个状态的估计 V_{t+1} 去逼近:
V_t ≈ R_t + gamma * V_{t+1}
Critic loss 通常写成:
loss = (R_t + gamma * V_{t+1} - V_t)^2
这解释了 R_t 和 V_t 同时存在的意义:一个来自奖励模型的即时反馈,一个来自 Critic 对长期收益的预测。
DPO 直接用偏好数据训练策略
DPO(Direct Preference Optimization)把奖励模型这一步绕开,直接用偏好数据优化语言模型。
它适合偏好明确、但奖励函数难设计的场景。比如两个回答谁更符合人类偏好,这件事可以标注;但要写出稳定的奖励函数,成本很高。
DPO 的核心输入是一组偏好对:
(prompt, chosen_response, rejected_response)
训练时要计算回答在策略模型下的 log 概率。一个常见写法如下:
def compute_logprobs(logits, labels, selection_mask=None):
labels = labels[:, 1:].clone()
logits = logits[:, :-1, :]
log_probs = F.log_softmax(logits, dim=-1)
selected = torch.gather(
input=log_probs,
dim=-1,
index=labels.unsqueeze(-1),
).squeeze(-1)
if selection_mask is not None:
mask = selection_mask[:, 1:].clone()
selected = selected * mask
return selected.sum(-1) / mask.sum(-1)
return selected.mean(-1)
DPO 和 PPO 的差异可以这样看:
| 维度 | DPO | PPO |
|---|---|---|
| 优化信号 | 偏好数据直接驱动 | 奖励模型间接驱动 |
| 奖励模型 | 不需要单独训练 | 通常需要 |
| 训练复杂度 | 更低 | 更高 |
| 稳定性来源 | 偏好数据质量 | 裁剪、KL 和价值估计 |
| 适合场景 | 偏好明确、奖励难写 | 奖励可建模、需要在线优化 |
GRPO 用组内比较省掉 Critic
GRPO(Group Relative Policy Optimization)常被拿来解释 DeepSeek 类推理训练。它的核心是组内相对优势。
对同一个 query,旧策略生成一组输出:
q ~ P(Q)
{o_i}_{i=1}^{G} ~ pi_old(O | q)
每个输出得到一个奖励 r_i。优势不再由 Critic 估计,而是和同组样本比较:
A_i = (r_i - mean(r_1, r_2, ..., r_G)) / std(r_1, r_2, ..., r_G)
这带来一个工程收益:不需要单独的 Critic 模型。显存和训练复杂度都会下降。
一个简单例子:
query:2 + 3 的和是多少?
输出 1:5 reward = 0.9
输出 2:答案是 5 reward = 1.0
输出 3:它们的和是 5 reward = 1.0
输出 4:结果是 6 reward = 0.0
GRPO 会看每个输出相对组内平均表现的位置。高于平均的输出被鼓励,低于平均的输出被压低。
奖励可以来自多个维度:
- 准确性奖励:答案是否正确
- 格式奖励:是否符合结构要求,比如推理内容是否放进
<think>标签 - 语言一致性奖励:是否出现语言混用或格式不连贯
GRPO 仍会使用 PPO 类似的 clip 和 KL 约束,避免策略更新过猛。它省掉的是 Critic,不是所有稳定性机制。
显存压力来自多模型和多输出
RL 训练比 SFT 更吃显存,原因不只在模型大。
以 GRPO 或 RLHF 类训练为例,显存压力主要来自两类:
- 模型侧:策略模型、奖励模型、参考模型,有些方案还要 Critic
- 数据侧:每个 question 会生成多个 output,
num_completions一上去,激活和缓存都会增长
原文提到的实验配置很有代表性:
| 参数 | 含义 | 对显存的影响 |
|---|---|---|
batch_size=1 |
每批 query 数 | GRPO 每个 query 生成多答案,batch 放大很快 |
gradient_accumulation_steps=4 |
梯度累积步数 | 会增加梯度保存压力 |
num_completions=4 |
每个 query 的采样数 | 直接放大生成缓存;DeepSeekMath 论文使用过 64 |
max_prompt_length=256 |
prompt 长度 | 上下文越长,注意力开销越高 |
max_completion_length=786 |
response 长度 | 推理链越长,显存越高 |
| LoRA target modules | q_proj/k_proj/o_proj/up_proj/down_proj |
决定可训练参数范围 |
缓解办法通常有两个:
- 使用 8-bit 优化器,比如 8-bit AdamW,压缩优化器状态
- 使用 gradient checkpoint,用 20%~30% 的训练速度损失换显存
训练时内存里至少要放参数、梯度和优化器状态。AdamW 还要追踪更新历史,所以优化器状态常常比想象中更占空间。
真正落地先看奖励、数据和评估
在业务里落地 RL,不应该先从算法名开始选。
更务实的顺序是:
- 明确目标:要优化安全性、质量、通过率、覆盖率,还是用户偏好
- 判断信号来源:能写奖励函数,还是只能拿到偏好对
- 定义状态和动作:文本任务里动作通常是 token,工具任务里可能是 API 调用
- 评估数据质量:偏好数据、合成数据、线上反馈是否可靠
- 算显存账:多模型、多采样和长上下文能不能承受
- 设计评估流程:每轮训练后用稳定指标判断是否真的变好
文本用例生成就是一个典型场景。奖励函数很难精确定义,但偏好关系更容易拿到:
- AI 生成的用例集 < 人工修正后的用例集
- AI 续写的用例集 < 人工修正后的续写结果
这种场景可以先尝试 DPO。如果平台已经支持 GRPO,也可以用格式奖励、正确性奖励和一致性奖励做小规模验证。
还有几个问题值得继续看
第一,当前"预训练 + SFT + RLHF"的分段范式可能不是终局。未来的训练可能把 RL 更早嵌入预训练或微调阶段,让模型动态学习目标、奖励和环境。
第二,思考更久不等于答案更对。微软亚洲研究院的《Towards Thinking-Optimal Scaling of Test-Time Compute for LLM Reasoning》提到,在简单数学题上,CoT 超过一定长度后准确率反而下降。简单题需要短思考链,难题才需要更长推理。
第三,RL 可能会进入 Agent planning、Text-to-SQL、视觉推理、GUI 操作和工具使用。相关方向包括:
- 《SQL-R1: Training Natural Language to SQL Reasoning Model By Reinforcement Learning》
- 《Visual-RFT: Visual Reinforcement Fine-Tuning》
- 《UI-R1: Enhancing Action Prediction of GUI Agents by Reinforcement Learning》
- 《ToolRL: Reward is All Tool Learning Needs》
工具使用尤其适合 RL,但奖励要足够细。只看最终答案是否正确,无法告诉模型哪一次工具调用、哪个参数、哪一步计划出了问题。
最后一个方向是自适应推理。模型可以用 RL 决定推理深度、模块调用和计算预算。
更合理的目标是按问题难度分配算力。简单问题走短链路,困难问题再延长推理。
收束
LLM 强化学习能落地,关键在于大模型已经有足够好的初始策略。
SFT 给了模型可用的起点。奖励模型把偏好变成分数。REINFORCE、A2C 和 PPO 把奖励推回 token 概率。
DPO 用偏好数据跳过显式奖励模型。GRPO 用组内相对优势减少 Critic 的成本。
真正难的地方仍在工程侧:奖励怎么定义,偏好数据是否可信,显存是否够,评估能不能挡住训练跑偏。
算法名字会继续变。训练信号这条主线不容易变。
推荐阅读
DeepSeek Harness 的 Agent 运行时设计
长任务 Coding Agent 的关键不是写代码,而是交付链路