← 返回学习路线 ◆ 贯穿项目
大模型核心 · 阶段 9 · 预训练、后训练与强化学习
Stage 09 / 17 · 大模型核心

预训练、后训练与强化学习 Pretraining, Post-training & RL

这是 2026 年最能拉开差距的阶段,也是招聘溢价最高的能力。行业的事实共识已经很清晰:现代 Decoder 块 + 大规模去重数据 + SFT 冷启动 → 可验证奖励的 RL + 多阶段后训练(含蒸馏)。真正的竞争不在「要不要用 RL」,而在用哪种 RL、基于什么奖励信号、配多大算力。

⏱ 6–8 周(优先级最高) 🎯 高级 · 核心壁垒 ◆ 里程碑 M9 2026-09-29
PretrainingSFTRLHFDPOGRPODAPOAgentic RL蒸馏

阶段总览

✔
学完你能做到
  • 能设计并实现一条数据管线:清洗、去重、配比、质量筛选、合成数据与污染检查
  • 理解 Scaling Law 与算力预算,能估算一次预训练的成本与可行性
  • 掌握 SFT 的数据构造(格式、损失掩码、样本配比)与常见失效模式
  • 能用 DPO / KTO / ORPO 做偏好对齐,并知道它们相对 RLHF 的取舍
  • 能实现并跑通 GRPO 训练,理解 DAPO / GSPO / GMPO 在修什么问题
  • 理解 Agentic RL 的三大难题(稀疏奖励、信用分配、rollout 成本)与主流解法
  • 会做蒸馏与合成数据,能在有限算力下把能力迁移到小模型
  • 掌握分布式训练与断点续训,能在大规模训练中处理 loss spike 与硬件故障
阶段知识结构总览 · 从原始语料到对齐模型的完整链路
阶段 9 · 预训练、后训练与强化学习Pretraining, Post-training & RL · 9 大章 · 110+ 知识点
1. 预训练数据与算力MinHash + LSH 近似去重领域配比 + 温度采样污染检查 n-grammid-training 尾段退火Data Card
2. SFT 冷启动loss mask 只训 assistantSFT 数据配方配比失效模式五类Llama-Factory / TRL质量 > 数量
3. 偏好对齐 RLHF → DPOBradley-Terry 奖励模型PPO 四模型显存DPO 隐式奖励推导KTO / ORPO / SimPOβ 控制保守度
4. 可验证奖励 RLGRPO 组相对优势DAPO Clip-Higher ε=0.28熵崩塌监控Agentic RL 三大难题GSPO / GMPO / GiGPO
5. 蒸馏与合成数据on-policy 蒸馏白盒 logits KL拒绝采样通过率 20–40%模型坍塌三陷阱温度 T=2.0
6. 训练基建与故障SpikeGuard 回滚checkpoint 周期策略NCCL 卡死排查OOM 三连MFU 监控
7. 分词BPE 合并频次BBPE 256 字节SentencePiece压缩率 3.5–4.5digit token 算术
8. 参数高效微调LoRA ΔW = B·Ar=16 仅 0.78% 参数B 初始化 0 平滑起步QLoRA NF4 双重量化DoRA 幅度方向解耦
9. 遗忘与对齐评测灾难性遗忘四成因数据回放 10–30%双轨评测门禁五指标上线门禁β 连带调参
贯穿项目 · M9 领域微调与对齐第 47–54 周领域指令集构造(含去重、难度分层、格式统一、训练/评测隔离)LoRA / QLoRA 微调,记录显存与耗时对比偏好/可验证奖励对齐,含奖励黑客现象排查SFT / DPO / GRPO 三阶段效果对比(含人工抽检 30 例)
学习路径
★
2026 的八点共识(背下来):① 现代 Decoder 块;② 细粒度 MoE + 共享专家,按全局 batch 均衡;③ 重去重 + Scaling Law 数据配比 + mid-training 尾段;④ 刻意过训练;⑤ SFT / 冷启动 → RL;⑥ GRPO 家族 + 可验证奖励 + 熵控制 + 可训练性过滤;⑦ 多阶段后训练,蒸馏出现在某一环;⑧ 安全奖励栈 + 预备度评估 + 红队。
⚠
真正的分歧点(面试高分题):合成数据 vs 人类数据;继承(蒸馏)vs 学习(RL);AdamW vs Muon(2026 年 Muon 明显占上风);GRPO vs GSPO vs 回归 Critic;RL 为主 vs DPO 为主。能对每个分歧说出「什么条件下该选哪一边」,就是资深工程师的表征。
周次主题交付物
第 1 周预训练数据管线一份可复现的清洗 + 去重 + 配比脚本与数据卡片
第 2 周Scaling Law 与算力预算一次训练的算力 / 成本估算与可行性判断
第 3 周SFT 全流程用 Llama-Factory 或 TRL 完成一次指令微调
第 4 周偏好对齐 DPO / KTO / ORPO构造偏好数据并完成 DPO 训练与对比
第 5–6 周GRPO 与可验证奖励数学 / 代码任务上跑通 GRPO 并分析熵与长度变化
第 7 周Agentic RL 与蒸馏多轮工具任务的轨迹数据 + 蒸馏小模型
第 8 周基建与复盘分布式训练排错手册 + 完整实验报告

1. 预训练:数据与算力的双重工程

知识结构图 · 预训练数据与算力
预训练数据与算力3 大知识域 · 17 个知识点
数据管线采集→清洗→精确去重→近似去重→筛选→配比MinHash + LSH 去重语义去重 ANN质量筛选启发式 + 模型打分污染检查 n-gram数据卡片 Data Card
学习路径
  1. 读 1.1:背下数据管线七步(采集→清洗→精确去重→近似去重→筛选→配比→合成),记 MinHash+LSH 与 ANN
  2. 对一小份语料跑精确+近似去重,观察去重后剩余占比并记录统计
  3. 对接 M9:把该管线思想落到 SFT 数据构造(含去重/难度分层/格式统一)
✔ 能执行一遍数据清洗去重并量化减少幅度,产出可复现的数据卡片
核心知识点详解
  • 七步管线顺序不能乱:采集→清洗→精确去重→近似去重→筛选→配比→合成。先去除重再做质量筛选,优先去掉机器噪声再谈难度配比,顺序错了会重复浪费算力。
  • 精确去重 + MinHash+LSH 近似去重:精确去重按内容哈希;近似去重用 MinHash 生成签名 + LSH 分桶找 Jaccard 相似度高的近重复。语义去重再加 ANN(向量近似检索)。
  • 污染检查用 n-gram 命中:把评测集切成 n-gram,看是否大量出现在训练语料里(如 k=13 连续命中率高即疑似污染)。污染会让评测虚高。
  • 数据卡片与可复现性:每个步骤记录输入/输出 token 数与哈希,产出 Data Card。常见坑:去重后忘记录保留率,无法回答「数据从多少缩到多少」,也无法复现。
配比与退火温度采样 mix_sample领域权重退火去重后仅剩 30–50%10–30T token 量级
学习路径
  1. 读 1.1:理解温度采样 mix_sample 与领域权重退火,记去重后仅剩 30–50%、10–30T 量级
  2. 跑插值 mix_sample 或配比退火示例,观察各领域 token 占比随步数变化
  3. 完成本章自测:给定任务写出一份领域配比并说明为何加高质量尾段
✔ 能设计领域配比与退火策略,并解释质量优先原则下的 token 预算
核心知识点详解
  • 去重后的量级:原始语料去重 + 筛掉低质后仅剩 30–50%;训练常见 10–30T token。配比先按领域权重混合,再用温度采样 mix_sample 平滑。
  • 领域权重退火:训练前期代码/数学重一些,后期逐渐把权重退给高质与目标域数据;末尾加「高质量尾段」让模型记住输出风格。weight(t)=w0+(w1−w0)·t/T。
  • 质量优先的 token 预算:预算有限时,宁可少 token 高质,也别灌水低质把模型毁掉。token 预算 = ∑(领域权重×领域 token 量)。
  • 如何自测配额比例:给定业务领域(如代码/中文/数学),写出一份配比并说明为何把「高质量尾段」放在最后。常见坑:领域权重直接硬 mix 不做退火,尾段权重被前面打断。
mid-training 尾段学习率退火高质量占比 15%→30%长上下文扩展到 128K能力预热占算力 5–15%
学习路径
  1. 读 1.2:理解 mid-training 是"尾段":学习率退火、高质量占比 15%→30%、长上下文 128K、能力预热、占算力 5–15%
  2. 对接 M9:把 mid-training 的高质量数据提升思路用在 SFT 数据难度分层上
  3. 完成本章自测:说明 mid-training 与主预训练的边界与作用
✔ 能说清 mid-training 三个动作及其 5–15% 算力占比,并与 M9 数据策略贯通
核心知识点详解
  • mid-training 是「尾段」:在主预训练末尾追加一段高质量、长上下文训练:学习率退火、高质量占比 15%→30%、把上下文扩到 128K。它占整段算力 5–15%,却显著决定最终能用多长、多高质量。
  • 能力预热:在尾段预先「预热」读长文档、跨距离利用等能力,避免上线后才发现长上下文没训到。
  • 与主预训练的边界:主预训练保面、mid-training 提点:前者数据广、lr 高、短上下文;后者数据精、lr 退火、长上下文。二者是同一套权重的两个阶段。
  • 能否用于 M9:M9 的 SFT 数据里可沿用「难度分层 + 高质量尾段」思路:把高质量指令放训练末期。常见坑:把 mid-training 做成二次预训练,lr 从头再 warmup 而不是退火,浪费算力。
学习路径

1.1 数据管线:决定上限的一步

一句话总结 2026 年的数据经验:数据质量与配比的收益,往往大于模型规模的收益。一条合格的数据管线按下面的顺序执行,每一步都要留可复现的统计与版本。

采集与抽取
网页、书籍、代码、论文、对话、专有数据。记录来源与许可,这是合规的基础。
正文提取与清洗
去模板与导航、去乱码与控制字符、语言识别、长度过滤、有害内容过滤。
精确去重
按文档内容的哈希去重;同源镜像极多,不去重会让模型记住并复述。
近似去重
MinHash / SimHash + LSH 处理改写、拼接、轻微变动;这一步对代码与网页尤其关键。
质量筛选
启发式(标点比、重复行比、词表覆盖)+ 模型打分(小型分类器或 LLM 打分)。廉价的分类器先滤一遍。
领域配比与混采
确定各领域权重并用温度采样控制;训练中后期做配比退火(中后期提高高质量数据占比)。
合成数据与增强
用强模型重写、生成、扩写;必须做质量过滤与去污染,否则会放大错误。
污染检查
用 n-gram 或嵌入检测训练集与评测集的交集。污染了,所有指标都是幻觉。
打包与分词
文档打包到固定长度、记录注意力边界的处理方式、多轮样本的掩码规则。
python# 近似去重(MinHash + LSH):预训练数据管线里性价比最高的一个环节
from datasketch import MinHash, MinHashLSH
import re

def shingles(text, k=5):
    tokens = re.findall(r"\w+", text.lower())
    return {" ".join(tokens[i:i + k]) for i in range(max(1, len(tokens) - k + 1))}

def minhash(text, n=128):
    m = MinHash(num_perm=n)
    for s in shingles(text):
        m.update(s.encode("utf8"))
    return m

lsh = MinHashLSH(threshold=0.8, num_perm=128)     # 相似度 > 0.8 视为重复
kept, dropped = [], 0
for i, doc in enumerate(documents):
    if i % 100000 == 0:
        print(f"progress {i:,}  kept={len(kept):,}  dropped={dropped:,}")   # 长任务必须打点
    m = minhash(doc)
    if lsh.query(m):                             # 命中已有近重复
        dropped += 1
        continue
    lsh.insert(str(i), m)
    kept.append(doc)
✔
数据卡片(Data Card):每份数据集都应记录:来源与许可、采集时间、清洗规则版本、去重比例、领域分布、污染检查结果、已知偏差与风险。这是合规审查(如 EU AI Act 要求提供训练数据摘要)与团队协作的必备产物,也是新项目最容易偷懒、最容易在审计时出问题的地方。

语义去重(semantic dedup) 是精确 / MinHash 之上的第三层:对残留文档做 embedding,用近似最近邻(FAISS / ScaNN)或聚类去除「语义相同但字面不同」的近重复。它比 MinHash 更准(能抓改写、转述),但成本高出 1–2 个数量级,且阈值需谨慎——过严会把合理重复(同义表述、常见开头)也删掉。

污染检测(contamination) 决定所有指标是否可信:用 n-gram 重叠率或困惑度异常,检查训练集与评测集是否交叠。数学 / 代码类 benchmark 最容易被「不小心」混进预训练语料,导致分数虚高、上线即崩;2026 年主流开源模型都会随权重发布 contamination report。

课程学习与数据退火:训练早期用宽分布打基础,训练中后期逐步抬高高质量 / 难样本(数学、代码、长文、推理链)的占比,并把学习率线性衰减(annealing)。这与 1.2 的 mid-training 是同一思想的两种落地——先广后精。

数据量级与 Scaling Law 的关系:Chinchilla 的最优比例约 20 token / 参数(即 7B 配约 140B token)。但 2026 年(DeepSeek、OLMo、MiniCPM 等)普遍「过训练」:用 100+ token / 参数 训更小的模型,因为推理才是长期成本,小模型服务更便宜;同时数据质量(去重、配比、合成)带来的 loss 下降常大于单纯加量——数据工程已是第一性生产力。

去重层次方法成本精度适用
精确去重哈希 / 全文比对最低只抓完全复制同源镜像
近似去重MinHash + LSH中抓改写 / 拼接网页、代码
语义去重embedding + ANN高抓转述 / 同义高质量语料精修
python# 领域配比 + 温度采样:控制「各领域被抽到的相对比例」
import numpy as np

def mix_sample(domains, probs, temps, n, seed=0):
    p = np.array(probs, dtype=float)
    t = np.array(temps, dtype=float)
    q = p ** (1.0 / t); q = q / q.sum()        # 温度>1 拉平,<1 放大高权重领域
    picks = np.random.default_rng(seed).choice(len(domains), size=n, p=q)
    for i, d in enumerate(domains):
        print(f"{d:6s} 目标={p[i]:.2f} 温度={t[i]:.2f} 实际占比={(picks==i).mean():.3f}")

mix_sample(["web","code","math","books"], [0.5,0.2,0.15,0.15], [1.0,0.7,0.6,0.8], 200000)
# 预期:温度<1 的领域(code/math)实际占比高于目标权重
# 机制:这就是「中期抬高高质量占比」的实现——先广后精,配比退火与 lr 退火同步

2026 的规模量级参考:头部开源模型预训练语料在 10–30T token 量级(多语言 + 代码 + 数学 + 网页),去重后的有效数据往往只剩原始抓取的 30%–50%。污染检查是红线:数学/代码 benchmark 一旦混入预训练语料,所有分数虚高、上线即崩。

1.2 mid-training:2026 年被重视的“尾段”

除了预训练与后训练,2026 年各家普遍多了一段 mid-training / 退火阶段:在预训练后期调整数据配比(提高高质量、数学、代码、长文档的占比),用更低学习率继续训练。这一阶段对最终能力影响显著,且成本远低于从头训练。

python# mid-training 的「两段式」:前期宽分布,尾段切高质量 + lr 退火
def midtrain_schedule(step, total, switch_frac=0.8):
    anneal = step >= total * switch_frac
    phase = "anneal" if anneal else "broad"
    if anneal:
        frac = (step - total * switch_frac) / (total * (1 - switch_frac))
        lr = 3e-4 * max(0.0, 1 - frac)
    else:
        lr = 3e-4
    hi = 0.15 if not anneal else 0.30           # 代码/数学高质占比
    return phase, lr, hi

for s in (0, int(8e4) - 1, int(8e4), 100000):
    ph, lr, hi = midtrain_schedule(s, 100000)
    print(f"step {s:6d} -> {ph:6s} lr≈{lr:.2e} 高质量占比={hi:.0%}")
