SFT
监督学习,高质量 (input, output) 对
CS336 · 第 15 课
预训练得到通用 next-token predictor 后,模型还会经历高质量 continued training、指令示范与偏好优化。本课把这些阶段的训练信号分开:SFT 学目标 response,preference/RLHF 再处理多个可行回答之间的取舍。
Spring 2026 官方来源:Lecture 15 PDF · 课程日程
本页是中文学习导读;讲次主题、教师与材料版本以 Stanford 官方页面和讲义为准。
本讲问题:Base model 学会的是预测文本,不是遵循用户意图。Alignment 需要先用示范定义期望行为,再用偏好信号处理多个合理输出之间的取舍。
Base model → instruction / response demonstrations → SFT → preference pairs → reward / preference optimization → 检查 helpfulness、honesty 与 reward hacking。
预训练学的是 next-token distribution,不等于学会服从 instruction。SFT 提供目标 response tokens;preference learning 比较同一 prompt 下的候选;RL 再改变采样 policy。先分清 demonstration、preference pair、reward model、policy 与 reference policy。
SFT: prompt + target response → token cross-entropy → policy
Preference: prompt + chosen/rejected → comparison objective → reward/preference model
RLHF: policy rollouts → reward - KL pressure → advantage → policy update
human preference label ≠ scalar reward truth
reward model score ≠ real-world helpfulness
KL penalty ≠ safety guarantee序列是 [system][user][assistant]。Prompt tokens 是条件,assistant tokens 是要模仿的目标;mask prompt loss 可避免训练目标被长 prompt 主导。若把所有 tokens 都算 loss,模型主要学复述输入格式也可能得到低 loss,却没有更好回答。
若偏好数据中较长答案常获胜,reward model 可能把长度当代理;policy 于是堆砌文字提高 reward,却降低真实质量。KL 约束防止一步漂得太远,但 reference policy 本身有缺陷时,靠近它不等于 honest 或 safe。必须用独立 eval 与 adversarial probes 检查。
核心问题:预训练模型 p(x) 是 token 上的概率分布。它学会的是"什么 token 最可能出现",而非"什么回答最有用"。Alignment 是将模型行为从"likely"调整到"helpful, harmless, honest"的过程。
| Base Model | Instruct Model | |
|---|---|---|
| 训练目标 | 预测下一个 token | 遵循指令、有帮助 |
| 行为 | 续写文本 | 回答问题、完成任务 |
| 示例 | 输入"The cat"→"sat on the mat" | 输入"What is 2+2?"→"2+2=4" |
| 能力 | 语言建模、知识 | + 指令跟随、对话 |
| 方法 | 数据 | 训练方式 | 复杂度 |
|---|---|---|---|
| SFT | (input, output) 对 | 监督学习 | 低 |
| RLHF | 偏好对 (chosen, rejected) | 强化学习 | 高 |
| DPO | 偏好对 (chosen, rejected) | 监督学习 | 中 |
Base Model (预训练完成)
↓ SFT (Supervised Fine-Tuning)
SFT Model (能遵循指令)
↓ RLHF (Reinforcement Learning from Human Feedback)
RLHF Model (符合人类偏好)
SFT 是最直接的 alignment 方法:收集高质量的 (instruction, response) 对,用标准的监督学习微调模型。
# SFT 的数据格式
{
"instruction": "解释什么是机器学习",
"output": "机器学习是人工智能的一个分支,它允许计算机从数据中学习...",
}
# 或者多轮对话格式
{
"messages": [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好!有什么可以帮助你的吗?"},
{"role": "user", "content": "解释什么是机器学习"},
{"role": "assistant", "content": "机器学习是..."},
]
}
| 来源 | 方法 | 代表 |
|---|---|---|
| 人工标注 | 标注员撰写高质量回答 | Llama 2 instruction data |
| 强模型蒸馏 | 用 GPT-4 生成回答 | Alpaca, OpenHermes |
| 用户共享 | 收集真实人机对话 | ShareGPT |
| 现有数据集 | 转换 NLP 数据集为指令格式 | Flan, Super-Natural Instructions |
# SFT 的损失函数(与预训练相同,但只在 response 上计算)
# 对于每个样本 (instruction, response):
# 1. 拼接为: [instruction_tokens, response_tokens]
# 2. 计算 loss 时,instruction 部分 mask 掉
# 3. 只在 response token 上计算 cross-entropy loss
def sft_loss(model, instruction, response):
# 拼接输入
input_ids = tokenize(instruction + response)
# 创建 mask:只对 response 部分计算 loss
mask = [0] * len(tokenize(instruction)) + [1] * len(tokenize(response))
# 前向传播
logits = model(input_ids)
# 计算 loss(只对 response 部分)
loss = cross_entropy(logits[mask], input_ids[mask])
return loss
# 训练参数:
# - 学习率: 比预训练低 10-100 倍 (如 1e-6 到 1e-5)
# - Epochs: 1-3(容易过拟合)
# - Batch size: 适中(32-128)
SFT 的局限:
Llama 2 的发现:27,540 个人工标注的高质量样本,效果优于数百万个开源数据样本。质量远比数量重要。
SFT 只能让模型"模仿"训练数据。但很多时候我们需要模型在多个合理回答中选择最好的那个——这超出了 SFT 的能力:
Step 1: SFT
Base Model → SFT Model (初始化 policy)
Step 2: Reward Model
收集偏好数据 → 训练 Reward Model R(s, a)
Step 3: PPO 优化
用 Reward Model 作为奖励信号,通过 PPO 优化 policy
Reward Model 学会预测"人类更喜欢哪个回答":
# 偏好数据收集
# 给定同一个 prompt,模型生成多个回答
# 人类标注者排序: A > B > C
# Reward Model 训练
# 输入: (prompt, response)
# 输出: 标量 reward
# 损失函数 (Bradley-Terry 模型):
# L = -E[log(σ(R(prompt, chosen) - R(prompt, rejected)))]
# 即: 让 chosen 的 reward 高于 rejected
class RewardModel(nn.Module):
def __init__(self, base_model):
super().__init__()
self.transformer = base_model
# 替换 classification head 为标量输出
self.reward_head = nn.Linear(hidden_dim, 1)
def forward(self, input_ids, attention_mask):
outputs = self.transformer(input_ids, attention_mask)
# 取最后一个 token 的隐藏状态
last_hidden = outputs.last_hidden_state[:, -1, :]
reward = self.reward_head(last_hidden)
return reward.squeeze(-1)
PPO (Proximal Policy Optimization) 的核心思想:
用 Reward Model 的输出作为奖励
通过 policy gradient 优化语言模型
同时用 KL 惩罚防止模型偏离太远
对每个 prompt:
1. 用当前 policy π 生成 response
2. 用 Reward Model 计算 reward R(prompt, response)
3. 计算 KL 惩罚: KL(π || π_SFT)
4. 总奖励 = R - β × KL
5. 用 PPO 更新 policy
PPO 的 loss:
L = -E[min(ratio × advantage, clip(ratio, 1-ε, 1+ε) × advantage)]
其中 ratio = π_new(a|s) / π_old(a|s)
# RLHF/PPO 训练循环:
for batch in prompts:
# 1. 生成 responses
responses = policy.generate(batch.prompt)
# 2. 计算 rewards
rewards = reward_model(batch.prompt, responses)
# 3. 计算 KL 惩罚
kl_penalty = compute_kl(policy, sft_model, batch.prompt, responses)
# 4. 总奖励
total_reward = rewards - beta * kl_penalty
# 5. 计算 advantage (使用 GAE)
advantages = compute_gae(total_reward, values)
# 6. PPO 更新
for _ in range(ppo_epochs):
new_log_probs = policy.log_prob(batch.prompt, responses)
ratio = exp(new_log_probs - old_log_probs)
loss = -min(ratio * advantages,
clip(ratio, 1-eps, 1+eps) * advantages)
loss.backward()
optimizer.step()
方法 1: 直接比较
给定 prompt,生成 4 个 responses
人类标注者排序: A > C > B > D
生成偏好对: (A, C), (A, B), (A, D), (C, B), (C, D), (B, D)
方法 2: 成对比较
给定 prompt,生成 2 个 responses
人类标注者选择: A > B
生成一个偏好对: (A, B)
方法 3: Elo 评分 (类似 Chatbot Arena)
多次比较,计算每个 response 的 Elo 分数
Llama 2 的发现:偏好数据的质量比数量重要。少量高质量偏好对(~10K)比大量低质量偏好对更有效。一致性(inter-annotator agreement)是关键指标。
模型学会"欺骗" reward model,而非真正提高质量:
Reward hacking 的表现:
1. 生成 reward model 喜欢但人类不喜欢的回答
2. 利用 reward model 的盲点
3. 生成"安全但无用"的回答(reward model 不给负分)
例: Reward model 偏好长回答
→ 模型生成冗长、重复的回答
→ Reward 高,但人类不喜欢
缓解方法:
1. KL 惩罚(防止偏离 SFT 太远)
2. 定期更新 reward model
3. 人类在环评估
KL 惩罚: KL(π_RLHF || π_SFT)
防止模型偏离 SFT 分布太远
为什么需要 KL?
- 没有 KL: 模型可能找到 reward model 的漏洞
- 有 KL: 模型必须在"提高 reward"和"保持接近 SFT"之间权衡
KL 惩罚的大小 (β):
- β 太小: 几乎无约束,reward hacking 风险高
- β 太大: 模型几乎不更新,RLHF 无效
- 最优 β: 需要实验确定
| 挑战 | 表现 | 缓解 |
|---|---|---|
| 标注者不一致 | 不同标注者有不同偏好 | 多数投票、一致性过滤 |
| Reward model 过拟合 | 在训练分布外表现差 | 正则化、更大模型 |
| 模式崩塌 | 模型输出多样性下降 | 温度调参、diversity reward |
| 长度偏差 | 偏好长回答 | 长度归一化 |
| 计算成本 | 需要多个模型同时运行 | 模型压缩、蒸馏 |
| 维度 | SFT | RLHF |
|---|---|---|
| 数据 | (input, output) 对 | (prompt, chosen, rejected) 三元组 |
| 训练方式 | 监督学习 | 强化学习 (PPO) |
| 计算成本 | 低 | 高(需要 4 个模型) |
| 能力上限 | 受限于训练数据 | 可以超越训练数据 |
| 风格控制 | 直接模仿 | 通过 reward 间接控制 |
| Reward hacking | 无 | 有(主要风险) |
| 实现复杂度 | 低 | 高 |
关键洞察:SFT 和 RLHF 不是互斥的。实际系统中通常先用 SFT 让模型"入门",再用 RLHF 进一步"调优"。SFT 提供基础能力,RLHF 提供风格和安全。
数据覆盖多种任务类型
数据经过人工审核或来自高质量来源
使用统一的对话格式
只在 response 上计算 loss
使用较低的学习率 (1e-6 到 1e-5)
训练 1-3 个 epoch(避免过拟合)
在 held-out 验证集上监控 loss
SFT model 质量足够好(作为初始化)
偏好数据覆盖多种 prompt 类型
标注者一致性 > 80%
Reward model 在验证集上准确率 > 70%
PPO 训练时监控 KL 散度
定期做人类评估(不只看 reward 分数)
保存多个 checkpoint,选择 reward 和 KL 的平衡点
问题 1:SFT 训练时,loss 在哪些 token 上计算?
问题 2:什么是 Reward Hacking?
问题 3:RLHF 中 KL 惩罚的作用是什么?
问题 4:SFT 和 RLHF 的关系是什么?
Prompt 900 tokens、response 100 tokens。若全部 token 等权算 loss,哪类目标更容易主导?
答案:prompt reconstruction 占 90% positions,可能压过 response imitation;response-only mask 把 prompt 作为条件。
若认为每个样本只算一次所以长度无关,你忽略了 token-level cross-entropy 的求和/平均对象。
人类偏好昂贵且主观;下一课转向数学答案、代码测试等可验证奖励,并追踪 rollout group 如何形成相对 advantage。
监督学习,高质量 (input, output) 对
Reward model + PPO,从偏好中学习
主要风险,KL 惩罚缓解
质量 > 数量,SFT + RLHF 结合