← 返回首页
21_rlvr_grpo_viz.html

RLVR 与 GRPO:只给判分器,不给答案

第 8 章的 SFT 要标准答案,第 10 章的 DPO 要一对好坏回答。 RLVR 只要一个能自动判对错的程序:模型自己答,程序判分,按分数更新。本关用 GRPO 把第 6 章的 124M 教会两位数加法,再在同一基座、同一评测、同样 4096 道题下和 SFT、DPO 同台比。配套代码 phase5-fullstack/19_grpo.py,在 RTX 4090 上跑完。

STEP 1
判分器只会对答案
STEP 2
组内比较:优势
STEP 3
全错的组没有信号
STEP 4
三条路同台
STEP 5
组大小与 KL
这一关 基座 124M 第 6 章 · 10B token G 8 每道题采样几次 训练题 4,096 每条路都一样 batch 16 每步几道题 → 256 步 β 0.04 KL 系数 评测 500 没见过的题 · dev 另 200 道 G 的 8 与 pass@8 的 8 含义不同:前者是训练时每题采几次,后者是评测时采几次

① 判分器只会对答案

任务是两位数加法,数字逐位写:6 0 + 9 2 =,正确回答 1 5 2。 判分器 是 verify 函数里的一行比较:回答去掉空格,等不等于正确的和。下面是训练第一批里的真实采样(温度 1,同一道题 8 次)。换一道题:

–
答对几个(奖励 1)
–
组内平均奖励
–
训练第几步采的
↳ 代码:19_grpo.py 的 verify · generate(每道题生成 G 个回答)
题目为什么写成 "6 0 + 9 2",不写 "60 + 92"?
GPT-2 的词表里 10 到 99、20 到 198 各是一个整体 token,60 和 152 都是单个 token,模型看不到个位和十位,只能死记 90 × 90 张表。 用那种写法先试过:4096 道题 SFT 后 500 道评测题只对 5% 到 9%。逐位用空格隔开后每个数字一个 token,同样 4096 道题 SFT 能到六成以上。 分词怎样影响数字,见 第 18 章 STEP 5。
基座一开始会做加法吗?为什么要先"热身"?
基本不会。124M 基座对 500 道评测题贪心解码只对 –,采样 8 次至少一次对的比例 –,很多回答连格式都不对。 RL 的信号来自"同一道题里有的对、有的错",全错就学不到东西(第 3 步)。所以先用一小批带答案的题做一次热身 SFT,得到共同起点 warm,再从 warm 分出三条路。 本页有两个起点:热身 200 道(warm 贪心 –)和热身 1000 道(–)。热身用的题和训练题、评测题都不重叠。
↳ 下一步:8 个回答各拿到 0 或 1。怎样把"这一个比同组其他的好"变成更新方向?

② 组内比较:每个回答的优势

GRPO 不训价值网络,用同组的平均奖励当基线: 优势 A = (r − 组内均值) / 组内标准差。比平均好的回答 A > 0,更新时它的概率被抬高;比平均差的被压低。 点下面 8 个回答,切换对错,看优势怎么变:

–
组内均值(基线)
–
组内标准差
–
答对的那条 A
–
答错的那条 A
↳ 代码:19_grpo.py 的 run_grpo,【步骤 3】adv = (rg − 均值) / (标准差 + 1e-4)
然后怎么更新?和 SFT 差在哪?
loss = −A · log π(回答) + β · KL,按回答里的 token 平均。log π(回答) 就是第 8 章 SFT 的那个量:SFT 对标准答案做 −log π,相当于每条回答的 A 都是 1; GRPO 对模型自己采样的回答做,A 可正可负。KL 项用论文 (4) 式的估计 π_ref/π − log(π_ref/π) − 1,拉住模型别离热身起点太远。 这里每批采样只更新一次,更新前后是同一个策略,PPO 的比值裁剪 clip(π/π_old) 恒等于 1,代码里省掉了。
1 对 7 错时,答对那条的优势为什么比 7 对 1 错时大这么多?
除以标准差之后,少数派的 |A| 大。1 对 7 错:均值 0.125,标准差 0.354,答对那条 A = 2.47,每条答错的 −0.35;7 对 1 错反过来。 效果是:难题上偶然答对的那一次被强力加强,容易题上偶然答错的那一次被强力压低。 按标准差归一化会让不同难度的题权重不同,Dr. GRPO(Liu et al., arXiv 2503.20783)认为这带来偏差,建议去掉除以标准差;本脚本按 DeepSeekMath 原式保留。
和 PPO、第 10 章的 DPO 比,GRPO 少了什么?
比 PPO 少了价值网络(critic)。PPO 要另训一个和策略差不多大的网络估计每个状态的期望回报当基线;GRPO 同一道题采 G 个,拿组内均值当基线,省掉这个网络。 DeepSeekMath §4.1 的动机就是省下 critic 的显存和算力。 和 DPO 比:DPO 用离线的成对数据,不在训练中采样;GRPO 每一步都用当前模型采样,判分器当场打分。
↳ 下一步:"全错"时 8 条的优势都是 0,这道题对更新毫无贡献。训练中这种组有多少?