# 预期:80% 步数后切到 anneal:lr 线性趋零、代码/数学占比从 15% 抬到 30%
# 经验:mid-training 常只占总算力的 5%-15%,但对最终能力影响显著
★
为什么「尾段」这么值钱:在固定预训练预算里,把最后 5%-15% 的算力花在高质量数据 + 低学习率上,性价比极高:它不改变模型规模,却能明显提升数学/代码/长文能力。2026 各家公开配方几乎都把长上下文扩展与能力预热放在这一段,而不是放到昂贵的从头训练里。
★
1.3 动手练习与自测:数据题考「管线顺序 + 配比 + 污染」三件事。
  1. 排顺序:给出清洗、精确去重、近似去重、质量筛选、配比的正确顺序。判据:清洗→精确去重→近似去重→质量筛选→配比→打包。
  2. 算去重率:原始 10T token,去重后 4T,去重率?参考答案:60%。
  3. 污染检查:怎么判断训练集混入了 GSM8K?判据:n-gram 重叠率或 perplexity 异常检测。
  4. 配比退火:为什么中后期提高代码/数学占比?判据:高质量数据在尾段对能力影响最大。
  5. 温度采样:温度 > 1 会让分布更平还是更尖?判据:更平(拉近各领域占比)。

2. SFT:冷启动与指令跟随

知识结构图 · SFT 冷启动
SFT 冷启动3 大知识域 · 15 个知识点
数据构造与损失掩码loss mask 只算 assistant非 assistant 段置 -100按能力维度配比失效模式:遗忘 / 僵化 / 复读通用指令 5k–50k 条
学习路径
  1. 读 2.1:理解 loss mask 只算 assistant 段、按能力配比,记通用指令 5k–50k 的量级
  2. 实现 build_example 构造数据并核对 input_ids 与 labels 的掩码正确性
  3. 对接 M9:为领域 SFT 构造指令集并做去重/难度分层/训练评测隔离
✔ 能造出 mask 正确的 SFT 数据并跑通一次,核验非 assistant 段全部置 -100、避免长样本主导梯度
核心知识点详解
  • loss mask 只算 assistant 段:user/系统提示的 target 全置 -100,CrossEntropyLoss(ignore_index=-100) 会跳过,模型只学如何作答而不是去生成问题。常见坑:忘设 ignore,模型把用户问题也学了,表现为「复读指令」。
  • 非 assistant 段置 -100 的判定:labels[i] = tokenizer.pad_id if not assistant else input_ids[i],干扰格式 token 也一并屏蔽。
  • 按能力维度配比与规模:通用指令常见 5k–50k 条即可;按能力维度(知识/推理/遵从)分层配比,质量>数量。
  • 避免长样本主导梯度:loss 通常是均值贡献,超长样本的 token 数多会吸走大部分梯度;要按 token 数加权或截断平衡。常见坑:多轮对话里只标中间某轮 assistant,前后轮漏标导致掩码错位。
SFT 实操Llama-Factory 配置化TRL SFTTrainerLoRA rank 16全量 lr 1e-5~2e-5梯度累积等效 batchSFT 只是冷启动
学习路径
  1. 读 2.2:用 Llama-Factory / TRL SFTTrainer 配 LoRA(rank 16)、全量 lr 1e-5~2e-5、梯度累积等效 batch
  2. 在领域数据上跑一次完整 SFT,记录训练曲线与验证指标
  3. 对接 M9:用 M7 训练管线复用做 SFT,产出具名/对比可复现的结果
✔ 能配好并跑通一次 SFT,理解 SFT 只教形式不教推理,指标可复现
核心知识点详解
  • LoRA rank 16 起步:lora_r=16、lora_alpha=2r(DeltaW 缩放 α/r),只训低秩增量,把可训参压到 1% 以下。peft 或 Llama-Factory 一行切换 target_modules。
  • 全量 lr 1e-5~2e-5、LoRA lr 1e-4~3e-4:全量微调学习率一个小量级到 1e-5~2e-5;LoRA 用 1e-4~3e-4。lr 过高会灾难性遗忘、过低学不动。
  • 梯度累积等效更大的 batch:grad_accum=N 每 N 步才更新一次(optimizer.step() + zero_grad()),等效 batch=N×batch_size,只占同样显存。
  • SFT 是冷启动不是终点:SFT 只教「输出形式」不教「推理能力」,真正的能力提升要靠 DPO/GRPO。常见坑:SFT 数据里硬塞错误/标答混合,指标看似好但实际学的是风格不是能力。
定位与判据SFT 教形式不教推理质量 > 数量多轮掩码正确避免长样本主导梯度
学习路径
  1. 读 2.1/2.2:理解 SFT 教形式不教推理、质量 > 数量、多轮掩码正确、避免长样本主导梯度
  2. 完成本章自测:说明 SFT 与预训练的定位差及两者的失效模式预防
  3. 对接 M9:确认领域问答基线相对基座的提升并说明 SFT 的边界
✔ 能区分 SFT 的定位并给出数据质量与掩码的正确工程判据
核心知识点详解
  • SFT 教形式、不教推理:它把已有能力引导到正确输出格式(指令跟随、格式统一),本身不新增知识或推理。所以别指望 SFT 提升数学能力,那是 RL 的活。
  • 质量 > 数量:几千到几万高质量样本往往优于几十万低质样本;统一格式、去重、难度分层比堆量收益大。
  • 三条工程判据:① 非 assistant 段全置 -100;② 多轮掩码正确、不把历史问题算进 loss;③ 无超长样本主导梯度。三者都过才算数据合格。
  • 失效模式先行防:「遗忘 / 僵化 / 复读」三种退化都要在配比与退火上提前防范。常见坑:只盯准确率不看 PPL 与复读率,SFT 过拟合了都没发现。
学习路径

2.1 数据构造与损失掩码

SFT 的目标不是「教会模型新知识」,而是把已有的能力引导到正确的输出形式上。数据质量与格式一致性比数量重要得多——2026 年的实践中,几千到几万条高质量样本往往优于几十万条低质量样本。

python# 关键细节:只在 assistant 片段上算损失(loss mask)
# 若对 user 部分也算损失,模型会学着去“生成用户的问题”
def build_example(tokenizer, messages, max_len=4096):
    input_ids, labels = [], []
    for m in messages:
        ids = tokenizer.apply_chat_template([m], add_generation_prompt=False,
                                            tokenize=True)[2:-2]     # 去掉首尾特殊符
        input_ids += ids
        labels += ids if m["role"] == "assistant" else [-100] * len(ids)   # 非 assistant 掩掉
    input_ids, labels = input_ids[:max_len], labels[:max_len]
    return {"input_ids": input_ids, "labels": labels, "attention_mask": [1] * len(input_ids)}

# 常见数据配方(按能力维度配比,而不是等比例混)
RECIPE = {
    "通用指令": 0.35, "数学推理": 0.20, "代码": 0.20,
    "长文档问答": 0.10, "工具调用": 0.10, "安全拒答": 0.05,
}
失效模式表现原因与对策
灾难性遗忘通用能力下降、语言混杂数据太窄;混入通用数据、降低学习率、用 LoRA
格式僵化回答千篇一律、过度客气模板太单一;增加风格多样性
只学形式不学推理答案结构漂亮但内容是错的需要 RL 阶段用可验证奖励纠偏
重复与复读输出循环重复数据里有重复样本;去重、加重复惩罚
过度拒答把正常问题也拒掉安全数据权重过高;重新配比
python# 验证 loss mask:只有 assistant 段有非 -100 标签
def check_mask(labels):
    n_sup = sum(1 for x in labels if x != -100)
    print(f"监督 token 占比 = {n_sup/len(labels):.2%}")
    assert labels[-1] != -100, "最后一个 token 必须被监督(否则学不到结束)"

# 预期:监督占比通常 20%-60%(取决于回答长度)
# 若接近 100% -> 忘了掩掉 user 段;若接近 0 -> 掩反了

样本量经验:通用指令 5k–50k 条、垂直领域 1k–20k 条往往足够;2026 的共识是「质量 > 数量」,几十万条低质量样本常不如几千条精筛样本。多轮对话要保证每轮都正确掩码,并限制单样本长度,避免长样本主导梯度。

2.2 实操:一次完整的 SFT

bash# 方案 A:Llama-Factory(配置化,最快出结果)
llamafactory-cli train configs/sft_lora.yaml
#   model_name_or_path: Qwen/Qwen3-8B
#   stage: sft
#   finetuning_type: lora
#   lora_rank: 16
#   dataset: my_instruct_v3          # 已注册的数据集名
#   cutoff_len: 4096
#   per_device_train_batch_size: 2
#   gradient_accumulation_steps: 8   # 等效 batch = 16
#   learning_rate: 1.0e-4            # LoRA 可用较大学习率
#   num_train_epochs: 3
#   lr_scheduler_type: cosine
#   bf16: true

# 方案 B:TRL(代码可控,便于自定义)
python -m trl.scripts.sft --model Qwen/Qwen3-8B --dataset my_instruct_v3

# 方案 C:从零开始(理解流程用,不建议直接上生产)
#   datasets + transformers.Trainer + 自定义 collator(含 loss mask)
★
SFT 的定位(2026 年的共识):SFT 是冷启动,负责教会模型「该以什么形式回答」;真正提升推理能力与可靠性的,是可验证奖励的 RL 阶段。不要指望用 SFT 把数学和代码能力“喂”进去——SFT 只能学到训练数据里出现过的模式,而 RL 可以通过奖励信号探索出新的解题路径。
python# 用 TRL 做 SFT 的最小可运行脚本(含 loss mask)
from datasets import load_dataset
from transformers import AutoModelForCausalLM
from trl import SFTTrainer, SFTConfig

model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-8B", dtype="bfloat16")
ds = load_dataset("json", data_files="my_instruct.jsonl", split="train")

cfg = SFTConfig(output_dir="out", max_length=4096, num_train_epochs=3,
                per_device_train_batch_size=2, gradient_accumulation_steps=8,
                learning_rate=2e-5, lr_scheduler_type="cosine", bf16=True,
                gradient_checkpointing=True)
SFTTrainer(model=model, args=cfg, train_dataset=ds).train()
# 预期:等效 batch=16;3 epoch 后 loss 明显下降,用 eval 集监控过拟合
# 经验:全量 SFT lr 约 1e-5~2e-5;LoRA 可放大到 1e-4~3e-4
★
2.3 动手练习与自测:SFT 的坑几乎都出在「数据与掩码」上。
  1. 掩码判断:对 user 段也算 loss 会怎样?判据:模型学会生成用户问题、指令跟随退化。
  2. 样本量:1 万条精筛 vs 30 万条低质,选哪个?判据:优先精筛(质量 > 数量)。
  3. 超参:全量 SFT 与 LoRA 的学习率量级差别?判据:LoRA 大 1–2 个数量级(1e-4~3e-4 vs 1e-5~2e-5)。
  4. 失效诊断:模型开始复读怎么处理?判据:数据去重 + 重复惩罚 + 降 lr。
  5. 定位:SFT 能教出新的数学推理能力吗?判据:不能,SFT 只学数据里出现过的模式,需 RL 突破。

3. 偏好对齐:从 RLHF 到 DPO

知识结构图 · 偏好对齐
偏好对齐3 大知识域 · 21 个知识点
RLHF 与奖励模型三阶段流程Bradley-Terry 损失 σ(r_w−r_l)奖励黑客PPO 四模型显存KL 系数 β 0.01–0.1
学习路径
  1. 读 3.1:理解 RLHF 三阶段、Bradley-Terry 损失、PPO 四模型显存与 KL 系数 β 0.01–0.1
  2. 实现 rm_loss 并核验"被偏好回答得分更高"的收敛方向
  3. 对接 M9:对比 RLHF 与 DPO/GRPO 的成本与稳定性,说明本项目为何选后者
✔ 能写 Bradley-Terry 损失并说清 RLHF 三硬伤(reward hacking/成本/标注贵)
核心知识点详解
  • 三阶段流程与 Bradley-Terry:SFT → 训 RM → RL(PPO)。RM 用 Bradley-Terry:p(y_w≻y_l)=σ(r_w−r_l),最小化 -log σ(r_w−r_l),让被偏好回答得分更高。F.binary_cross_entropy_with_logits 一行实现。
  • PPO 需要四份模型:policy / reference / RM / Critic 同时驻留显存,显存开销大;每个 policy 回答都要 ref 与 RM 打分,成本高。
  • KL 系数 β 0.01–0.1:总奖励 r_total = r_RM − β·KL(π_θ∥π_ref)。β 过大学不动,过小语言退化。reward 要先 scaling/裁剪,否则 KL 易爆炸。
  • 三硬伤:① 奖励黑客(模型学会谄媚/变长而非真变好);② 成本高(4 模型 + 推理推理);③ 偏好标注贵且不一致。常见坑:RM 训练时的偏好样本与 SFT 分布偏移,导致 RM 泛化出错。
DPO 家族DPO 离线隐式奖励β 控制偏离参考KTO 二元标签ORPO 合并 SFTSimPO 去参考模型成本为 PPO 的 1/2–1/4
学习路径
  1. 读 3.2:区分 DPO / KTO / ORPO / SimPO 的标签需求与适用,记成本为 PPO 的 1/2–1/4
  2. 实现 dpo_loss 四个标量输入跑一遍,理解隐式奖励 = β(logπ−logπ_ref)
  3. 对接 M9:用 DPO(或直接实现在 TrainLoop)做偏好对齐,记录 β 的敏感性
✔ 能实现 DPO 损失并说清各家族方法的数据需求与适用场景
核心知识点详解
  • DPO 离线隐式奖励:不需要单独 RM,把隐式奖励直接代入目标:loss = -log σ(β·log(π(y_w)/π_ref(y_w)) − β·log(π(y_l)/π_ref(y_l)))。离线用已有偏好对即可训。
  • β 控制偏离参考:β 越大越保守(贴参考模型),越小越激进。隐式奖励 r = β(logπ − logπ_ref) 由当前策略与参考策略的对数比给出。
  • 家族改法一句话:KTO 只要二元好坏标签(无需两两对比);ORPO 把 SFT 与偏好合并一起训;SimPO 去掉参考模型降低显存。成本普遍为 PPO 的 1/2–1/4。
  • 谁用谁:有偏好对比对→DPO;只有好/坏二元标注→KTO;想省显存→SimPO。常见坑:DPO 要求偏好对来自同一 policy 分布,跨模型 mix 出的对会让梯度错乱。
DPO 隐式推导π* ∝ π_ref·exp(r/β)r=β(logπ−logπ_ref)代入 Bradley-Terry 消元何时用 GRPO 而非 DPO
学习路径
  1. 读 3.3:推导 π* ∝ π_ref·exp(r/β),把隐式奖励 r 代入 Bradley-Terry 消去 RM
  2. 用 logp 数值复现 implicit_reward 与 DPO 目标,验证 β 越大越保守
  3. 对接 M9:从数学上说明何时用 DPO 而非 GRPO(有无可验证奖励)
✔ 能完整推导 DPO 隐式奖励并说清 DPO 与 GRPO 的数学适用边界
核心知识点详解
  • π* ∝ π_ref·exp(r/β):从 KL 正则的 RL 目标出发,最优策略闭式解为 π*(y|x) ∝ π_ref(y|x)·exp(r(x,y)/β)——偏好对齐就是在「贴近参考」与「最大化奖励」间权衡。
  • 把隐式奖励 r 代入 Bradley-Terry 消去 RM:由闭式解反解 r(x,y) = β(logπ − logπ_ref),再代入 p(y_w≻y_l)=σ(r_w−r_l),RM 完全消失,剩下只含当前策略与参考策略的 DPO 目标,实现「隐式对齐」。
  • β 越大越保守的数值验证:r=β(logπ−logπ_ref),β 越大对参数更新更「迟钝」(每次梯度更小),宏观上贴参考。β=0.1 比 β=1 学得更快但更漂。
  • 何时用 DPO 而非 GRPO:有可验证奖励(对错可判、格式可查)时走 GRPO/RLVR;只有不可验证的偏好信号时走 DPO。常见坑:把不可判定的偏好硬套成可验证奖励去做 RLVR,得到的是噪声梯度。
