调参优先级:先动哪三个旋钮
十几个超参不必都调。按影响排序,前三个决定成败,剩下的基本不用碰。
学完这节你能做到
- 按影响力给 GRPO 的超参排序,并说出每个的合理起始值
- 判断一个现象该调哪个参数,而不是全部微调一遍
- 在有限的卡时里设计出信息量最大的实验序列
十几个旋钮,只有三个值得动
GRPO 的配置项加起来有二十多个。新手的典型做法是逐个微调,跑完发现哪个都没用,卡时烧光了。
真实的影响力分布极不均匀:
影响力
▲
│ ████████████████████ reward 设计
│ ████████ 学习率 / KL 系数
│ ████ G / batch / temperature
│ ▌ clip 阈值 / betas / warmup
└──────────────────────────────────────────────→
这一节给出这个排序的依据,以及每一档的合理起始值。L2「三轮迭代」那次实验的结论正是这个排序的实证:调超参最好只拿到 +0.8(噪声内),改采样策略拿到 +5.3。
第一优先:reward 设计
它不算超参,但影响最大——而且是唯一一个「调错了别的都救不了」的东西。
理由在 L1「reward 从哪来」讲过:模型优化的是你写的 reward,不是你心里想的目标。如果 reward 有捷径,无论学习率、KL、batch 怎么调,模型都会去走那条捷径。
检查顺序(每次实验前都过一遍):
□ reward 拆成分项记录了吗?(否则 hacking 发生时看不出来)
□ 每一项的「成功率 × 分值」排序对吗?便宜的分给得少吗?
□ 空答案 / 截断样本拿多少分?
□ 有没有「重复某模式就能重复拿分」的项?
□ 分数是纯 0/1 吗?(容易整组归零)
调 reward 常常不表现为分数上涨,而表现为「训练终于开始动了」。
比如 L2 里格式分从 0.2 降到 0.05,分数只 +0.5(噪声内)——但 reward 的绝对值从 0.847 降到 0.661,更贴近真实正确率,曲线一下变得好读了。
reward 的价值不只在最终分数,还在让你的监控可信。
第二优先:学习率与 KL 系数
学习率
RL 后训练的学习率比 SFT 低一到两个数量级:
| 阶段 | 典型学习率 |
|---|---|
| 预训练 | 1e-4 ~ 3e-4 |
| SFT | 1e-5 ~ 5e-5 |
| RL 后训练 | 1e-6 ~ 5e-6 |
为什么这么低:RL 的每一步都在改变数据分布本身(改了模型就改了下一批采样)。走太快会让分布剧烈震荡,采出来的数据和优势估计都失去意义。
起始值 1e-6(slime、Miles、TRL 的推荐档都在这里)。
不要凭感觉调,看这个数:
clip_frac | 判断 | 动作 |
|---|---|---|
| < 1% | 更新过于保守 | 可以试 2e-6 ~ 3e-6 |
| 2% ~ 10% | 健康 | 别动 |
| 10% ~ 20% | 偏猛 | 观察 reward 有没有还在涨 |
| > 20% | 太猛 | 降一个档 |
配合 gnorm(梯度范数)一起看:健康时在 1 附近,跑到 5 以上说明单步想跳太远。
L2 read-the-curve 的 D 组辨认过:clip=0.419 / gnorm=6 就是学习率过大(那次是 5e-5,高了 50 倍)。
KL 系数 β
| β | 效果 | 什么时候用 |
|---|---|---|
| 0 | 完全不约束 | ✅ 默认起点(可验证奖励 + 中短训练) |
| 0.001 | 轻度 | 训练变长、开始看到 KL 上行 |
| 0.01 | 中度 | ⚠️ L2 实测掉 11.8 个点,慎用 |
| > 0.05 | 强约束 | 只在救火时用 |
L2 那轮实验的结论值得记住:β=0.01 有害的机制是 KL 不区分「有益的漂移」和「有害的漂移」。 它把模型拴在初始分布附近,连「多写几步推理」这个有益变化都做不出来(len 只涨到 108,对照组 152)。
现代配方常把 β 设 0(slime 入门例子就是 --kl-loss-coef 0.00),但它同时开着 --use-kl-loss——KL 不进损失,作为监控指标记录。
单卡上为省 1.1 GiB 而完全不要参考模型,代价是失去 KL 预警。L4「五种炸法」里那份 KL 从 0.002 飙到 12.88 的日志,就是这么来的。
留着它。1.1 GiB 换一条预警线,很划算。
第三优先:G、batch、temperature
G(组大小)
L2 的实测结论:收益递减点在 8 附近。
| G | 退化组占比 | 等卡时下的表现 |
|---|---|---|
| 4 | 18.4% | −4.3 个百分点,明显更差 |
| 8 | 9.1% | ✅ 基准 |
| 16 | 6.2% | +0.8(噪声内),不划算 |
下界是 4(再小基线估计不可用),上界看你的耐心。不确定就用 8。
batch
两个维度要分开看:
| 维度 | 加大的收益 | 优先级 |
|---|---|---|
| 每步 prompt 数 | 数据多样性上升 | ✅ 优先加这个 |
| G | 组内基线更准 | 收益 8 之后递减 |
单卡上受显存限制,8 prompt × G=8 = 64 条序列是个舒服的组合。显存有余量时优先加 prompt 数。
micro_batch 只影响显存和速度,不影响数学结果(配合梯度累积等价)。
所以它不参与调参——OOM 了就降到 1,够用就加大。别把它和「有效 batch」混在一起讨论。
temperature
它是探索与稳定之间最直接的旋钮:
| temperature | 效果 |
|---|---|
| 0 | ❌ 组内无差异,训练完全不动 |
| 0.7 ~ 0.8 | 偏保守,容易出现整组全对或全错 |
| 1.0 | ✅ 默认起点 |
| 1.1 ~ 1.2 | 救熵崩塌用 |
| > 1.3 | 输出质量下滑,容易变胡话 |
诊断对应关系:
adv_std 一直很低(且 entropy 正常) → 提 temperature,增加组内差异
entropy 在往 0 走 → 提 temperature(配合熵奖励)
输出开始不通顺、格式散乱 → 降回 1.0
基本不用动的
| 参数 | 推荐值 | 为什么不用动 |
|---|---|---|
clip 下界 eps | 0.2 | PPO 以来的稳定默认值 |
clip 上界 eps_high | 0.28 | DAPO 的非对称 clip,鼓励探索;slime 入门配方就是这组 |
adam_beta1 | 0.9 | 标准值 |
adam_beta2 | 0.98 | ⚠️ 注意不是默认的 0.999。RL 里梯度统计变化快,0.98 更跟得上 |
weight_decay | 0 ~ 0.1 | 影响很小 |
| warmup | 0 步 | RL 从一个已训练好的模型出发,不需要 warmup |
max_grad_norm | 1.0 | 标准的梯度裁剪 |
PyTorch 的 AdamW 默认 betas=(0.9, 0.999)。RL 后训练普遍用 0.98。
原因:0.999 意味着二阶动量的有效窗口约 1000 步。而 RL 里数据分布每步都在变,1000 步前的梯度统计已经过时了。0.98 把窗口缩到约 50 步,跟得上分布变化。
slime 的入门配方就是 --adam-beta1 0.9 --adam-beta2 0.98。直接抄。
三组起始配置
拿去直接用,不用自己试。
Qwen3-0.6B 全参(本路径主线)
G 8
每步 prompt 数 8
micro batch 2 (OOM 就降到 1 + 梯度累积)
学习率 1e-6
betas 0.9 / 0.98
β (KL) 0 (但留参考模型做监控)
clip 0.2 / 0.28
temperature 1.0
top_p 1.0
max_completion_len 512
归一化 序列平权
梯度检查点 开
参考模型 留
vLLM util 0.30 起,跑通后往上调到 0.5
sleep mode 开
────────────────────────────────
预期显存 约 21 GiB / 32 GiB
预期单步 约 45 秒
Qwen3-1.7B LoRA
LoRA rank 16 (target: attn + mlp)
G 8
每步 prompt 数 8
micro batch 1 + 梯度累积 4
学习率 2e-5 ← LoRA 要比全参高一个数量级
betas 0.9 / 0.98
β (KL) 0 (参考模型 = 禁用适配器,免费)
temperature 1.0
max_completion_len 512
vLLM util 0.35
────────────────────────────────
预期显存 约 24 GiB / 32 GiB
-
学习率要高一到两个数量级(2e-5 而不是 1e-6)。因为可训练参数只有 0.4%,同样的学习率下参数的实际变化量小得多。
-
参考模型是免费的:
with model.disable_adapter():
logp_ref, _ = sequence_logprobs(model, input_ids, attn_mask, comp_mask)禁用适配器就是基座模型。所以 LoRA 用户没有理由不开 KL 监控。
Qwen3-8B QLoRA(32GB 的上限)
量化 4bit (nf4)
LoRA rank 16
G 4 ← 显存所迫,已到下界
每步 prompt 数 4
micro batch 1 + 梯度累积 8
学习率 2e-5
max_completion_len 512 ← 不能再长
vLLM util 0.30
sleep mode 开(必须)
────────────────────────────────
预期显存 约 29 GiB / 32 GiB ⚠️ 很紧
预期单步 约 3 分钟
G 已经压到下界 4,回答长度不能超过 512,单步三分钟——200 步要跑十小时。
除非你有明确理由必须用 8B,否则留在 0.6B 或 1.7B。 小模型快速迭代学到的东西,远多于在 8B 上跑一次十小时的实验。
调参的实验序列
有限卡时下,按这个顺序花:
第 1 步 基准配置跑通,拿到对照组 (必须)
第 2 步 检查 reward:分项记录、找作弊路径 (最高性价比,不花卡时)
第 3 步 看 clip_frac 决定学习率要不要动 (看仪表盘,多半不用动)
第 4 步 上动态采样过滤退化组 (L2 实测 +5.3,最大单项收益)
第 5 步 数据难度:adv_std 低了就换难题 (比调参有效)
第 6 步 才轮到 G / temperature 微调 (通常在噪声内)
第 2 步不花卡时,纯思考;第 4 步是 L2 三轮实验里唯一确定有效的改动(+5.3,远超 4 个百分点的分辨率下限)。
而第 6 步——大多数人最先做的那一步——在 L2 实测里全部落在噪声内。
顺序错了,卡时就浪费在最没用的地方。
为什么 RL 后训练的学习率比 SFT 低一到两个数量级?
`adam_beta2` 为什么推荐 0.98 而不是 PyTorch 默认的 0.999?
有限卡时下,下面哪个动作的性价比最高?
LoRA 训练相比全参,有哪两处配置明显不同?
这节课的落点
- 影响力排序:reward 设计 ≫ 学习率/KL > G/batch/temperature ≫ clip/betas/warmup
- reward 是唯一「调错了别的都救不了」的东西,且改它常表现为「监控变可信」而非分数上涨
- 学习率起始 1e-6(比 SFT 低一到两个数量级),用
clip_frac当仪表盘 - β 默认 0,但一定要留参考模型做 KL 监控;β=0.01 实测掉 11.8 个点
- G 的收益递减点在 8;加大 batch 优先加 prompt 数而非 G
micro_batch不是超参(配梯度累积数学等价),只管显存和速度- temperature 1.0 起步,是探索与稳定的直接旋钮
adam_beta2用 0.98(唯一的反默认推荐),warmup 不需要- 三组起始配置:0.6B 全参 / 1.7B LoRA(lr 2e-5 + 免费参考模型)/ 8B QLoRA(能跑不好跑)
- 实验序列:跑通 → 查 reward → 看 clip_frac → 上动态采样 → 换难题 → 才微调 G