③ 全错的组没有信号

两个起点各跑一次 GRPO:每步 16 道题,记下其中 8 次全错、8 次全对的比例,以及采样的平均奖励和 dev 题上的贪心准确率。切换起点:

8 次全错的组 8 次全对的组 采样平均奖励 dev 贪心准确率
–
起点:贪心 / pass@8
–
训练中没有信号的组(全错 + 全对)
–
GRPO 后评测贪心
pass@8 是什么,为什么拿它看起点?
pass@k 是每道题采样 k 次、至少一次答对的比例。GRPO 训练时一组正好是 8 次采样,所以起点的 pass@8 基本就是"一道题能不能凑出至少一个对的"的概率: pass@8 低,大多数组全错,没有信号。热身 200 道的起点 pass@8 只有 –,热身 1000 道是 –。
DeepSeek-R1-Zero 直接从基座做 RL,为什么这里不行?
R1-Zero(DeepSeek-AI,arXiv 2501.12948)从 DeepSeek-V3-Base 出发,基座本身已经能在一部分数学题上采样出正确答案,RL 有信号可放大。 这里的 124M 基座对两位数加法 pass@8 约为 0,RL 无从下手,所以要先热身。 同一篇报告里,R1 正式版在 RL 之前也先用几千条长思维链数据做了冷启动 SFT。
↳ 下一步:两个起点上,GRPO 和只给答案的 SFT、离线 DPO 相比如何?

④ 三条路同台:同一起点、同一评测、同样 4096 道题

三条路从同一份热身权重出发,看同一串 4096 道训练题,在同样 500 道没见过的题上评测。每个起点上,每条路各扫 3 到 6 个学习率,按 dev 题挑。切换起点:

dev 题贪心准确率随训练步数
SFT DPO GRPO 起点 warm
↳ 代码:19_grpo.py 的 run_sft / run_dpo / run_grpo · 学习率扫描 runs/queue_grpo_lr.sh 与 queue_grpo.sh
三条路各用了什么"监督"?算力一样吗?
SFT:4096 道题的标准答案,每道题 1 次前向 + 反向。 DPO:不用答案,warm 对每道题采 8 次,判分器从中挑一对一错凑成偏好对,凑不出(全对或全错)的题丢掉;训练时同样 256 步。 GRPO:不用答案,每一步当场对 16 道题各采 8 次,判分器打分,8 条回答都参与反向。 所以"同样 4096 道题"指看过的题相同;GRPO 的生成和反向是 SFT 的约 8 倍。换成 SFT 看更多带答案的题,准确率也会继续涨,本页没有做这组。
学习率是怎么挑的?
每个学习率跑完整的 256 步,看 200 道 dev 题的贪心准确率,取最高的;评测题的准确率列在旁边,只用来对照,不参与挑选。dev 只有 200 道,差一两个百分点就是差两三道题,几个学习率接近时,挑中哪个带有偶然性;dev 并列时取较大的学习率。最优值落在扫描区间边上时,再往外补点,直到它落在区间内部。全部在 RTX 4090 上跑。
DPO 为什么只在很小的学习率下才涨?
–
只给判分器的 GRPO,和有标准答案的 SFT 差多少?
–
↳ 下一步:组大小 G 和 KL 项对结果的影响。

⑤ 组大小与 KL

都从热身 1000 道的起点出发,学习率 3e-6、4096 道题不变,只改一个设置。每一行的竖线是起点 warm 的评测贪心准确率:

G 越大越好吗?
G 大,一组里更容易同时有对有错,全错 / 全对的组少,基线也估得更准;代价是每道题的采样和反向随 G 线性增加。 G = 2 时一组只有两条,要么一对一错(A 为 ±1),要么全同(无信号)。 DeepSeekMath §4.2 的设置是每题采 64 个。这里 G = 16 的开销是 G = 8 的两倍。 没有信号的组的比例随 G 单调下降,准确率却不是:G = 4 比 G = 2 还低。每个设置只跑了一个随机种子,这种先后可能来自噪声,不宜解读。
去掉 KL 反而更高,为什么还要它?
KL 项防止模型离起点太远:奖励只看最后的数字对不对,没有 KL 时模型可以把其他行为(比如续写别的文本的能力)改得面目全非,判分器看不见。 这里任务单一、只训 256 步,KL 的约束只表现为稍慢一点的提升。DAPO(Yu et al., arXiv 2503.14476)等后续工作在长思维链推理上去掉了 KL 项; 是否保留取决于任务和训练长度,本页的一组对照不足以下结论。
达标本关实测
↳ 跑法:bash runs/queue_grpo_lr.sh && bash runs/queue_grpo.sh(CUDA / MPS / CPU;RTX 4090 上每次约 2 分钟)
🎉 RLVR 与 GRPO · 通关 · Phase 5 收尾
你只给了一个会对答案的判分器,就让 124M 学会了两位数加法:同一道题采样 8 次,组内比较得出优势,按优势更新。也看到起点采样不出对的答案时 RL 拿不到信号。Phase 5 从分词器、FlashAttention、scaling law 走到 RLVR,补齐了这条学习线的全链路。