学习路径

3.1 RLHF 与它的昂贵

RLHF 的三段式流程:① 收集人类对多个回答的排序;② 训练一个奖励模型(RM)拟合这些偏好;③ 用 RL(传统上是 PPO)优化策略,使 RM 打分更高,同时用 KL 惩罚约束不要偏离 SFT 模型太远。

⚠
RLHF 的三个固有问题:① 奖励黑客(reward hacking):模型学会博取 RM 的高分而不是真正变好(比如变得更长、更自信、更谄媚);② 成本高:需要 4 个模型同时在显存里(策略、参考、RM、Critic),PPO 显存开销大;③ 偏好数据昂贵:人类标注慢且不一致。

三阶段的数据需求:① SFT 数据(指令-回答对,数千到数十万条,质量优先);② 偏好数据(同一 prompt 的多个候选回答 + 人类排序,通常每任务数百到数千条对比对);③ 奖励模型用 Bradley-Terry 模型拟合:p(y_w ≻ y_l | x) = σ(r(x, y_w) − r(x, y_l)),训练目标是最大化被偏好回答的得分差。

PPO 训练机制:每一步由 policy 生成回答 → reward model 打分 → 用 GAE 估计优势 → 策略梯度更新。总奖励 r_total = r_RM − β·KL(π_θ ∥ π_ref),其中 KL 惩罚把策略锁在 SFT 模型附近(β 过大则学不动、过小则语言退化)。奖励要先做 reward scaling 与裁剪,否则 KL 易爆炸。显存瓶颈在于要同时驻留 policy / reference / RM / Critic 四份模型——这也是 PPO 被 GRPO 等无 Critic 方法替代的主因。训练精度上,2026 大集群普遍用 FP8(per-tensor / per-block scaling 的 Transformer Engine) 跑预训练与大规模 RL 的 rollout 以压低算力成本,并配合 QAT 量化感知训练保持数值稳定。

阶段数据形态量级主要成本
SFT指令-回答对10³–10⁵ 条低,可纯合成
偏好标注多候选 + 排序10²–10³ 对比对/任务人工慢、贵、不一致
RM 训练偏好对10⁴–10⁵中
PPO 在线实时生成 + RM 打分持续采样最高(4 模型 + rollout)
python# Bradley-Terry 奖励模型损失:让「被偏好」的回答得分更高
import torch, torch.nn.functional as F

def rm_loss(reward_chosen, reward_rejected):
    # p(y_w 优于 y_l) = sigmoid(r_w - r_l)
    return -F.logsigmoid(reward_chosen - reward_rejected).mean()

print(rm_loss(torch.tensor([2.0, 1.5]), torch.tensor([0.5, 0.2])))
# 预期:r_w 明显大于 r_l 时 loss 趋近 0;反之 loss 增大
# 隐患:RM 会奖励「更长、更自信、更谄媚」——这是 reward hacking 的温床

PPO 的显存与稳定性账本:要同时驻留 policy / reference / RM / Critic 四份模型,7B 模型即需约 4 份权重的显存;KL 系数 β 常取 0.01–0.1,过大则学不动、过小则语言退化。这也是 2026 用无 Critic 的 GRPO 替换 PPO 的直接动因。

3.2 DPO 家族:把 RL 变成分类问题

DPO 的核心洞察很漂亮:RLHF 的最优策略有闭式解,可以把它代入偏好目标,从而消掉奖励模型与 RL 环节,直接得到对「好答案 vs 坏答案」的监督损失。于是训练像微调一样简单,成本只有 PPO 的 1/2–1/4。

python# DPO 损失的核心结构(理解用,实际用 TRL 的 DPOTrainer)
import torch, torch.nn.functional as F

def dpo_loss(policy_chosen_logp, policy_rejected_logp,
             ref_chosen_logp, ref_rejected_logp, beta=0.1):
    """
    beta 控制允许偏离参考模型的强度:越大越保守。
    关键:用 policy 与 ref 的对数概率差作为隐式奖励,
          因此不需要单独的奖励模型。
    """
    chosen_reward   = beta * (policy_chosen_logp   - ref_chosen_logp)
    rejected_reward = beta * (policy_rejected_logp - ref_rejected_logp)
    loss = -F.logsigmoid(chosen_reward - rejected_reward).mean()
    return loss, chosen_reward.mean().item(), rejected_reward.mean().item()

# 只用 4 个标量就能讲清 DPO 的全部数学 —— 这就是它的美
print(dpo_loss(torch.tensor([-8.0]), torch.tensor([-12.0]),
               torch.tensor([-9.0]), torch.tensor([-9.5])))
方法需要奖励模型需要在线采样适用场景特点
RLHF + PPO是是追求上限、可在线探索最贵;多模态与生产级对齐仍常用
DPO否否(离线)中小模型对齐的事实标准轻量稳定;不探索,正确答案不在数据里就学不会
KTO否否只有「好/坏」二元标签(无成对数据)数据要求更低,工业场景很实用
ORPO否否想把 SFT 与对齐合并成一步省一次训练,效果略逊于分阶段
RLAIF / 宪法式用 AI 反馈代替人类视实现降低人工标注依赖需注意 AI 判官的偏见传播
python# DPO 的隐式奖励与 beta 的作用(数值演示)
def implicit_reward(logp_policy, logp_ref, beta=0.1):
    return beta * (logp_policy - logp_ref)      # r = beta * log(pi/pi_ref)

ch = implicit_reward(-7.0, -8.0, 0.1)           # +0.10
rj = implicit_reward(-11.0, -9.0, 0.1)          # -0.20
print(f"chosen={ch:.2f}  rejected={rj:.2f}  diff={ch-rj:.2f}")
# 预期:差为正且越大,loss 越小;beta 越大越保守(贴合参考模型)
# 经验:beta 常取 0.1(0.05 更激进、0.5 更保守)

SimPO 进一步去掉参考模型:直接用策略自身的平均 log 概率做长度归一化奖励 r = (β/|y|)·log π(y|x),省掉 reference 前向的显存与计算;CPO 则把 SFT 项与偏好项合并。这些变体让「离线对齐」在单卡上更可行,是 2026 小团队最常用路线。

3.3 DPO 的奖励隐式推导(为什么不需要 RM)

DPO 的美在于它把「奖励」彻底约掉。RLHF 的最优策略满足 π*(y|x) ∝ π_ref(y|x)·exp(r(x,y)/β)。两边取对数得 log π* = log π_ref + r/β + const,整理出隐式奖励 r(x,y) = β·[log π_θ(y|x) − log π_ref(y|x)] + C——即奖励被表达为「策略与参考模型的对数概率之差」。

text# DPO 损失的来源(推导骨架)
# 1) 最优策略:  pi*(y|x)  ∝  pi_ref(y|x) * exp(r(x,y)/beta)
# 2) 取对数:    log pi*   =  log pi_ref + r/beta + C
# 3) 解出奖励:  r(x,y)    =  beta * (log pi_theta(y|x) - log pi_ref(y|x)) + C
# 4) 代入 Bradley-Terry 偏好目标并消元 r:
#    L_DPO = -E[ log sigmoid( beta*(logpi_theta(y_w|x)-logpi_theta(y_l|x))
#                            - beta*(logpi_ref (y_w|x)-logpi_ref (y_l|x)) ) ]
# 没有 RM、没有在线采样——奖励被「隐式」表达为策略与参考的 log 比

推导的实操含义:β 控制「允许偏离参考模型多远」——β 越大越保守(更像 SFT 模型、对齐收益小),越小越激进(可能训飞)。DPO 不在线探索,所以正确答案若不在偏好数据里就学不到;这是它相对 PPO/GRPO 的天花板。KTO / ORPO / SimPO 是它的近亲:KTO 用「好/坏」二元标签而非成对数据;ORPO 把对齐塞进 SFT 一步(省一次训练);SimPO 去掉参考模型、直接用策略自身的平均 log 概率做长度归一化奖励,更省显存。

ℹ
什么时候该用 DPO 而非 GRPO:当奖励无法被程序验证(写作风格、安全性、主观偏好)且你只有离线偏好数据时,DPO / KTO 是性价比最高的选择;当奖励可被验证(答案对错、单测通过、格式合规)时,GRPO / RLVR 能探索出数据里没有的解,上限明显更高。2026 年的成熟流水线往往是「DPO 管主观对齐、GRPO 管能力上限」双轨并行。
python# SimPO:去掉参考模型,用长度归一化的平均 log 概率当奖励
import torch, torch.nn.functional as F

def simpo_loss(logp_chosen, len_chosen, logp_rejected, len_rejected, beta=2.0, gamma=0.5):
    r_w = beta / len_chosen * logp_chosen           # 平均每 token log 概率
    r_l = beta / len_rejected * logp_rejected
    return -F.logsigmoid(r_w - r_l - gamma).mean()  # gamma 为目标奖励间隔

print(simpo_loss(torch.tensor([-20.0]), 40, torch.tensor([-60.0]), 60))
# 预期:gamma(margin)越大越要求 chosen 明显更优,训练更激进
# 好处:无需 reference 模型 -> 显存约省 1/3,适合单卡离线对齐
变体关键改动省掉了什么
DPO策略/参考 log 比当隐式奖励奖励模型 + 在线采样
SimPO长度归一化 + 目标间隔 γ参考模型前向
CPOSFT 项与偏好项合并一次额外训练
KTO好/坏二元标签(非成对)成对偏好数据要求
ORPO把对齐塞进 SFT 一步单独的偏好训练阶段
★
3.4 动手练习与自测:对齐题要能「推公式 + 选方法」。
  1. 推 DPO:从最优策略 π* ∝ π_ref·exp(r/β) 推出隐式奖励。判据:r = β(log π − log π_ref)+C。
  2. 选方法:只有「好/坏」二元标注、没有成对数据,用哪个?判据:KTO。
  3. 省显存:想在单卡做离线对齐且不想加载参考模型?判据:SimPO(长度归一化,无 reference)。
  4. β 取舍:DPO 的 β 太大/太小分别什么后果?判据:太大过度保守像参考;太小奖励被忽略、易训飞。
  5. 何时不用 DPO:奖励可程序验证时该用什么?判据:GRPO/RLVR,能探索数据里没有的解。

4. 可验证奖励 RL:2026 的主战场

知识结构图 · 可验证奖励 RL
可验证奖励 RL3 大知识域 · 22 个知识点
RLVR 与 GRPO可验证奖励免 RM组相对优势 Â_iGRPO 去 Criticgroup_size 8–16KL β 0–0.04熵崩塌判据
学习路径
  1. 读 4.1:理解 RLVR 免奖励模型、组相对优势、GRPO 去 Critic,参数 group_size 8–16、KL β 0–0.04
  2. 实现 grpo_step 骨架并跑通一次,看到全对/全错组被跳过与熵崩塌判定
  3. 对接 M9:实现 grpo.py 做可验证奖励对齐,记录 group/β 敏感性
✔ 能实现 GRPO 训练循环并说清组相对优势避免 Critic、可验证奖励无黑客
核心知识点详解
  • 可验证奖励免 RM、无奖励黑客:奖励由程序判定(数学对错/代码过测/格式合规),不存在「讨好评委会」的 hacking 空间,RL 因此可规模化、可复现。
  • 组相对优势 Â_i 替代 Critic:对同一 prompt 采样 group_size 个回答,用组内奖励相对偏离替代 PPO 的 Critic 价值估计:Â_i = (r_i − mean(r组)) / std(r组),去掉 Critic 模型。
  • GRPO 目标与参数:loss = -E[1/g 组均值 Â_i·min(ρ_i, clip(ρ_i,1−ε,1+ε))] + β·KL(π∥π_ref),ρ_i 是重要性比。group_size 常用 8–16,KL β 取 0–0.04。
  • 熵崩塌判据:策略熵快速下降、组内回答趋同即熵崩塌。常见坑:全对/全错的组贡献零信号却仍更新,白耗算力——DAPO 的动态采样会丢弃这类组。
GRPO 家族改法DAPO Clip-Higher ε_high=0.28DAPO 动态采样丢弃全同组Token-level 归一GSPO 序列级重要性比GMPO 几何平均CISPO 只裁权重
学习路径
  1. 读 4.1:记住 DAPO / GSPO / GMPO / CISPO 各修什么问题
  2. 对接 M9:在 grpo.py 里对确有更好的改法说明取舍与测量
  3. 完成本章自测:把家族改法对照到 M9 遇到的现实问题(熵崩塌、无效样本、长度膨胀)
✔ 能说出各 GRPO 家族改法对应修的问题,并为 M9 选一合适项
核心知识点详解
  • DAPO:Clip-Higher + 动态采样 + Token 级损失:上界剪钳 ε_high=0.28(而非对称 ε)、丢弃全对/全错组、token 级归一、超长惩罚,针对熵崩塌与无效样本。clip(ρ,1-ε_low,1+ε_high)。
  • GSPO / GMPO / CISPO 一句话:GSPO 把重要性比从 token 级升到序列级,抑长序列噪声;GMPO 用几何平均更稳;CISPO 只对权重做裁剪,简化实现。
  • 对照 M9 现实问题选法:若遇到熵崩塌→选 DAPO Clip-Higher;长度膨胀→超长惩罚;噪声大→GSPO 序列级。先量问题再上改法。
  • 测量先行:每个改法都要留开关并记录 reward/长度/熵三曲线,别一把全上无法归因。常见坑:好几个改法同时开,出现「混合效应」分不清谁的功劳。
Agentic RL稀疏奖励信用分配rollout 成本 10–100×GiGPO 组中组两层优势Tree-GRPO 树搜索回归 Critic 双轨制
学习路径
  1. 读 4.2:理解稀疏奖励、信用分配、rollout 成本 10–100×、GiGPO/Tree-GRPO/回归 Critic
  2. 完成本章自测:说明稀疏奖励下 GRPO 的局限与多步信用分配难点
  3. 对接 M9:说明 Agentic RL 与本阶段可验证奖励的区别,明确项目阶段边界
✔ 能说清 Agentic RL 的稀疏奖励与信用分配难点,并界定与 GRPO 的适用范围
核心知识点详解
  • 稀疏奖励是最大难点:Agent 任务常只有最终成功/失败一个信号,中间千百步动作没有奖励。对比单轮 RLVR 的「立即对错」,Agentic RL 的反馈是稀疏的。
  • 信用分配:整条轨迹只有末端奖励时,难以知道是「哪一步决策导致了失败」。需 GiGPO 的组中组两层优势(粗粒度步骤级 + 细粒度 token 级)做多级归因。
  • rollout 成本 10–100×:每步动作要调外部工具/环境,一条轨迹的 rollout 代价比单轮文本生成高 10–100×,因此样本效率与复用很关键。
  • 与 GRPO 的边界:本阶段的 GRPO 用可验证单轮奖励;Agentic RL 是多步稀疏奖励的进阶话题,明确「不做」以界定项目范围。常见坑:把 GRPO 直接套多步 Agent 环境,粒子稀疏、差分不明显,策略几乎不更新。
学习路径

4.1 RLVR 与 GRPO 家族

RLVR(Reinforcement Learning with Verifiable Rewards)是 2025–2026 年最重要的方法论转变:当奖励可以被程序验证时(数学答案是否正确、代码是否通过单测、格式是否合规、工具调用是否成功),就不需要奖励模型,也就没有奖励黑客。这使 RL 训练变得可规模化、可复现。

算法一句话定位修的问题
GRPO组内相对比较,去掉 CriticPPO 显存开销大;天然适配可验证奖励
DAPOClip-Higher + 动态采样 + Token 级损失 + 超长惩罚熵崩塌;全对/全错的无效样本浪费算力;长度偏差
GSPO重要性比值从 token 级提升到序列级长序列噪声累积;MoE 需额外补丁
GMPO用几何平均替代算术平均异常 token 主导梯度(有界性可证)
GFPO多采样后按最短/最高效过滤RL 后模型越写越长但没更准
CISPO只裁剪权重不裁剪 token反思类低概率词(wait / recheck)被裁掉
VAPO把价值模型请回来做精细信用分配长 CoT 场景下无 Critic 的局限
python# GRPO 的训练循环骨架:理解 "组内采样 → 相对优势 → 加权策略梯度"
import torch

def grpo_step(policy, ref_policy, tokenizer, prompts, reward_fn,
              group_size=8, beta=0.04, clip=0.2):
    total_loss = 0.0
    for prompt in prompts:
        # 1) 同一个 prompt 采样一组答案 —— 组内相对比较的基础
        with torch.no_grad():
            completions = [policy.generate(prompt) for _ in range(group_size)]
            rewards = torch.tensor([reward_fn(prompt, c) for c in completions], dtype=torch.float)

        if rewards.std() < 1e-6:          # 全对或全错:没有学习信号,跳过
            continue
        adv = (rewards - rewards.mean()) / (rewards.std() + 1e-4)   # 组相对优势

        for comp, a in zip(completions, adv):
            logp    = policy.logprobs(prompt, comp)
            logp_r  = ref_policy.logprobs(prompt, comp)
            ratio   = torch.exp(logp - logp.detach())
            unclip  = ratio * a
            clipped = torch.clamp(ratio, 1 - clip, 1 + clip) * a
            pg      = -torch.min(unclip, clipped).mean()
            kl      = (torch.exp(logp_r - logp) - (logp_r - logp) - 1).mean()  # 无偏 KL 估计
            total_loss += pg + beta * kl
    return total_loss / max(1, len(prompts))
✔
RL 训练必须盯住的三个曲线:① 奖励应稳步上升,若猛涨到接近满分要怀疑奖励被 hack;② 输出长度监控是否失控膨胀(GFPO 这类工作就是在治它);③ 策略熵是否过快崩塌——熵没了,模型就失去探索能力,训练会停滞。这三个曲线比 loss 更能反映真实状态。

GRPO 的正式目标函数:对每个 prompt 采样 G 个回答 {o_1 … o_G},用组内奖励估计优势 Â_i = (R_i − mean(R)) / (std(R) + ε);若整组奖励全同则跳过(无学习信号)。策略损失 L_GRPO = E_i[ −min( ρ_i·Â_i, clip(ρ_i, 1−ε, 1+ε)·Â_i ) ] + β·KL(π_θ ∥ π_ref),其中 ρ_i = π_θ(o_i)/π_ref(o_i) 是重要性比。关键点:没有 Critic,省下与 policy 同级的参数与显存,且优势来自组内相对比较,天然适配「答案对错」这类可验证奖励。

text# GRPO 目标(数学骨架,与第 4.1 节的代码一一对应)
# 对每个 prompt 采样 G 个 completion:
#   A_i = (R_i - mean(R)) / (std(R) + eps)        # 组相对优势
#   rho_i = pi_theta(o_i) / pi_ref(o_i)            # 重要性比
#   L_clip = -min( rho_i * A_i, clip(rho_i,1-e,1+e) * A_i )
#   L = mean_i L_clip  +  beta * KL(pi_theta || pi_ref)
# 无 Critic、无在线 RM:奖励 R_i 直接由可验证函数给出

GRPO 家族在修什么(2025–2026 主线):DAPO 用 Clip-Higher(正/负例用不同 clip 上限,给「答对」的答案更大探索空间)、Dynamic Sampling(丢弃全对/全错的 prompt 以剔除无效样本)、Token-level loss(按 token 归一而非按样本,防长样本主导梯度)、超长惩罚(抑制度膨胀);GSPO 把重要性比值从 token 级提升到序列级 π_seq=Π_t π_t,降低长序列的噪声累积,对 MoE 还需补丁;GMPO 用几何平均替代算术平均估计优势,异常 token 的影响有界、可证更稳;CISPO 只裁剪权重不裁剪 token,保留「重新检查 / recheck」这类低概率反思词(它们常被普通 clip 误杀)。

算法核心改法修的问题
GRPO组内相对优势,去 CriticPPO 显存与稳定性
DAPOClip-Higher + 动态采样 + token 级 + 超长惩罚熵崩塌 / 无效样本 / 长度偏置
GSPO序列级重要性比长序列噪声 / MoE 抖动
GMPO几何平均优势异常 token 主导梯度
CISPO只裁权重不裁 token反思词被误杀

DAPO 的两个关键改动(可直接跑的最小实现)

python# DAPO vs 原始 GRPO 的两个决定性改动
import torch

def grpo_adv(rewards, eps=1e-4):
    """原始 GRPO:组内标准化,全对/全错时 std≈0,优势被放大成噪声。"""
    return (rewards - rewards.mean()) / (rewards.std() + eps)

def dapo_adv_and_mask(rewards, group_size=8, eps=1e-4):
    """DAPO 动态采样:丢弃全对(1.0)/全错(0.0)的整组,只保留有区分度的组。
    预期:group_size=8 时,简单题常整组全对 -> 有效组可能只剩一半。"""
    acc = rewards.mean().item()
    if acc >= 0.999 or acc <= 0.001:      # 无学习信号,整组丢弃
        return None, torch.zeros_like(rewards)
    std = rewards.std()
    # 动态采样:丢弃标准差过小的组(近似无效),而非仅做标准化
    keep = (std > 0.05).float()
    adv = (rewards - rewards.mean()) / (std + eps) * keep
    return adv, keep

def dapo_clip_higher(ratio, adv, eps_low=0.2, eps_high=0.28):
    """Clip-Higher:正优势(答对)用更宽松的上界 eps_high,防止低概率正确 token 被过早裁掉。
    这是 DAPO 治熵崩塌的核心:常规 PPO 正负都用 0.2,会压制探索。"""
    lo = 1.0 - eps_low
    hi = 1.0 + (eps_high if adv >= 0 else eps_low)   # 正优势放宽上界
    return -torch.min(ratio * adv, torch.clamp(ratio, lo, hi) * adv)

# 预期:把 eps_high 从 0.2 调到 0.28,策略熵下降速度明显变慢,
# 训练后期 pass@1 仍能爬升(不调则 300 步后熵塌、奖励停滞)。
DAPO 改动原始 GRPODAPO效果
裁剪切分正负都用 ε=0.2Clip-Higher:正 ε_high=0.28缓解熵崩塌,保探索
样本筛选全对/全错也参与(优势≈噪声)动态采样直接丢弃全同组同等算力下梯度更有效
损失归一按样本平均(长样本主导)Token-level:按 token 总数归一长 CoT 不被惩罚
长度控制无超长软惩罚 + 长度奖励塑形抑制无意义的长度膨胀
⚠
熵崩塌是 RLVR 最常见的死亡方式:当 clip 把所有正优势的更新都压在上界内,低概率的正确 token(往往就是探索发生的时刻)比率被反复压回,几轮后策略熵单调下降,模型不再「试新路」,奖励曲线在高位停滞。判据:训练 200–500 步内策略熵(对采样 token 的平均熵)下降超过 50% 且奖励未同步上升,就应怀疑熵崩塌,优先检查 clip 上界、KL 系数 β 与学习率。

经验取值:GRPO/DAPO 的 group_size 常取 8–16(太小优势估计噪声大,太大 rollout 成本线性膨胀);KL 系数 β 在纯 RLVR 场景常设 0–0.04(可验证奖励下过度锚定 reference 反而限制提升,DeepSeek/ Qwen 系列多用极小或无 KL);clip 区间 ε 常规 0.2,DAPO 正例上界抬到 0.28 左右;学习率通常比 SFT 小一个量级(1e-6 ~ 5e-7)。

4.2 Agentic RL:2026 的新战场

单轮做题的红利已经吃尽,所有实验室的火力都转向了多轮工具调用、长程规划的 Agent RL。它带来三个新难题:

奖励更稀疏
整条几十步的轨迹只在一个最终结果上给奖励,中间步骤完全没有信号。
信用更难分配
最终成功(或失败)应该归功于哪一步?哪些工具调用是有效的?
rollout 更烧钱
每一步都要真实执行工具(检索、代码、浏览器),采样成本比纯文本生成高得多。
方法核心思路效果
ARPO只在工具返回那一刻(token 熵骤增的决策分叉点)分支采样token 消耗大降,成功率大升
Tree-GRPO把树搜索搬进 RL,共享前缀让同预算下 rollout 数翻倍同时免费获得步级过程监督信号
GiGPO组中组:轨迹级 + 步级两层优势ALFWorld 提升 12%
CW-GRPO用 LLM Judge 给每轮检索打「贡献分」再重缩放优势搜索类 Agent 显著提升
AT-GRPO多智能体系统按角色 / 轮次分组长程规划任务大幅提升
回归 Critic不等长子轨迹无法组内公平对比,改回 Critic 做 token 级优势GLM-5.2 在长程阶段的选择
★
2026 年最值得玩味的技术判断:「GRPO 家族 + 可验证奖励」的共识,正在长程 Agentic 场景松动。2026 年的 RL 版图正在裂变为双轨制:短推理用 GRPO 系,长 Agent 回归 Critic 系。原因是当一条几十步的轨迹被压缩成不等长的子轨迹后,GRPO 的「组内可比」假设失效——只有 Critic 能对单条轨迹做 token 级优势估计。能讲清这个判断,说明你真的读懂了这一层。

GiGPO 的两层优势:组中组怎么算

python# GiGPO 核心:轨迹级(ho) + 步级(hi) 两层优势,解决 Agent 稀疏奖励
import torch

def gigpo_advantages(traj_rewards, step_rewards, eps=1e-4):
    """traj_rewards: [G] 同一任务 G 条完整轨迹的最终奖励。
    step_rewards: [G, T] 每条轨迹每个「锚定状态」的即时奖励。
    思路:把重复出现的状态(状态指纹相同)归为同一「步组」,在步组内做相对比较。"""
    # ---- 第一层:轨迹级优势(宏观)----
    a_traj = (traj_rewards - traj_rewards.mean()) / (traj_rewards.std() + eps)

    # ---- 第二层:步级优势(微观)----
    # 把 (状态指纹) 相同的步聚成一个步组,组内标准化
    groups = {}
    for g in range(step_rewards.shape[0]):
        for t in range(step_rewards.shape[1]):
            key = round(float(step_rewards[g, t]), 6)   # 实际用状态 embedding 指纹
            groups.setdefault(key, []).append((g, t))
    a_step = torch.zeros_like(step_rewards)
    for key, idxs in groups.items():
        vals = torch.tensor([step_rewards[g, t] for g, t in idxs])
        if vals.std() < 1e-6 or len(vals) < 2:
            continue
        norm = (vals - vals.mean()) / (vals.std() + eps)
        for (g, t), v in zip(idxs, norm):
            a_step[g, t] = v

    # ---- 合并:宏观 + 微观 ----
    total = a_traj.unsqueeze(1) + a_step
    return a_traj, a_step, total

# 预期:ALFWorld(文本家务任务)上 GiGPO 相对纯轨迹级 GRPO 提升约 12%,
# 因为「打开冰箱」这类重复状态能在步组内获得稳定信号,缓解稀疏奖励。
⚠
Agentic RL 的真成本在 rollout,不在训练:Agent RL 的瓶颈不是 GPU 前向,而是工具调用与环境执行:一次 rollout 可能触发几十次检索 / 代码执行 / 浏览器操作,单条轨迹的墙钟成本可达纯文本生成的 10–100 倍。因此 2026 年的工程重点变成:把 rollout 做成可并行、可缓存、可重放的服务(Gym 式环境池 + 结果缓存),并优先用 ARPO「只在决策分叉点分支」这类省 token 的方法。判断一个 Agent RL 配方是否实用,先看它的 rollout 吞吐,而不是看 loss 曲线。
★
4.3 动手练习与自测:这一章是 2026 面试的「分水岭」:能推导 GRPO、能说清 DAPO 每个改动的动机,才算过关。
  1. 推导组相对优势:为什么用 Â_i=(R_i−mean)/std 而非直接用 R_i?判据:能说明它等价于「基线减方差」且无需 Critic,并指出全同组时 std→0 必须跳过。
  2. 实现 Clip-Higher:写出正负优势使用不同上界的分支逻辑,并解释为什么只放宽「正优势」的上界而非下界。判据:代码正确 + 指出目的是保护低概率正确 token、缓解熵崩塌。
  3. 诊断熵崩塌:给定「奖励 300 步后停滞、平均熵从 1.8 掉到 0.6」,列出至少 3 个要排查的超参并说明各自机制。判据:命中 clip 上界 / β(KL)/ 学习率 / 温度中至少 3 个且有因果。
  4. 算 rollout 成本:group_size=8、每 prompt 平均生成 2k token、Agent 任务每轨迹触发 10 次工具调用,估算相对纯文本生成的墙钟倍数。判据:能识别工具执行是主项而非 token 生成。
  5. 选算法:同一任务改用 MoE 骨干 + 超长 CoT,为什么 GSPO 比 token 级 GRPO 更合适?判据:说出序列级重要性比降低长序列噪声累积、并提到 MoE 需额外稳定性补丁。

5. 蒸馏与合成数据

知识结构图 · 蒸馏与合成数据
蒸馏与合成数据3 大知识域 · 15 个知识点
蒸馏方式黑盒数据蒸馏白盒 logits 蒸馏 KLon-policy 蒸馏强到弱多级蒸馏推理轨迹蒸馏
学习路径
  1. 读 5.1:区分黑盒/白盒/on-policy/强到弱/推理轨迹蒸馏的做法与适用
  2. 实现 onpolicy_kd_loss,用温度 2.0 软标签 + 拒绝过滤跑一轮
  3. 对接 M9:用 on-policy + 拒绝采样构造领域 SFT 数据,控制模型坍塌与污染
✔ 能实现蒸馏损失并用拒绝采样生成数据,说清各蒸馏方式的适用边界
核心知识点详解
  • 黑盒 vs 白盒蒸馏:黑盒只用强模型输出(含思维链)当数据;白盒用 logits KL 对齐学生与教师分布 loss=KL(teacher_student),能访问权重时效果更好。
  • on-policy 蒸馏是 2026 主流:让学生自己采样,教师为输出打分/纠错,天然缓解训练/推理分布偏移,是最贴近部署设置的蒸馏。
  • 软标签温度 T=2.0:soft = softmax(teacher_logits / T),更高的 T 让分布更平、信息更足;配合拒绝过滤弱样本。F.kl_div(log(soft), soft, reduce sum)。
  • 强到弱多级与轨迹蒸馏:强模型指导中等再指导小模型,逐级缩小差距;轨迹蒸馏把解题思维链数据直接当 SFT 训练。常见坑:直接把老师硬标签当学生标签,损失软标签信息且没做许可/污染检查。
合成数据陷阱与对策模型坍塌错误放大污染评测真实数据混合每轮去重过滤
学习路径
  1. 读 5.1:背下合成数据三陷阱(模型坍塌/错误放大/污染评测)与对策
  2. 做一轮合成数据并用真实数据混合,量化每轮的多样性变化
  3. 对接 M9:在 SFT 数据构造里每轮去重过滤并用独立评测集验证
✔ 能识别并缓解模型坍塌/错误放大/污染,配合独立评测验证
核心知识点详解
  • 三陷阱:① 模型坍塌:用模型自己的输出训练让自己分布越来越窄(复用塌缩);② 错误放大:老师的小错在蒸馏中放大成系统性错;③ 污染评测:合成数据漏进了评测基准。
  • 对策:真实数据混合 alpha=0.7:保持与真实数据按比例混合(x_total = α·real + (1−α)·synth,α 常用 0.7),抑制坍塌的分布漂移。
  • 每轮去重过滤:每轮生成后做去重与质量过滤,只保留多样性合格的新样本,避免重复样本主导分布。
  • 独立评测验证:用训练外的独立评测集(含污染检查)衡量合成数据占比对下游指标的影响。常见坑:评测集与合成数据同源生成,测出来的「提升」是假象。
拒绝采样与温度拒绝采样通过率 20–40%温度 T=2.0 软标签alpha=0.7 混合独立评测集验证
学习路径
  1. 读 5.1:记住拒绝采样通过率 20–40%、温度 2.0 软标签、alpha=0.7 混合
  2. 跑 on-policy 蒸馏 + 拒绝采样,记录通过率与混合系数对下游指标的敏感
  3. 完成本章自测:说明拒绝滤波为何降低弱样本对合成的噪声污染
✔ 能设好拒绝采样与温度/alpha 参数,并用独立评测集验证合成数据质量
核心知识点详解
  • 拒绝采样通过率 20–40%:让强模型生成候选,用规则/评分过滤,只保留通过率约 20–40% 的高质量输出。通过率过高说明没在筛、过低浪费算力。
  • 温度 T=2.0 + alpha=0.7:蒸馏软标签温度 2.0 提供更平滑的分布先验;真实/合成混合 alpha=0.7 保持分布稳定。soft_logits = softmax(logits/T)。
  • 拒绝滤波为何能降噪:删掉错解与低质解,等价于用「更干净的标签」训练,弱候选不再污染梯度与最终分布。
  • 独立评测收尾:合成数据的好坏以训练外评测集为准,不看训练 PPL。常见坑:只看通过率或自评指标,不回归到真实评测,参数调了半天无实际收益。
学习路径

5.1 把大模型的能力迁移到小模型

方式做法适用
黑盒 / 数据蒸馏用强模型的输出(含思维链)作为训练数据无法访问权重时唯一选择;要注意许可条款
白盒 logits 蒸馏对齐教师与学生的输出分布(KL),含 top-k logits可访问权重时效果更好
on-policy 蒸馏让学生自己采样,教师为其输出打分/纠错2026 年主流,能缓解分布偏移
强到弱蒸馏用最强模型指导中等模型,再指导小模型多级蒸馏,常见于开源模型训练配方
推理轨迹蒸馏只蒸馏思维链与解题过程,而非最终答案把推理能力迁移到小模型的关键
⚠
合成数据的三个陷阱:① 模型坍塌:反复用模型自身输出训练会导致分布收窄、多样性下降;② 错误放大:教师的错误被学生当成真理学走;③ 污染评测:合成数据里混入了评测集内容。对策:每轮合成都要过滤、去重、与真实数据混合、并用独立评测集验证。

on-policy 蒸馏 + 拒绝采样(2026 主流配方)

python# on-policy 蒸馏:学生先自己采样,再用教师对「学生自己的输出」打分/纠错
# 关键区别:不是让学生模仿教师的输出,而是让学生在自己的分布上被教师纠正
import torch, torch.nn.functional as F

def onpolicy_kd_loss(student_logits, teacher_logits, student_ids,
                     temperature=2.0, alpha=0.7):
    """白盒 logits 蒸馏损失(仅对 top-k 教师分布,省显存)。
    student/teacher_logits: [B, V];student_ids: [B] 真实/采样 token。"""
    # 1) 软标签:教师分布(温度平滑,保留「暗知识」)
    t_soft = F.softmax(teacher_logits / temperature, dim=-1)
    s_log  = F.log_softmax(student_logits / temperature, dim=-1)
    kd = F.kl_div(s_log, t_soft, reduction='batchmean') * (temperature ** 2)

    # 2) 硬标签:学生自己采样的 token(on-policy 的分布对齐)
    ce = F.cross_entropy(student_logits, student_ids)
    return alpha * kd + (1 - alpha) * ce

# 拒绝采样(rejection sampling)过滤:只保留教师给出「高分」的学生轨迹作为 SFT 数据
def rejection_filter(answers, judge_fn, threshold=1.0, max_keep_ratio=0.4):
    kept = [a for a in answers if judge_fn(a) >= threshold]
    # 经验:单轮通过率 20%-40% 时数据质量最好;>80% 说明任务太简单、无区分度
    return kept

# 预期输出:alpha=0.7、T=2.0 常在推理类任务上比纯 CE 高 2-5 个点;
# T 取 1 会退化成硬标签蒸馏,T>4 会让分布过平、学生学到噪声。
蒸馏方法教师信号显存/成本2026 适用场景
数据蒸馏(黑盒)仅文本输出 + CoT最低(只需 API)无法拿权重;跨厂商迁移
logits 蒸馏(白盒)完整/top-k 输出分布高(需同时驻留两模型)同家族强→弱,效果最好
on-policy 蒸馏教师对学生采样的打分高(要 rollout)主流;缓解分布偏移
拒绝采样 + SFT教师对采样的二值/打分过滤中(一次前向)把 RL 能力固化回 SFT,省 RL 算力
强→弱多级逐级教师高开源模型训练配方(如把 671B 能力下沉)

2026 的真实做法:头部开源模型常采用「on-policy 蒸馏 + 拒绝采样」的混合配方——先让基座对海量 prompt 采样多条回答,用最强教师(或规则验证器)打分,只保留高质量轨迹做 SFT,再偏 RL 精调。DeepSeek-V3/R1 系列公开的配方里,长 CoT 数据的生成与筛选就属于这一类。关键工程点:拒绝采样的通过率要控制在 20%–40%,过高说明题目太易、过低说明太难,都会浪费算力而不长本领。

★
5.2 动手练习与自测:蒸馏的核心不是「抄答案」,而是「在学生的分布上纠错」。
  1. 区分两种蒸馏:写清楚 off-policy(模仿教师输出)与 on-policy(学生采样后教师打分)在分布偏移上的差别。判据:能指出 off-policy 训练/推理分布不一致,on-policy 缓解它但要额外 rollout。
  2. 调温度:白盒 KD 中 T 从 1 调到 4,学生会学到什么变化?判据:T 越大分布越平、越保留暗知识但也越易学噪声;T=1 退化为硬标签。
  3. 设通过率:拒绝采样通过率 95% 和 5% 分别说明什么?判据:95% 任务太易无区分度、5% 太难信号稀疏,都该调整难度分布。
  4. 防模型坍塌:设计一个最小流程避免「自训练坍塌」。判据:真实数据混入 + 每轮去重过滤 + 独立评测 + 保留人类/强模型锚点。
  5. 估成本:白盒 logits 蒸馏为何显存贵?给出理由。判据:教师与学生需同时驻留、要保存全词表 logits(可用 top-k 近似降显存)。

6. 训练基建与故障处理

知识结构图 · 训练基建与故障处理
训练基建与故障处理3 大知识域 · 16 个知识点
容错与监控torchrun --resumeckpt_every 200 / keep_last 3NCCL_DEBUG 定位dcgm-exporter + Prometheusexpandable_segments
学习路径
  1. 读 6.1:配 torchrun --resume、ckpt_every/keep_last、NCCL_DEBUG、dcgm/Prometheus、expandable_segments
  2. 跑一次带监控与断点重训的长训练,验证 --resume 与 ckpt 保留策略
  3. 对接 M9:复用 M7 管线跑 SFT/DPO/GRPO 时含容错监控与回滚预案
✔ 能配置弹性容错并让监控告警生效,中断后可精确续训
核心知识点详解
  • torchrun --resume + ckpt 策略:torchrun --resume 从最近 checkpoint 续训;--ckpt_every 200 --keep_last 3 每 200 步存一份、只留最近 3 份,控制磁盘与恢复精度。
  • 先起监控再谈训练:NCCL_DEBUG=INFO 定位通信;dcgm-exporter + Prometheus 采集 GPU 利用/温度/显存,配告警规则。监控不启动就跑步等于「盲训」。
  • expandable_segments 治显存碎片:PyTorch 设 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True 减少重复 alloc 的碎片开销,长训更稳。
  • 断点续训的成品标准:中断后重启,loss 曲线从断点无跳变地接上,而不是从头再来。常见坑:resume 时忘了对齐随机状态/优化器 state,续训出现 loss 断层。
故障处理Loss spike 回滚NCCL 卡死显存 OOM 三连数据饿死 GPU某个 rank 慢
学习路径
  1. 读 6.1:记下五种故障的现象与处理(loss spike/回滚、NCCL 卡死、OOM、数据饿死、rank 慢)
  2. 完成本章自测:给出应对五类故障的具体处置步骤
✔ 能对五类训练故障给出定位与处置,含 loss spike 的回滚与数据瓶颈修复
核心知识点详解
  • Loss spike → 回滚 + 降 lr:loss 突然尖峰上涨,立即回滚到上一个稳定 checkpoint,并把 lr 降约 50% 再继续,别硬扛。
  • NCCL 卡死 / OOM / 数据饿死 / rank 慢:卡死用 NCCL_DEBUG 定位卡在哪个集合通信;OOM 查激活/梯度并降 batch 或用激活重算;饿死查 torch.utils.data.DataLoader 的 num_workers;rank 慢查是否有 straggler 拖慢 all-reduce。
  • OOM 三连排查顺序:先压 batch → 开 gradient checkpointing(activation_offload)→ 再压序列长,逐级试,别一次性全改无法判断哪个生效。
  • 数据瓶颈的量化:GPU 利用率低而 num_workers/IO 打满,多为数据管线慢;加预取与 worker、落内存或换磁盘。常见坑:五类并发出现时只盯 loss,丢掉了 CPU/GPU 利用率这些定位信号。
SpikeGuard滑动中位数 3× 判 spike冷却 200–500 步回滚 + lr 降 50%
学习路径
  1. 读 6.1:理解 SpikeGuard 用滑动中位数 3× 判 spike、冷却 200–500 步、回滚 + lr 降 50%
  2. 实现并被注入一个 loss spike,验证其自动检测与回滚行为
  3. 对接 M9:长训练里启用 SpikeGuard 并记录一次自动回滚案例
✔ 能实现 spike 自动检测并验证回滚+降 lr,减少人工盯盘
核心知识点详解
  • 滑动中位数 3× 判 spike:用滑动中位数建立基线,当前 loss 超过 median×3(或偏离多个 MAD)即判 spike,避免误判正常抖动。
  • 冷却 200–500 步 + 回滚 + lr 降 50%:命中后进入冷却(200–500 步不重复触发),回滚 checkpoint 并把 lr 降 50% 减缓恢复,防止同一振荡反复。
  • 实现即注入验证:在训练里人为注入一个 loss spike,assert detector 触发 → rollback 生效,让机制可测而不仅是「写了」。
  • 自动化后的注意:自动回滚要落日志与告警,保留完整轨迹供事后复盘,别让黑盒自动改训练。常见坑:阈值设太低频繁误回滚,实际是在退化而非保护。
学习路径

6.1 让长周期训练活下来

bash# 一次大规模训练的必备工程配置(清单式)
# 1) 弹性与容错
torchrun --nnodes=32 --nproc_per_node=8 \
  train.py --resume --ckpt_every 200 --keep_last 3

# 2) 通信与显存
#   export NCCL_IB_DISABLE=0
#   export NCCL_DEBUG=WARN            # 通信卡住时改成 INFO 定位
#   export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

# 3) 监控(缺失等于盲飞)
#   nvidia-smi dmon -s pucvmet -d 5    # 功耗/利用率/显存/温度
#   wandb 记录 loss / grad_norm / lr / tokens_per_sec / mfu
#   dcgm-exporter + Prometheus 做集群级告警

# 4) 回滚预案
#   保留最近 N 个 checkpoint + 记录每个 ckpt 对应的数据与配置版本
#   检测到 loss spike(如 > 3x 中位数)自动回滚并降低 lr
故障现象处理
Loss spikeloss 突然跳到数倍然后不降回滚到 spike 前的 checkpoint,跳过这批数据,降低 lr 或加裁剪
NCCL 卡死训练无输出、GPU 利用率 0看 NCCL_DEBUG 日志定位;检查网卡 / IB / 拓扑;超时重启
显存 OOM偶发 OOM降 micro-batch + 增梯度累积;开梯度检查点;检查碎片(expandable_segments)
数据加载饿死 GPUGPU 利用率抖动、吞吐骤降增加 DataLoader workers、预取、本地缓存、减少 CPU 预处理
某个 rank 慢整体吞吐被拖慢检查硬件故障、数据分片不均、专家路由不均

SpikeGuard:loss spike 的自动检测与回滚

python# 长周期训练最常见的事故是 loss spike。做法:滑动中位数 + 相对跳变阈值 + 自动回滚
import collections, statistics

class SpikeGuard:
    def __init__(self, win=200, ratio=3.0, cooldown=300):
        self.hist = collections.deque(maxlen=win)   # 只保留最近 window 步
        self.ratio = ratio        # loss > ratio * 中位数 判为 spike
        self.cooldown = cooldown  # 触发后跳过 N 步,避免反复震荡
        self.skip = 0

    def step(self, loss, global_step):
        if self.skip > 0:
            self.skip -= 1
            return 'skip'                       # 跳过异常数据,不再用这批更新
        if len(self.hist) >= 50:                # 样本足够才判
            med = statistics.median(self.hist)
            if loss > self.ratio * med:         # 经验阈值:3x 中位数
                self.skip = self.cooldown
                return 'rollback'               # 回滚到 spike 前 ckpt 并降 lr
        self.hist.append(loss)
        return 'ok'

# 经验数字:bf16 大模型训练,loss spike 多发生在 warmup 结束前后与
# 学习率较高阶段;阈值取 3x 中位数、冷却 200-500 步可覆盖多数情况。
# 更稳的做法:spike 回滚同时把 lr 临时降 50%,并在后续若干步缓慢恢复。
⚠
让长周期训练活下来的四个必备件:① 周期性 checkpoint(每 100–500 步,保留最近 3 个)——没有 ckpt 就无法回滚;② loss spike 自动检测 + 回滚(否则一次异常数据可能毁掉几天训练);③ 可复现的数据/配置版本号(每个 ckpt 必须能回答「用的哪批数据、什么超参」);④ 全链路监控(loss / grad_norm / lr / tokens/s / MFU / GPU 温度)。大模型训练的失败大多是工程问题而非算法问题,这四件套的完备度直接决定你能训多大的模型。
★
6.2 动手练习与自测:这一章考的是「事故处理直觉」:听到现象要能立刻说出排查顺序。
  1. 故障排序:训练中途 GPU 利用率掉到 0、日志无输出,你的前 3 步排查是什么?判据:NCCL_DEBUG 日志 → 网卡/IB/拓扑 → 超时重启进程。
  2. 写回滚逻辑:loss 从 2.1 跳到 7.5 后不降,给出处理流程。判据:回滚到 spike 前 ckpt + 跳过该批数据 + 降 lr/加梯度裁剪 + 冷却若干步。
  3. 算吞吐:8xH100、micro-batch=4、seq=8k、grad_accum=16,估算全局 batch 的 token 数。判据:4×16×8000×8 = 4,096,000 tokens/step(记入 activation/通信开销前)。
  4. 判断 MFU:若实测 200 TFLOPs/s/卡而 H100 峰值约 990 TFLOPs/s(bf16),MFU 是多少?判据:≈20%,对 MoE/长序列属正常偏低,应查通信与长序列 attention 开销。
  5. OOM 三连:偶发 OOM 的三个优先手段。判据:降 micro-batch 增累积 / 开梯度检查点 / 处理显存碎片(expandable_segments)。

7. 分词:BPE、BBPE 与词表规模权衡

知识结构图 · 分词
分词3 大知识域 · 16 个知识点
分词算法BPE 合并最高频对BBPE 256 字节无 UNKWordPieceSentencePiece + fallback压缩率 3.6 vs 4.5 字符/token
学习路径
  1. 读 7.1:理解 BPE 合并最高频对、BBPE 256 字节无 UNK、SentencePiece + fallback 与压缩率
  2. 用手写极简 BPE 对一小语料跑两次合并,画出词表增长过程
  3. 完成本章自测:手推 BPE 前两次合并并比较字符/token 压缩率
✔ 能手推 BPE 合并流程并说清 BBPE/SentencePiece 在覆盖率与 UNK 上的差别
核心知识点详解
  • BPE 合并最高频对:从字符/字节词表出发,反复统计相邻 token 对频次,把最频繁的一对 merge 成新 token,直到达到目标词表大小。复杂度由 get_pairs + 计数器控制。
  • BBPE 用 256 字节、无 UNK:Byte-level BPE 以字节为基元,任何输入都能编码,没有 UNK token;与 Unicode 无关,多语言全覆盖。tiktoken 即其实现。
  • SentencePiece + fallback:SentencePiece 把空格也当字符处理(可逆),配合字节 fallback 处理稀有 token。WordPiece 用贪心最长匹配词表来做切分。
  • 压缩率 3.6 vs 4.5 字符/token:英文约 3.6 字符/token,中文等表意文约 4.5。常见坑:手推 BPE 时忘了「每次合并后重新统计频次」,得到错误的下一次 merge。
词表规模权衡大词表省算力embedding V×d 体量纯英文 32k–64k多语 100k–200k数字逐位切分坑AST 代码分词
学习路径
  1. 读 7.2:理解大词表省算力、embedding V×d、纯英文 32k–64k、多语 100k–200k、数字/AST 分词技巧
  2. 对英文/多语/代码文本各做一次分词统计,对比压缩率与词表影响
  3. 完成本章自测:算 token 减 20% 对算力的影响与 V=150k 的 embedding 体量
✔ 能权衡词表大小与 embedding 成本,并避开数字逐位切分的坑
核心知识点详解
  • 大词表省算力:同样语料、更大的词表 → token 数更少 → 序列更短 → 训练与注意力成本更低。但 embedding V×d 与 softmax 层会变大。
  • 量级经验值:纯英文 32k–64k;多语 100k–200k。embedding 参数量 = V×d,V=150k、d=4096 时 ≈ 614M 参数,占相当比例。
  • 数字逐位切分的坑:把「2026」切成单个数字 token 会让模型难以学到数字的数值结构,电话号/日期最好聚成一个 token 或用规则 preprocess。AST 代码分词按语法保留结构。
  • token 减 20% 对算力的影响:序列/注意力成本 ≈ token 数二次方相关,token 减 20%(如 5→4)显存与 FLOPs 明显下降,可量化「压缩率≈成本」。常见坑:为了省 token 盲目追求超大词表,embedding 内存与 softmax 开销反而拖垮小模型。
动手自测要点手推 BPE 前两次合并token 减 20% 算力降 36%V=150k 约 614M 参数
学习路径
  1. 完成本章自测:手推 BPE 合并、算 token 减 20% 的算力降幅与 V=150k 的 embedding 参数
✔ 自测命中判据,分词原理与词表权衡能独立推算
核心知识点详解
  • 手推 BPE 前两次合并:对一小语料数频次,第一次合并最高频字符对,第二次在更新后的序列上再数——两步都要写出来才算会。
  • token 减 20% 算力降 36%:成本 ∝ token² 近似:0.8²=0.64,即降 36%。这是「压缩率↔算力」的快速换算。
  • V=150k 约 614M 参数:150000×4096 = 6.144e8 ≈ 614M,embedding 只看 V×d,可直接秒算。
学习路径

7.1 BPE / BBPE / SentencePiece 算法

分词是「文本 → 整数 id」的第一道关卡,它直接决定了模型能「看见」的最小语义单元。主流算法是 BPE(Byte-Pair Encoding):从字符(或字节)词汇表出发,反复统计相邻 token 对的出现频次,把最频繁的一对合并成新 token,直到达到目标词表大小。GPT-2/3/4、LLaMA、Qwen、DeepSeek 都基于 BPE 的变体。

python# 极简 BPE 训练(教学用,真实实现见 tokenizers / sentencepiece)
def get_pairs(word):
    return set(zip(word[:-1], word[1:]))

def bpe_train(corpus, vocab_size=1000):
    # 1) 预分词到词,再拆成字符序列
    words = [list(w) for w in " ".join(corpus).split()]
    vocab = {tuple(w): 1 for w in words}          # 初始词表 = 字符
    while len(vocab) < vocab_size:
        pairs = {}
        for w in words:                            # 2) 统计所有相邻对
            for p in get_pairs(w):
                pairs[p] = pairs.get(p, 0) + 1
        best = max(pairs, key=pairs.get)           # 3) 取最频繁的一对
        nw = []
        i = 0
        while i < len(words[0]) if False else True:  # 占位,下面真正合并
            break
        words = [merge(w, best) for w in words]    # 4) 合并
        vocab[tuple(best)] = 1
    return vocab

def merge(word, pair):
    out, i = [], 0
    while i < len(word):
        if i < len(word)-1 and (word[i], word[i+1]) == pair:
            out.append(word[i]+word[i+1]); i += 2
        else:
            out.append(word[i]); i += 1
    return out

BBPE(Byte-Level BPE) 把基础符号从「字符」换成「256 个字节」,于是任何文本(含罕见字、emoji、代码)都能被无损表示,永远不会出现 UNK。GPT 系列与 LLaMA 用 BBPE。SentencePiece 则把原始文本当作一个整体(不依赖空格预切分),学习 BPE 或 Unigram 子词,并支持 byte-fallback,是多语言模型(T5、早期 LLaMA、多语种 Qwen)的常见选择。三者核心差异在于「预分词方式」与「是否空格敏感」,对最终效果影响小于词表大小与训练数据。

方案基础符号UNK 风险代表
BPE(字符级)字符有(未登录字符)早期 GPT-2 小词表
BBPE字节(256)无GPT-3/4、LLaMA、Qwen、DeepSeek
WordPiece子词有BERT、多语种 BERT
SentencePiece(BPE/Unigram)字符/字节低(含 fallback)T5、LLaMA、多语言模型

量化词表质量:压缩率(字符/token)

python# 比较不同 tokenizer 的压缩率:token 数越少,同样上下文窗口装的信息越多
# enc 换成你有权使用的 encode 函数,如 tiktoken / transformers
def compression_report(texts, tokenizers):
    rows = []
    for name, enc in tokenizers.items():
        tokens = sum(len(enc(t)) for t in texts)
        chars  = sum(len(t) for t in texts)
        rows.append((name, tokens, chars / tokens))   # (名字, token 总数, 字符/token)
    return rows

# 预期(同一段英文技术文本,字符/token 越高越好):
#   gpt2(50k 词表)   ~3.6
#   llama3(128k)     ~4.3
#   qwen(150k+)      ~4.5
# 中文差距更大:小词表 1 字常被切成 2-3 个 token,大词表可接近 1 token/字。
# 注意 attention 是 O(T^2),token 数少 20% => 注意力算力约省 36%。
✔
为什么压缩率不是越高越好:压缩率高(每 token 覆盖更多字符)能省算力与成本,但词表过大有代价:embedding 与 LM head 参数膨胀、长尾 token 训练不充分(出现次数太少,向量学不好)、softmax 计算变贵。所以大词表必须配足够大的训练语料,否则长尾 token 反而拖累。经验做法:多语言模型用 100k–200k,纯英文可用 32k–64k。

7.2 词表大小与数学 / 代码能力

词表大小是一组权衡:越大 → 每文档 token 数越少 → 注意力计算更省、长文档能塞更长上下文,但 embedding 表(V×d)与 LM head 更大;越小 → 压缩率低、token 多、成本高,但对低资源语言更友好。公开实践:英文为主的模型常用 32k(GPT-2)到 100k(GPT-4 约 100k);多语言模型普遍 100k–200k(Llama-3 128k、Qwen 系列约 150k+),用大词表换取非英语的压缩率。

词表典型压缩率(英文)多语言覆盖embedding 体量(d=4096)
32k~3.5–4 字符/token差131M
100k~4–4.5 字符/token中410M
200k~5+ 字符/token好820M

分词质量直接拖累数学与代码能力,原因有三:① 数字常被切成「逐位」token(如 12345 → 1/2/3/4/5 五个 token),跨多位做进位、比较的算术要在很长序列上完成,极易出错;② 代码里的稀有符号(括号、运算符、缩进)碎片化严重,结构信息被切碎;③ 不同分词会让同一道题的 token 序列完全不同,影响泛化。2026 年的改进包括:为数字引入专用 digit token、对代码做基于 AST 的分词、以及用更细粒度 tokenizer 提升符号保真度——这也是为什么「换 tokenizer 有时比换模型更重要」在数据敏感任务上成立。

词表规模的参数与推理成本换算

python# 词表规模的参数量代价 + 压缩率带来的成本差
d_model = 4096
for V in (32_000, 100_000, 200_000):
    tied   = V * d_model / 1e6              # embedding 与 LM head 共享(weight tying)
    untied = 2 * V * d_model / 1e6          # 不共享则翻倍
    print(f"V={V:>7}  tied={tied:6.1f}M  untied={untied:6.1f}M")

# 预期(d_model=4096):
#   V=32k  -> tied 131M   untied 262M
#   V=100k -> tied 410M   untied 819M
#   V=200k -> tied 819M   untied 1.64B   # 对 7B 模型占比已超 10% (tied) / 23% (untied)

# 成本换算:假设某文档 5 万字符
for cpt in (3.5, 4.5):                      # 字符/token
    print(f"{cpt} 字符/token -> {50000 / cpt:.0f} tokens/doc")
# 预期:3.5 -> 14286 tokens;4.5 -> 11111 tokens,相差约 22% 的推理成本。
★
数字 token 的坑:为什么大模型总算错进位:若数字被逐位切分(12345 → 1/2/3/4/5 五个 token),模型做多位数加法的进位、比较必须在「分散在 5 个 token 上」的信息间来回搬运,而每一步都要经过 attention——这就是早期大模型算术不稳的结构性原因。改进方向:为数字引入专用 digit token 或按数位对齐切分,让进位发生在局部相邻 token 上;代码则用基于 AST 的分词保留结构。一句话:分词粒度决定了模型「看见」数字的方式,进而决定它能否可靠地做算术。
⚠
微调的隐藏陷阱:若你的下游数据(如化学式、基因序列、专有代码)包含大量「训练 tokenizer 时从未见过」的字符组合,模型会把它炸成一大堆碎片 token,效果骤降。此时应重训或扩展 tokenizer 并把新 token 的 embedding 初始化好,而不是只调学习率。
★
7.3 动手练习与自测:分词是「看不见的手」:它同时决定算力、成本与数学/代码能力。
  1. 手推 BPE:语料为 "low lower lowest",初始字符词表,写出前 2 次合并的 token 对。判据:第一次合并最高频对(如 l+o),第二次基于新序列再统计,能说明「词内频次而非全局次数」。
  2. 算压缩率收益:token 数减少 20%,attention 算力与推理成本各降多少?判据:attention 约降 36%(O(T²)),线性部分(矩阵乘)降约 20%。
  3. 估 embedding 体量:V=150k、d=4096、weight tying,embedding 占多少参数?判据:约 150000×4096 ≈ 614M。
  4. 解释算术失败:为什么逐位切分损害多位数乘法?判据:进位信息被切散到多个 token,需跨 token 搬运,attention 难稳定对齐。
  5. 选词表:纯英文产品模型 vs 中英双语模型,词表该各取多大?判据:纯英文 32k–64k 足够;多语 100k–200k 换压缩率,但需配大语料喂饱长尾 token。

8. 参数高效微调:LoRA / QLoRA / DoRA

知识结构图 · 参数高效微调
参数高效微调3 大知识域 · 17 个知识点
LoRA 原理与超参ΔW = B·A 低秩参数量 r(d+k)r=16 仅 0.78%alpha/r 控制增量B 初始化 0 平滑起步lr 1e-4~3e-4merge 部署零开销
学习路径
  1. 读 8.1:理解 LoRA ΔW=B·A、参数量 r(d+k)、r=16 仅 0.78%、alpha/r、B 初始化 0、lr 1e-4~3e-4
  2. 实现 LoRALinear 并核验 r=16 时参数量压缩、跑 merge 与运行时叠加
  3. 对接 M9:用 LoRA 跑 SFT 记录显存与耗时,与全量对比确认降本
✔ 能实现 LoRA 并核验参数量与缩放,说明 merge 部署的零推理开销
核心知识点详解
  • ΔW = B·A 的低秩分解:冻结 W,学增量 h = Wx + (B·A)x,A∈R^{r×k}、B∈R^{d×r},r≪min(d,k)。参数从 d·k 降到 r(d+k)。d=k=4096 时 W 有 4096²≈16.78M 参,而 LoRA 仅 r·(d+k)=16×8192≈0.13M,约占 0.78%。
  • alpha/r 控制增量与 merge:缩放系数 scaling = alpha/r(实践取 alpha=2r)。训练后 W += B·A·scaling merge 回主权重,推理零额外开销。
  • B 初始化 0、A 随机,lr 1e-4~3e-4:B 置 0 让起点增量=0(不打断原权重),A 高斯随机。LoRA 常配 lr 1e-4~3e-4,比全量 1e-5~2e-5 高一两个数量级。
  • 部署:merge 与运行时叠加:运行时 x @ (W + B*A);部署前把 ΔW 并回主权重。常见坑:忘了乘 scaling 或 merge 时重复叠加,导致增量被放大/错位,推理结果漂移。
QLoRA 与 DoRA4-bit NF4 量化双重量化 0.37 bit分页优化器DoRA 幅度 + 方向解耦
学习路径
  1. 读 8.2:理解 QLoRA 的 4-bit NF4、双重量化、分页优化器与 DoRA 解耦幅度/方向
  2. 在单卡上用 QLoRA 微调一次,实测显存约 3.3 GB 与 LoRA 13 GB、全量 78 GB 的差距
  3. 对接 M9:用 QLoRA 把领域微调压进单卡,记录显存/质量权衡
✔ 能配好并跑通 QLoRA 微调,说出 NF4/双重量化/分页优化器为何省显存
核心知识点详解
  • 4-bit NF4 量化基座:主权重用 NF4(4-bit 归一化 float)量化驻留,前向时反量化参与计算。相比 bf16 权重省约 4× 显存,是 QLoRA 省显存的主因。
  • 双重量化到 0.37 bit:对量化常数再量化一遍,把 NF4 的有效位数压到约 0.37 bit/参数,进一步省显存。
  • 分页优化器治 OOM:优化器 state 不够时自动分页换出(CPU)、需要时换入,避免小显存 OOM,QLoRA 因此能在 24GB 卡上跑 7B/8B。
  • DoRA 把幅度与方向解耦:把权重分解成幅度与方向分别学习,比纯 LoRA 表达力更强。常见坑:量化基座在跨任务反复微调时精度衰减,基准差异超过阈值要重量化。
显存账本与选型7B 全量约 78 GBLoRA 约 13 GBQLoRA 约 3.3 GBFull FT vs LoRA 取舍
学习路径
  1. 读 8.2:背下 7B 全量约 78 GB、LoRA 约 13 GB、QLoRA 约 3.3 GB 的显存量级
  2. 估算 7B 全量 vs LoRA vs QLoRA 的显存账,确认节约来源
  3. 对接 M9:为选全量/LoRA/QLoRA 给出显存与质量取舍,写入微调配置
✔ 能手算 7B 三种微调的显存账并在资源约束下选对方案
核心知识点详解
  • 7B 三种量级的显存:全量约 78 GB、LoRA 约 13 GB、QLoRA 约 3.3 GB。全量需要多卡/大显存,LoRA 一张 16GB 勉强,QLoRA 单张 24GB 很轻松。
  • 显存构成:全量=权重+梯度+优化器 state+激活;LoRA 只存 0.78% 梯度与优化器、基座冻结仍要驻留权重;QLoRA 再把权重压到 NF4。节约来自「少存梯度/优化器 state + 量化权重」。
  • 全量 vs LoRA 取舍:LoRA 省显存省存储、抗遗忘、可热插拔多任务;全量更彻底但贵且易遗忘。质量通常 LoRA 达全量 90%+。
  • 那张卡选哪个:按可用显存选:>78GB(多卡)可全量;16–78GB 用 LoRA;<8GB 用 QLoRA。常见坑:以为 QLoRA 是「免费的 LoRA」,忽略量化精度损失与反量化的速度开销。
学习路径

8.1 LoRA:原理与超参

全量微调(Full FT)更新所有权重,显存与存储成本都高,且易遗忘。LoRA(Low-Rank Adaptation) 冻结原权重 W,只学习一个低秩增量 ΔW = B·A:前向变为 h = Wx + (B·A)x。其中 A∈R^{r×k}、B∈R^{d×r},r ≪ min(d,k)。参数从 d·k 降到 r·(d+k),当 d=k=4096、r=16 时仅约 0.8%,却常能达到全量微调 90%+ 的效果。

python# LoRA 的参数量与缩放
import torch, torch.nn as nn
d, k, r = 4096, 4096, 16
full = d * k                       # 16.78M
lora = r * (d + k)                 # 0.13M
print(f"full={full/1e6:.2f}M  lora={lora/1e6:.2f}M  压缩={lora/full:.2%}")

class LoRALinear(nn.Module):
    def __init__(self, in_f, out_f, r=16, alpha=32, drop=0.05):
        super().__init__()
        self.W = nn.Linear(in_f, out_f, bias=False)     # 冻结
        self.A = nn.Parameter(torch.zeros(r, in_f))
        self.B = nn.Parameter(torch.zeros(out_f, r))
        nn.init.kaiming_uniform_(self.A)
        self.scale = alpha / r                           # alpha/r 控制增量幅度
        self.drop = nn.Dropout(drop)
    def forward(self, x):
        return self.W(x) + self.drop(x @ self.A.T @ self.B.T) * self.scale
超参常用取值作用 / 取舍
rank r8 / 16 / 32 / 64越大容量越高;8–32 覆盖多数任务,64+ 用于难任务
alphar 的 1–2 倍(如 16/32)实际增量幅度 = alpha/r,过大会淹没原权重
dropout0.05–0.1防过拟合,数据少时更重要
target modulesq_proj,k_proj,v_proj,o_proj (+ gate/up/down)注意力投影必加;FFN 视情况
学习率1e-4 ~ 3e-4比全量微调大 1–2 个数量级

target modules 的选择:注意力里的 q/k/v/o 投影几乎必加;FFN 的 gate/up/down 投影对领域知识注入很有用,但会增加参数量与过拟合风险。经验法则是「先只加注意力投影,不够再加 FFN」。r 与 alpha 的关系由缩放 alpha/r 决定,调 r 时记得同步调 alpha 以保持有效增量幅度。

部署:把 LoRA 合并进原权重(零推理开销)

python# LoRA 的两种部署方式:运行时叠加(可热插拔) vs 离线合并(零额外延迟)
import torch

def merge_lora(W, A, B, alpha, r):
    """把 Delta W = (alpha/r) * B @ A 合并进原权重。
    W:[out,in]  A:[r,in]  B:[out,r];合并后推理与原模型完全一致、无额外延迟。"""
    delta = (alpha / r) * (B @ A)
    return W + delta

def add_lora(W, A, B, alpha, r, x):
    """运行时叠加:适合多任务热插拔(vLLM/SGLang 的多 LoRA 服务)。"""
    return x @ W.T + (alpha / r) * (x @ A.T @ B.T)

# 预期:merge 前后同一输入 logits 差异 < 1e-4(仅数值误差)。
# 取舍:merge 省推理开销但锁死单任务;未合并才能一个基座挂 N 个适配器来回切。
# 经验:适配器体积 = r*(d+k)*4字节;r=16,d=k=4096 时约 0.5MB/层,全模型常 <100MB,极便于分发。
✔
B 初始化为 0 的原因:LoRA 把 B 初始化为全 0、A 用随机初始化,于是训练开始时 ΔW = B·A = 0,模型从「等于原模型」的状态平滑起步,不会在第一步就把预训练权重破坏掉。若把 B 也随机初始化,训练初期增量会很大,常导致 loss 升高再下降(甚至发散)。这也是为什么 LoRA 能在高学习率下依然稳定。

8.2 QLoRA 与 DoRA:把微调压进单卡

QLoRA 让 65B 级模型能在单张 48GB 卡上微调:① 基座以 4-bit NF4 量化常驻显存(精度损失极小);② 双重量化(Double Quantization) 把量化所用的缩放因子再量化一次,省下约 0.37 bit/参数;③ 分页优化器(Paged Optimizer) 在显存峰值把优化器状态换页到 CPU,避免 OOM。LoRA 适配器仍以 16-bit 训练,梯度只回传适配器。

DoRA(Weight-Decomposed LoRA) 把权重分解为「幅度(magnitude)+ 方向(direction)」:幅度单独学习、方向用类 LoRA 的低秩更新并做归一化。相比普通 LoRA,DoRA 在同等参数量下更稳、更易收敛,尤其在低数据场景。它与 QLoRA 可叠加:4-bit 基座 + DoRA 适配器。

方法显存占用(相对)质量适用
Full FT最高(需存优化器状态)上限最高数据极多 / 需大幅改分布
LoRA (16bit 基座)中接近 Full FT单卡 24–80GB,最常见
QLoRA (4bit 基座)最低略低于 LoRA消费级 / 单卡大模型
DoRA≈ LoRA常优于 LoRA低数据 / 追求稳定

把显存算清楚:Full FT / LoRA / QLoRA 各占多少

python# 微调显存估算:以 7B 模型、bf16 为例,逐项算清「常驻」显存
P = 7e9
def gb(x): return x / (1024 ** 3)

# 全量微调(AdamW) 常驻项:权重 + 梯度 + 优化器一阶/二阶矩(fp32)
params_bf16  = 2 * P              # 权重 bf16
grad_bf16    = 2 * P             # 梯度 bf16
adam_moments = 8 * P             # fp32 m + fp32 v
print(f"Full FT 常驻 = {gb(params_bf16 + grad_bf16 + adam_moments):.1f} GB")

# LoRA(16bit 冻结基座):只训适配器,基座无梯度/优化器状态
print(f"LoRA     常驻 = {gb(params_bf16):.1f} GB + 适配器(极小)")

# QLoRA(4bit NF4 基座):约 0.5 字节/参数 + 量化常数
print(f"QLoRA    常驻 = {gb(0.5 * P):.1f} GB + 适配器")

# 预期:Full FT ≈ 78 GB;LoRA ≈ 13 GB;QLoRA ≈ 3.3 GB(仅权重项)
# 别忘还有 activations:随 batch×seq 线性增长,开梯度检查点可降 2-4 倍。
★
Full FT vs LoRA 的取舍:数据量足够大且显存充足时,Full FT 仍是最强(它不被低秩子空间限制);但 2026 年绝大多数团队的实际选择是 QLoRA/LoRA:成本低一个数量级、可为一堆任务各训一份小适配器、部署时热插拔。只有当任务与基座分布差异极大(如从通用到强领域专家)才值得付出 Full FT 的代价。
★
8.3 动手练习与自测:PEFT 的题都在「算账」与「选型」上:显存、参数量、部署方式。
  1. 算 LoRA 参数量:d=k=4096、r=16,LoRA 占全量的百分比?判据:16×(4096+4096)=131072 ≈ 0.13M,全量 16.78M,约 0.78%。
  2. 估全量微调显存:7B/bf16 + AdamW 的常驻显存是多少?判据:(2+2+8)×7B ≈ 78 GB(未含激活)。
  3. 选部署方式:一个基座要挂 20 个客户适配器,该 merge 还是运行时叠加?判据:运行时叠加(多 LoRA 服务),merge 会锁死单任务。
  4. 解释初始化:LoRA 为什么把 B 初始化为 0?判据:使 ΔW=0,从原模型平滑起步,避免初期破坏预训练权重。
  5. DoRA 动机:DoRA 相比 LoRA 多分解了什么?判据:幅度与方向解耦(magnitude + direction),低数据更稳。

9. 灾难性遗忘、后训练超参与对齐评测

知识结构图 · 遗忘与对齐评测
遗忘与对齐评测3 大知识域 · 15 个知识点
灾难性遗忘成因:数据窄 / lr 大 / 风格偏数据回放 replay 10–30%KL 正则 β 0.01–0.1LoRA 天然更轻GSM8K 掉 3–8 点告警
学习路径
  1. 读 9.1:理解灾难性遗忘成因(数据窄/lr 大/风格偏)与缓解(replay 10–30%、KL、LoRA、配比、退火)
  2. 实现 forget_report 双轨评测,确认"通用基准 + 领域任务"都跑
  3. 对接 M9:SFT/DPO 后跑统一+领域双轨评测,任一通用基准跌 >2 点算遗忘并修
✔ 能量化遗忘(如 GSM8K 掉 3–8 点告警),并用 replay/LoRA/降 lr 缓解
核心知识点详解
  • 灾难性遗忘的成因:① 训练数据过窄(全是某领域指令);② 学习率过大把已学表示推远;③ 对齐太偏某类风格。它发生在训练集之外的通用能力上,与过拟合不同。
  • 量化阈值:GSM8K 掉 3–8 点告警:通用基准(GSM8K/MMLU 等)对比 base 下跌 3–8 点即明显遗忘,应触发修复而不是继续叠领域数据。
  • 四种缓解:数据回放(replay 混 10–30% 通用/预训练数据)、KL 正则(β 0.01–0.1 贴参考)、LoRA(只动少量参数冻结底座)、配比与退火(领域/通用平衡)。
  • 双轨评测才能发现遗忘:只在领域任务上看指标会漏掉遗忘;必须「通用基准 + 领域任务」同时跑。常见坑:replay 混太多把领域精度冲淡,要平衡比例。
后训练超参SFT lr 1e-5~3e-4DPO beta 0.05–0.5RLHF KL 0.01–0.1GRPO group 4–16采样温度 0.8–1.0
学习路径
  1. 读 9.2:背下后训练超参范围(SFT lr、DPO beta 0.05–0.5、RLHF KL、GRPO group、采样温度)
  2. 对接 M9:把对齐超参写入配置并记录其对目标指标的影响
  3. 完成本章自测:对一次失败的 DPO/GRPO 训练归因超参问题
✔ 能给出各后训练阶段的超参范围并定位超参导致的失败
核心知识点详解
  • 各阶段超参一览:SFT lr 1e-5~3e-4;DPO β 0.05–0.5;RLHF KL 0.01–0.1;GRPO group 4–16;采样温度 0.8–1.0。按阶段各取一档。
  • 超参失败归因:DPO/GRPO 训练失败先看是不是 β 太大(学不动)或太小(语言崩);奖励不涨查 group 与温度是否过随机/过确定。
  • 写进配置并记录:所有对齐超参写入 yaml/config,每次运行记录其与目标指标(win rate/拒答率等)的对应,便于回滚归因。
  • 采样温度的作用:rollout 采样温度 0.8–1.0 平衡探索与稳定;过低则组内多样性不足,过高则噪声大。常见坑:三阶段共用一套超参配置,把 SFT 的 lr 直接用在 GRPO 上导致不稳。
对齐上线门禁目标能力 win rate > 0MMLU 跌幅 < 2 点拒答率 < 15%长度膨胀 < 30%奖励未饱和 < 0.95
学习路径
  1. 读 9.2:背下五指标上线门禁(win rate>0、MMLU 跌 <2、拒答 <15%、长度膨胀 <30%、奖励未饱和 <0.95)
  2. 编写对齐评测门禁脚本跑一次,确认所有阈值都有对照
  3. 对接 M9:作为 M9 对齐是否成功的验收门禁,产出 alignment.md 三阶段对比
✔ 能用五指标门禁判定对齐成功与否,并据此的 SFT/DPO/GRPO 三阶段对比
核心知识点详解
  • 五指标上线门禁:目标能力 win rate > 0;通用能力 MMLU 跌幅 < 2 点;拒答率 < 15%;长度膨胀 < 30%;奖励未饱和 < 0.95。五项齐过才算对齐成功。
  • 门禁要有对照:每个指标都要与 base 或上一阶段对照(Δ),而不是看绝对分。「跌幅<2」必须跟预训练/SFT 基线比。
  • 写成脚本可重复执行:scripts/alignment_gate.py 接受模型与评测集,输出五指标对照表并判定 pass/fail,纳入 CI。
  • 三阶段对比文档:产出 alignment.md:SFT/LoRA/DPO/GRPO 每一阶段在同样五指标上的变化,证明「能力升、通用不崩」。常见坑:只报提升的指标、隐掉通用下跌,等于没做过门禁。
学习路径

9.1 灾难性遗忘:成因与缓解

灾难性遗忘指后训练(SFT/对齐)让模型在通用能力、语言能力或多语言上明显回退。成因:① 训练数据过窄(全是某领域指令,模型「忘掉」其余);② 学习率过大把已学表示推离;③ 对齐阶段过度偏好某类回答风格,挤压原有能力。它和「过拟合」不同:过拟合是训练集上变差,遗忘是在训练集之外的下游能力上变差。

缓解手段机制代价
数据回放(replay)在 SFT/对齐数据里混入一定比例的预训练 / 通用数据稀释目标信号,需配比
KL 正则对参考模型加 KL 约束,限制偏离约束过强则学不动
LoRA / 低秩只动少量参数,原权重冻结容量上限受限
数据混合比例通用:领域 ≈ 7:3 或更保守需按任务实测
分阶段退火先宽后窄,逐步收窄流程更长

实用配方:SFT 阶段就混入 10–30% 通用 / 预训练续训数据;对齐阶段用 β·KL(π∥π_ref) 把策略锁在参考模型附近(β 太小防不住遗忘、太大训不动,常取 0.01–0.1);若用 LoRA 则遗忘天然更轻。评测时必须同时跑「通用基准 + 领域任务」,任一侧崩了都算失败。

把遗忘量化:双轨评测报告

python# 灾难性遗忘的量化:通用能力 vs 领域能力的双轨评测
def forget_report(base_scores, ft_scores,
                  key_bench=('MMLU', 'HumanEval', 'GSM8K'), tol=2.0):
    """base/ft_scores: {bench: 分数}。逐个基准算 delta,跌幅 > tol 触发告警。"""
    report = {}
    for b in key_bench:
        d = ft_scores[b] - base_scores[b]
        report[b] = (round(d, 2), 'OK' if d > -tol else 'REGRESS')
    return report

# 预期(某 8B 模型 LoRA SFT 后的典型结果):
#   MMLU      -0.8  OK
#   HumanEval -1.5  OK
#   GSM8K     -3.4  REGRESS   <- 数学推理回退明显
# 判据:任一通用基准跌幅 > 2 点即视为明显遗忘,应加大 replay 比例或降学习率。
遗忘信号典型量级对策
数学/代码推理回退GSM8K 掉 3–8 点混入推理数据 / 降 lr;避免纯风格数据
多语言能力退化非英语掉 5–15 点增大多语 replay 比例
通用知识下降MMLU 掉 > 2 点加通用 SFT 数据;减小训练步数
格式僵化/过度拒答拒答率骤升清洗安全数据;引入合理请求样本

9.2 后训练超参与对齐是否成功的判据

后训练超参与预训练量级差异巨大。学习率通常比预训练小 1–2 个数量级(SFT 约 1e-5~2e-5 全量、LoRA 约 1e-4~3e-4;DPO β 常取 0.1;RLHF 的 KL 系数约 0.01–0.1);GRPO 的组大小(group size)取 4–16,越大基线越准但 rollout 越贵;采样温度与每题采样数共同决定探索广度。

超参典型范围调错的症状
SFT lr1e-5 ~ 3e-4过大→遗忘/格式崩;过小→不动
DPO beta0.05 ~ 0.5过大→过度保守像参考;过小→奖励被忽略
RLHF KL coef0.01 ~ 0.1过大→学不动;过小→偏离、语言退化
GRPO group4 ~ 16过小→优势噪声大、不稳
采样数 / 温度4~8, 0.8~1.0过低→探索不足

对齐上线的五指标门禁(可当 CI 用)

python# 对齐上线门禁:五个指标同时达标才算「成功」,任一不过就退回调参
def alignment_gate(target_win, mmlu_drop, refusal_rate, len_growth, reward_sat):
    checks = {
        'target_win':   target_win   > 0.00,   # 目标能力上升(win rate)
        'general_keep': mmlu_drop    < 2.00,   # 通用能力跌幅 < 2 点
        'safety':       refusal_rate < 0.15,   # 不过度拒答
        'length':       len_growth   < 0.30,   # 输出长度膨胀 < 30%
        'not_hacked':   reward_sat   < 0.95,   # 奖励未饱和成满分
    }
    passed = all(checks.values())
    return checks, passed

# 预期:最常见的失败组合是 length 与 not_hacked 同时为 False ——
# 模型学会「越长越讨好」,奖励刷到 0.98 却并不更准。
# 对策:加长度惩罚(GFPO 的最短过滤 / DAPO 的超长惩罚),不复用被 hack 的 RM。
★
怎么判断对齐「成功」:单一指标会骗人。要看五件事同时成立:① 目标能力上升(数学/代码/工具调用 win rate 提升);② 通用能力不崩(MMLU / 基础 benchmark 跌幅在 1–2 点内);③ 安全但不过度拒答(拒答率不飙升,XSTest 等能区分合理与越狱);④ 输出长度不失控(被奖励 hacking 成「越长越谄媚」);⑤ 奖励未饱和成满分(满分基本意味着 hack)。这五条里有任何一条恶化,都说明对齐方向偏了。
⚠
后训练超参的对齐关系(一改就得连带改):这几个超参不是独立的:降 lr 通常要同时增训练步数否则学不到位;加大 replay 比例会稀释目标信号,隐含地需要更大 lr 或更多步;减小 DPO β(更放开优化目标)会放大遗忘与长度膨胀,需配合 KL/长度正则;GRPO group size 调大提升基线精度但要按比例增加 rollout 预算。调参时永远一次只动一组,并用 9.1 的双轨评测守住通用能力。
★
9.3 动手练习与自测:这一章是「上线守门」:能不能同时守住目标能力与通用能力。
  1. 定义遗忘:说清灾难性遗忘与过拟合的区别。判据:遗忘发生在训练集之外的下游能力上,过拟合是训练集变差。
  2. 写双轨评测:给定 base/ft 两组分数,写出门禁判据。判据:通用基准跌幅 > 2 点即告警,领域基准必须上升。
  3. 诊断退化:SFT 后 MMLU 掉 4 点、GSM8K 掉 6 点,列出 3 个对策。判据:加通用/推理 replay、降 lr、减训练步数(或改 LoRA)。
  4. 识别奖励 hack:奖励从 0.6 涨到 0.99 但人工评测没变好,说明什么?判据:奖励被 hack(长度/格式讨好),需换可验证奖励或加长度惩罚。
  5. 定 β:DPO 的 β 取 0.01 与 0.5 分别会发生什么?判据:过小偏离 reference、易遗忘与长度膨胀;过大贴近 reference、几乎学不动。

项目里程碑

贯穿项目 · Hamauls Orion
M9 领域微调与对齐 第 47–54 周

让 Hamauls Orion 的模型真正懂你的领域:清洗构造领域指令集,做 SFT,用 LoRA/QLoRA 降本,再用 DPO 或 GRPO 做偏好对齐,并验证「对齐之后到底好了没」。

本阶段产出(直接进入项目仓库)
验收标准:领域问答准确率相对基座提升 ≥ 15 个百分点且通用能力不显著退化;能解释 DPO 与 GRPO 的适用边界,并指出你这次为什么选它。

阶段练习项目

PROJECT 1
完整数据管线
从原始网页/文档语料出发,实现清洗 → 精确去重 → MinHash 近似去重 → 质量筛选 → 领域配比 → 污染检查的完整管线,产出数据卡片与可复现的版本哈希。
要达成的效果
  • 跑通完整六步管线并记录每步 token 保留率,产出可复现的版本哈希
  • 同输入在任意机器重跑得到完全一致的版本号(数据版本可追溯)
  • 产出数据卡片(来源 / 许可 / 清洗步骤 / 已知偏差 / 保留率)
功能需求
  • 用 polars / LazyFrame 批处理,避免逐行 for 循环
  • 实现精确去重(内容哈希) + MinHash+LSH 近似去重,量化去重后的剩余占比(约 30–50%)
  • 做至少一项质量筛选(长度 / 语言 / 启发式或模型打分),并做 n-gram 污染检查
  • 设计并记录领域配比与退火策略,统计各领域 token 占比
  • 每步输出输入 / 输出样本数与总 token,端到端版本哈希可复现
交付物
  • scripts/data/pipeline.py + 各步统计与数据卡片 md
  • 版本化后的清洗数据文件(含内容哈希清单)
边界 · 不做

不做模型训练评测打分,也不做超量模糊去重,先保证可复现的精确去重与质量四查到位。

PROJECT 2
SFT + DPO 端到端
用 8B 级开源模型完成 LoRA SFT,然后构造偏好数据做 DPO,对比 SFT / SFT+DPO 在指令跟随与安全性上的差异。
要达成的效果
  • 用 8B 级开源模型完成 LoRA SFT,再构造偏好对完成 DPO,两次训练指标可复现
  • 在指令跟随基准上,SFT+DPO 明显优于仅 SFT(可量化提升)
  • 给出三阶段(base / SFT / SFT+DPO)在目标能力与安全指标上的对照表
功能需求
  • 构造带 loss mask 的 SFT 数据(非 assistant 段置 -100),用 Llama-Factory / TRL 配 LoRA rank 16、lr 1e-4~3e-4 跑一次
  • 构造偏好数据对(同一 prompt 的成功 / 失败回答)并实现 / 复用 DPO 损失(β 取 0.05–0.5 记录敏感性)
  • 统一评测集上对比 base / SFT / SFT+DPO 的指令跟随与安全(拒答、有害性)指标
  • 全程用通用基准 + 领域基准双轨验证,通用能力下跌超阈值即告警
交付物
  • SFT / DPO 训练脚本与配置 + 三阶段评测对照表
  • DPO 损失实现与 β 敏感性记录 md
边界 · 不做

不做 RLHF(PPO),只做离线 DPO;不做多轮多步对齐。

PROJECT 3
GRPO 数学推理训练
在数学数据集上实现 GRPO(奖励用答案比对),监控奖励 / 长度 / 熵三条曲线,并对比 vanilla GRPO 与 DAPO 的稳定性差异。
要达成的效果
  • 在数学数据集上实现 GRPO 训练循环,奖励用答案精确比对,训练可复现
  • 端到端监控 reward / 输出长度 / 策略熵三条曲线,能明确观察到提升与稳定性变化
  • 对比 vanilla GRPO 与 DAPO 的稳定性差异(如熵崩塌 / 无效样本)并给出结论
功能需求
  • 实现组内相对优势 Â_i=(r_i−mean)/std、重要性比裁剪与 β·KL(π∥π_ref),丢弃全对 / 全错组
  • 奖励由答案字符串比对(可验证奖励)判定,不需要奖励模型
  • group_size 取 8–16,KL β 0–0.04,记录其对收敛的敏感性
  • 可视化并落表 reward / 长度 / 熵三曲线,作为稳定性与采纳判断依据
  • 可选实现 DAPO 的 Clip-Higher(ε_high=0.28)与动态采样做对比实验
交付物
  • grpo.py 训练脚本 + 三曲线监控图
  • vanilla GRPO vs DAPO 对比结论 md
边界 · 不做

不做多步 Agent 环境 RL,仅做单轮可验证奖励的数学推理对齐。

PROJECT 4
推理轨迹蒸馏
用强模型生成带思维链的解题数据,过滤后蒸馏到一个 1B–3B 小模型,在同一个评测集上对比蒸馏前后与「直接 SFT 答案」的效果。
要达成的效果
  • 用强模型生成带思维链的解题数据,经拒绝过滤后蒸馏到 1B–3B 小模型
  • 在同一个评测集上,轨迹蒸馏模型的解题能力优于「直接 SFT 结果答案」方案
  • 给出蒸馏前后与三种方案的准确率对比并量化提升
功能需求
  • 调用强模型生成思维链解题样本,用答案比对做拒绝采样(通过率约 20–40%)
  • 对 1B–3B 小模型做蒸馏 / SFT:轨迹蒸馏(含思维链)与直接 SFT(只训结果)各跑一版
  • 统一评测集上分别评估,记录 PPL 之外还需主观审看推理链质量
  • 记录合成数据的每轮去重与真实数据混合(alpha≈0.7),防止模型坍塌与污染
交付物
  • 蒸馏 / SFT 训练脚本 + 数据生成与过滤脚本
  • 三方案评测对比表与结论 md
边界 · 不做

不微调强教师模型,只做单轮蒸馏与结果对比;不引入模型评分器当奖励。

PROJECT 5
领域微调与对齐全链路(SFT/LoRA/DPO/GRPO)(M9)
选定一个垂直领域(如代码 / 医疗 / 法律),用 QLoRA 做 SFT 冷启动,再用 LoRA 做 DPO 偏好对齐,最后在可验证任务上跑 GRPO;全程用通用基准 + 领域基准双向门禁,证明能力上升且通用能力不崩。这是本阶段里程碑 M9 的交付物。
要达成的效果
  • 在同一垂直领域上依次完成 QLoRA SFT 冷启动 → DPO 偏好对齐 → GRPO 可验证奖励对齐,全链路可复现
  • 领域基准能力相对 base 显著上升,且通用基准任一指标下跌不超过阈值(如 MMLU 跌幅 <2 点)
  • 以五指标门禁(目标能力 win rate >0、拒答 <15%、长度膨胀 <30%、奖励未饱和 <0.95、通用跌幅 <2)全通过作为对齐成功判据
功能需求
  • 用 QLoRA(NF4 量化)在领域数据上做 SFT 冷启动,记录显存(约 3.3 GB 级)与质量权衡
  • 构造领域偏好对并用 LoRA 做 DPO(β 0.05–0.5),记录其对目标指标的影响
  • 在可验证任务(代码过测 / 数学对答等)上实现 GRPO,奖励用程序判定,监控 reward / 长度 / 熵曲线
  • 全程跑「通用基准 + 领域基准」双轨评测(含 forget_report),任一通用基准下跌超阈值即触发修复(replay / 降 lr / LoRA)
  • 所有阶段超参与配置写入 yaml,记录与五指标门禁的对应,支持回滚归因
交付物
  • sft.py + dpo.py + grpo.py 全链路训练脚本与统一配置
  • alignment.md(base / SFT / DPO / GRPO 三阶段五指标对比)+ forget_report
边界 · 不做

不做 Agentic RL / 多步环境 RL,不做 PPO,不做多语言大规模预训练,仅单参数到几十单参数级的可解释后训练对齐。

常见误区

面试高频问题速答

SFT 和 RL 分别解决什么问题?

SFT 解决「形式与对齐」:把预训练模型的续写倾向引导成对话/指令跟随的输出形式,学到的是数据中已有的模式。RL 解决「能力与可靠性」:通过奖励信号让模型探索更优的解题路径,尤其当奖励可验证时(答案对错、单测通过),能获得超越训练数据的推理能力。所以正确顺序是 SFT 冷启动 → RL 提升上限。

DPO 为什么不需要奖励模型?

RLHF 的最优策略有闭式解 π* ∝ π_ref · exp(r/β),即奖励可以被表示为「策略相对参考模型的对数概率比」。把 r 的这个表达式代入偏好目标(Bradley-Terry 模型),奖励项就被约掉,只剩对 chosen/rejected 的对数概率差做 log-sigmoid 损失。于是可以在离线成对数据上直接优化,无需奖励模型与在线采样。

GRPO 相比 PPO 省了什么?代价是什么?

省掉了 Critic(价值网络),从而省下与策略网络同量级的参数、梯度与优化器状态显存,且天然契合可验证奖励。代价:需要为同一 prompt 多次采样来估计组内基线(rollout 成本上升),当组内奖励全相同则无学习信号,且「组内可比」的假设在长程不等长子轨迹场景会失效。

RL 训练中模型输出越来越长,怎么办?

这是典型的长度偏置:长回答在人类/模型偏好里常被高估,RL 会放大它。对策有三类:① 奖励设计上对长度做惩罚或做长度归一化;② 采样后按 token 效率过滤只训最优子集(GFPO);③ 改用只裁剪权重不裁剪 token 的目标(CISPO)以保留「重新检查」这类低概率反思词。监控 length 与 entropy 曲线是必备动作。

蒸馏和 RL 应该怎么选?

不是二选一,而是互补。蒸馏是「继承」——把已有强模型的能力高效迁移到目标模型,成本低、见效快,适合把能力压缩到小模型或快速提升基座。RL 是「学习」——通过奖励探索出训练数据里没有的新行为,上限更高但更贵、更不稳定。主流配方是二者结合:先蒸馏拿到好起点,再用 RL 突破上限。

如果用不超过 8 张卡,你会怎么做一次“像样的”后训练?

① 选 7B–8B 级开源模型,用 QLoRA 做 SFT(4bit 量化 + 梯度检查点 + 梯度累积);② 用 LoRA 做 DPO,偏好数据规模几千条即可;③ 若做 RL,用小规模 GRPO,组大小取 4–8,只在一个窄任务(如数学或格式合规)上训,严格控制步数并监控熵;④ 全程用小评测集做门禁,避免过拟合;⑤ 用 vLLM 做推理加速 rollout。关键是把整个流程跑通而不是追求指标。

学习资源

DeepSeek-R1 论文论文 arxiv.org/abs/2501.12948 RLVR 与 GRPO 的里程碑,理解「可验证奖励 + 组相对优势」的必读。 DeepSeekMath(GRPO 源头)论文 arxiv.org/abs/2402.03300 GRPO 的原始提出,配合 R1 一起读。 DPO 论文论文 arxiv.org/abs/2305.18290 把 RLHF 简化为分类损失的经典,数学推导值得逐行读懂。 InstructGPT 论文论文 arxiv.org/abs/2203.02155 RLHF 三阶段流程的奠基,理解奖励模型与 PPO 的原始设计。 DAPO 论文论文 arxiv.org/abs/2503.14476 GRPO 的工业级稳定化四件套,长推理训练直接参照。 TRL(HuggingFace)GitHub github.com/huggingface/trl SFT / DPO / GRPO / PPO 的官方实现,读源码是最快的进阶方式。 verl(字节 Seed)GitHub github.com/volcengine/verl 面向 RL 训练的生产级框架,支持多种算法与 rollout 后端。 Llama-FactoryGitHub github.com/hiyouga/LLaMA-Factory 配置化完成 SFT / DPO / 蒸馏,最快出结果的选择。 How Frontier Labs Train LLMs(2026)长文 jxzhangjhu.github.io/blog/2026/how-frontier-labs-train-llms 各家训练配方的横向对比表,八点共识与分歧点都在这里。
★
2026 形势提示:2026 年最值钱的三个能力关键词:RLVR、Agentic RL、合成数据与蒸馏。招聘数据里「有 LLM 微调经验」的候选人面试通过率高出数倍,而真正稀缺的是「跑过完整 RL 后训练并知道怎么让它不发散」的人。即使只有单卡或少量卡,也要亲手把一个 GRPO 流程跑通——这段经历在面试里的说服力远大于任何证书。