Part III · RL for LLMs · Chapter 15

RL with verifiable rewards: reasoning models and GRPO

o1 and DeepSeek-R1. Group-relative advantages, R1-Zero, and why checkable answers changed everything.

~150 minBefore this: Policy gradients, PPO, LLM as a policy, Reward sourcesUpdated 2026-10

Here is a puzzle. You have a small language model that answers 37+48= correctly about half the time. You have no teacher who can show it better solutions, and no reward model trained on human opinions. You have one thing: a three-line program that checks whether an answer is right. Is that enough to make the model better at arithmetic?

Yes, and that is the subject of this chapter. In Chapter 12 the reward was a neural network trained to imitate human preferences. Such a network can be fooled, so RLHF needs a leash, a critic, and a lot of care. When the reward is a program that checks the answer (exact match for a math problem, unit tests for code), much of that machinery becomes optional. In September 2024 OpenAI’s o1 showed what large-scale RL on checkable problems can do. In January 2025 DeepSeek-R1 published a recipe anyone could follow: a strong base model, a checker, and an algorithm called GRPO that fits in twenty lines. By the end of this chapter you will have written those twenty lines yourself and watched them push your tiny model from 51% to over 80% accuracy.

Why checkable answers changed things

From “think step by step” to learned reasoning

Language models got better at multi-step problems long before RL entered the picture. Chain-of-thought (CoT) prompting (Wei et al., 2022) showed that if the prompt contains worked examples that reason step by step before answering, large models do the same and get far more math problems right. Kojima et al. (2022) found that appending “Let’s think step by step” to the question helps even without examples. The reasoning was there; prompting just drew it out.

The next step was to train on reasoning. A simple and influential version is STaR (Zelikman et al., 2022): sample many step-by-step solutions, keep the ones whose final answer is correct, fine-tune on them, repeat. If you did Exercise 7.8 in Chapter 7, you recognize this: fine-tuning on your own successes is REINFORCE with 0/1 rewards and no baseline. It already is reinforcement learning with a checker, in its plainest form.

Then, in September 2024, OpenAI announced o1. OpenAI says o1 was trained with large-scale reinforcement learning to think in a long chain of thought before answering, and reports that its performance kept improving both with more RL training compute and with more thinking time at inference. That second axis, test-time compute, was new: a model that gets more accurate the longer it is allowed to think. OpenAI did not publish the algorithm, the rewards or the data. The open community spent the next four months guessing.

What “verifiable” means

A verifiable reward is a reward computed by a program that checks the response against a known answer or specification, rather than by a learned model of someone’s judgment. Examples:

  • Math with a final answer: extract the answer (say, the contents of \boxed{...}), normalize it, compare with the reference. Reward 1 if equal, else 0. The lab in Chapter 14 builds a robust version of this.
  • Code: run the program against unit tests. Reward 1 if all pass (or the fraction that pass).
  • Formal proofs: a proof checker such as Lean accepts or rejects the proof.
  • Format: a regular expression checks that the response has the required structure.

Training with such rewards is called reinforcement learning with verifiable rewards (RLVR), a name coined by the Tülu 3 report (Lambert et al., 2024). For our TinyLM the verifier is a single line: 1.0 if response == answer else 0.0.

Why does this matter so much? Recall the central worry of RLHF (Chapter 12, and Chapter 19 in full): a learned reward model is an imperfect proxy, trustworthy only near the data it was trained on. Push a policy hard against it and the policy finds the proxy’s blind spots (verbose answers, flattery, confident nonsense) and the true quality falls. That is why RLHF keeps a KL leash to the reference model and stops early.

A verifier has no blind spots of that kind. There is no direction in response space where “the checker thinks it’s right but it isn’t” grows without limit. So you can optimize much harder, for much longer, which is exactly what reasoning models do: thousands of RL steps instead of a few hundred.

The other consequence: the KL leash matters less. DeepSeekMath’s GRPO used a KL coefficient β=0.04\beta = 0.04. DeepSeek-R1-Zero used β=0.001\beta = 0.001 and periodically reset the reference model to the current policy. Many 2025 recipes dropped the KL term entirely, and as of October 2026 the default in Hugging Face TRL’s GRPOTrainer is β=0\beta = 0. Chapter 16 follows that thread.

Quick check Why can RLVR training usually run for many more steps than RLHF with a learned reward model?

GRPO: compare each answer with its siblings

A worked example first

Take one prompt, xx = 37+48=, and sample G=4G = 4 responses from the current model. (The group size GG is the number of responses sampled per prompt.) Check each one:

Responsey(1)y^{(1)}y(2)y^{(2)}y(3)y^{(3)}y(4)y^{(4)}
Text857581585
Reward r(i)r^{(i)}1001

Which responses should the model make more likely, and by how much? GRPO’s answer: compare each response with the others in its group. Compute the group’s mean and standard deviation,

mean(r)=1+0+0+14=0.5,std(r)=14∑i(r(i)−0.5)2=0.5,\text{mean}(r) = \frac{1 + 0 + 0 + 1}{4} = 0.5, \qquad \text{std}(r) = \sqrt{\tfrac{1}{4}\textstyle\sum_i (r^{(i)} - 0.5)^2} = 0.5,

and give each response the group-relative advantage

A^(i)=r(i)−mean(r)std(r).\hat A^{(i)} = \frac{r^{(i)} - \text{mean}(r)}{\text{std}(r)}.

Here that is +1,−1,−1,+1+1, -1, -1, +1. The two correct answers are pushed up, the two wrong ones pushed down, with equal strength.

Now a harder prompt, where only one of four responses is right: rewards 1,0,0,01, 0, 0, 0. The mean is 0.250.25 and the std is 0.25×0.75=0.433\sqrt{0.25 \times 0.75} = 0.433, so

A^(1)=1−0.250.433=+1.73,A^(2)=A^(3)=A^(4)=0−0.250.433=−0.58.\hat A^{(1)} = \frac{1 - 0.25}{0.433} = +1.73, \qquad \hat A^{(2)} = \hat A^{(3)} = \hat A^{(4)} = \frac{0 - 0.25}{0.433} = -0.58.

The rare success gets a big push up. Each of the three common failures gets a small push down. The advantages still sum to zero.

Finally, suppose all four responses are right: rewards 1,1,1,11, 1, 1, 1. Every response equals the mean, so every advantage is zero. The same holds if all four are wrong. A group in which every response gets the same reward teaches the model nothing. Hold on to that; it shapes everything about how RLVR is run in practice.

Why “compare with your siblings” is the right idea

You have seen this move before. In Chapter 7 you learned that the policy gradient

∇θJ=E[(r−b) ∇θlog⁡πθ(y∣x)]\nabla_\theta J = \mathbb{E}\big[(r - b)\,\nabla_\theta \log \pi_\theta(y \mid x)\big]

is unbiased for any baseline bb that does not depend on the sampled response, and that a good baseline (close to the expected reward) slashes the variance. In Chapter 8 the standard choice was the value function, b=V(x)b = V(x) (not exactly the variance-minimizing baseline, as Exercise 7.6 showed, but close and meaningful), which makes r−V(x)r - V(x) the advantage: how much better this response was than what the policy gets on average from this prompt.

For a 0/1 verifiable reward, V(x)=Ey∼πθ[r(x,y)]V(x) = \mathbb{E}_{y \sim \pi_\theta}[r(x, y)] is the probability p(x)p(x) that the model solves the prompt. How would you estimate it? PPO-based RLHF trains a critic, a second network (usually as big as the policy) that predicts values token by token (Chapter 12). GRPO does something much simpler: it samples GG answers and uses their average reward as a Monte Carlo estimate of V(x)V(x). That is the group mean. No critic to train, no critic to store, no critic to get wrong.

Dividing by the std is GRPO’s other ingredient. It makes the advantages dimensionless: whatever the reward scale, each group’s advantages have mean 0 and standard deviation 1. That is convenient, but it is a choice, not a law. It also changes how much each prompt counts. Every group that has any signal gets advantages of the same overall size (their squares always sum to GG). So a prompt the model solves 1 time in 8 is pushed almost as hard as one it solves 4 times in 8: the average ∣A^∣\lvert\hat A\rvert is 0.66 versus 1.0. Without the std division it would be 0.22 versus 0.5. Liu et al. (2025) argue this is a bias toward too-easy and too-hard prompts and propose dropping the std (“Dr. GRPO”). You can see the effect in the demo below and work it out in Exercise 15.4. Chapter 16 weighs the arguments.

Groups that teach nothing

If a prompt is solved with probability pp, all GG responses get the same reward with probability

P(zero signal)=pG+(1−p)G.P(\text{zero signal}) = p^G + (1 - p)^G.
Prompt success rate ppG=8G = 8G=16G = 16G=64G = 64
0.5 (a fair challenge)0.008≈ 0≈ 0
0.9 or 0.10.430.19≈ 0
0.05 or 0.950.660.440.04
0.01 or 0.990.920.850.53

Read the table from both ends.

  • Too-hard prompts teach nothing. If the model never solves a prompt, every group is all zeros, every advantage is zero, and the model gets no gradient toward solving it. RL can only reinforce what the model already sometimes does. This is why R1-style training starts from a strong base model, and why the choice of training problems (difficulty, curriculum) matters so much.
  • Too-easy prompts waste compute. As training succeeds, more prompts move toward p≈1p \approx 1 and more groups come back all-correct. You paid for GG generations and got no gradient. DAPO’s dynamic sampling filters such groups out and samples more prompts to fill the batch (Chapter 16).
  • Bigger groups help at the extremes. A prompt with p=0.05p = 0.05 yields signal 34% of the time with G=8G = 8, but 96% of the time with G=64G = 64. DeepSeekMath used G=64G = 64; DeepSeek-R1-Zero used G=16G = 16.
Interactive One GRPO group up close
Prompt x: 37+48=Tap a response to flip it between right (reward 1) and wrong (reward 0).
group size G =
rewards
mean std
advantage of a right answer of a wrong one
sum of advantages mean |A|
Across prompts of different difficulty (G fixed): tap the chart to set p
P(group has signal) = 1 − pᴳ − (1 − p)ᴳaverage |A| per response, GRPOaverage |A| per response, mean only

What to try: (1) Press the 1, 0, 0, 1 preset and check the advantages against the worked example. Then 1, 0, 0, 0: the lone success gets +1.73. (2) Press All right: the banner tells you the group is wasted. (3) Set p = 0.95 and press Resample a few times with G = 4, then with G = 16. How often do you get a group with any signal? Compare with the dashed curve. (4) Switch to Mean only. The advantages shrink when the group is lopsided (try 1, 0, 0, 0). In the chart, the GRPO curve is flatter than the mean-only parabola: dividing by the std gives nearly-solved and nearly-hopeless prompts almost the same push as 50/50 prompts, whenever their group has any signal at all.

Quick check A prompt is solved by the current model 2% of the time. With G = 8, what happens on most training steps that include it?

From advantages to a loss

Every token of response y(i)y^{(i)} gets the same advantage A^(i)\hat A^{(i)}. The simplest version of GRPO is then REINFORCE with this advantage, averaged over tokens:

L(θ)=−1G∑i=1G1∣y(i)∣∑t=1∣y(i)∣A^(i) log⁡πθ(yt(i)∣x,y<t(i)).\mathcal{L}(\theta) = -\frac{1}{G}\sum_{i=1}^{G} \frac{1}{\lvert y^{(i)}\rvert}\sum_{t=1}^{\lvert y^{(i)}\rvert} \hat A^{(i)}\,\log \pi_\theta\big(y^{(i)}_t \mid x, y^{(i)}_{<t}\big).

Here ∣y(i)∣\lvert y^{(i)}\rvert is the number of tokens in response ii, and the log-probability of the whole response is the sum of token log-probs (Chapter 11). Minimizing L\mathcal{L} raises the log-probability of every token in the positive-advantage responses and lowers it in the negative ones.

Let’s see what this does in our example. Tokenized, the four responses are 8 5 <eos>, 7 5 <eos>, 8 1 5 <eos>, 8 5 <eos>: lengths 3, 3, 4, 3. Each token’s log-probability gets the gradient weight A^(i)/(G ∣y(i)∣)\hat A^{(i)} / (G\,\lvert y^{(i)}\rvert):

ResponseAdvantageWeight on each of its tokens
8 5 <eos> ✓+1+1+1/12≈+0.083+1/12 \approx +0.083
7 5 <eos> ✗−1-1−1/12≈−0.083-1/12 \approx -0.083
8 1 5 <eos> ✗−1-1−1/16≈−0.063-1/16 \approx -0.063
8 5 <eos> ✓+1+1+1/12≈+0.083+1/12 \approx +0.083

Now look at the first token, chosen right after =. Three responses started with 8 and one with 7. The token 8 at that position collects +112+112−116≈+0.10+\tfrac{1}{12} + \tfrac{1}{12} - \tfrac{1}{16} \approx +0.10: pushed up, though the wrong answer 815 also started with it. The token 7 collects −0.083-0.083. Nobody told the algorithm that the first digit of 815 was fine and the second one was the mistake. That credit assignment emerges only statistically, across many groups in which good and bad answers share some tokens and differ in others. It is crude, which is why process rewards that score individual steps exist (Chapter 17). It also works remarkably well at scale.

Notice too that the long wrong answer is pushed down less per token (−0.063-0.063 versus −0.083-0.083) simply because it is longer. That is a side effect of dividing by ∣y(i)∣\lvert y^{(i)}\rvert, and Liu et al. (2025) argue that it lets wrong answers drift longer during training. Chapter 16 dissects this “length bias” and the alternatives.

Adding PPO’s clip

Generating responses is the expensive part of RL for LLMs (Chapter 20), so you want to take more than one gradient step per batch. As soon as you do, the samples come from an older policy πold\pi_\text{old} (written πθold\pi_{\theta_\text{old}} in papers), and you need the importance ratio and the clip from Chapter 9. Per token,

ρt(i)(θ)=πθ(yt(i)∣x,y<t(i))πold(yt(i)∣x,y<t(i)),\rho^{(i)}_t(\theta) = \frac{\pi_\theta\big(y^{(i)}_t \mid x, y^{(i)}_{<t}\big)}{\pi_\text{old}\big(y^{(i)}_t \mid x, y^{(i)}_{<t}\big)},

and the token’s surrogate objective is PPO’s

min⁡(ρt(i) A^(i), clip⁡(ρt(i),1−ϵ,1+ϵ) A^(i)).\min\Big(\rho^{(i)}_t\,\hat A^{(i)},\ \operatorname{clip}\big(\rho^{(i)}_t, 1-\epsilon, 1+\epsilon\big)\,\hat A^{(i)}\Big).

Everything from Chapter 9 carries over: at ρ=1\rho = 1 the gradient equals the REINFORCE gradient above; once a positive-advantage token’s ratio exceeds 1+ϵ1 + \epsilon (or a negative-advantage token’s ratio falls below 1−ϵ1 - \epsilon), its gradient is zero and the update stops pushing it. In our example with ϵ=0.2\epsilon = 0.2, if after one inner step the probability of 5 in response 1 has risen from 0.40 to 0.50, its ratio is 1.25. The advantage is positive and 1.25>1.21.25 > 1.2, so on the next inner step that token contributes no gradient.

With a single gradient step per batch, ρ≡1\rho \equiv 1 and the clip never activates. That is the setting of the DeepSeekMath experiments (one policy update per batch of samples) and of TRL’s default. In that case GRPO’s policy term is exactly REINFORCE with a group baseline.

Adding the KL leash, in the loss

GRPO keeps a penalty for drifting from the reference model πref\pi_\text{ref} (usually the starting checkpoint), but puts it in the loss rather than in the reward. Classic RLHF subtracts βlog⁡πθπref\beta \log\frac{\pi_\theta}{\pi_\text{ref}} from each token’s reward, which mixes the KL into the advantages. DeepSeekMath adds it as a separate term instead, saying this avoids complicating the advantage computation. The per-token estimator is Schulman’s k3k_3 (Chapter 11):

k3=πref(yt∣⋅)πθ(yt∣⋅)−log⁡πref(yt∣⋅)πθ(yt∣⋅)−1.k_3 = \frac{\pi_\text{ref}(y_t \mid \cdot)}{\pi_\theta(y_t \mid \cdot)} - \log\frac{\pi_\text{ref}(y_t \mid \cdot)}{\pi_\theta(y_t \mid \cdot)} - 1.

Three things make k3k_3 attractive. It is never negative, since u−log⁡u−1≥0u - \log u - 1 \ge 0 for u>0u > 0. It is unbiased for KL(πθ∥πref)\mathrm{KL}(\pi_\theta \Vert \pi_\text{ref}) when yty_t is sampled from πθ\pi_\theta, because Eπθ[πref/πθ]=1\mathbb{E}_{\pi_\theta}[\pi_\text{ref}/\pi_\theta] = 1. And it is zero exactly when the two models agree on the token.

A numeric check: if the policy gives a token probability 0.6 and the reference gives 0.5, then u=0.5/0.6=0.833u = 0.5/0.6 = 0.833 and k3=0.833−log⁡0.833−1=0.0157k_3 = 0.833 - \log 0.833 - 1 = 0.0157. Its derivative with respect to log⁡πθ\log\pi_\theta is 1−πref/πθ=0.1671 - \pi_\text{ref}/\pi_\theta = 0.167. Since the loss contains +βk3+\beta k_3, gradient descent nudges this token’s log-probability down, back toward the reference. Where the policy has fallen below the reference, the push is up. Where they agree, there is no push at all.

The full objective

Put the three pieces together and you have GRPO exactly as the DeepSeekMath paper (Shao et al., 2024) writes it, translated to our notation:

JGRPO(θ)=Ex∼Dy(1),…,y(G)∼πold(⋅∣x) ⁣[1G∑i=1G1∣y(i)∣∑t=1∣y(i)∣{min⁡(ρt(i)A^t(i), clip⁡(ρt(i),1−ϵ,1+ϵ)A^t(i))−β DKL[πθ∥πref]}]\mathcal{J}_\text{GRPO}(\theta) = \mathbb{E}_{\substack{x \sim \mathcal{D}\\ y^{(1)},\dots,y^{(G)} \sim \pi_\text{old}(\cdot \mid x)}}\!\left[\frac{1}{G}\sum_{i=1}^{G}\frac{1}{\lvert y^{(i)}\rvert}\sum_{t=1}^{\lvert y^{(i)}\rvert}\Big\{\min\Big(\rho^{(i)}_t \hat A^{(i)}_t,\ \operatorname{clip}\big(\rho^{(i)}_t, 1-\epsilon, 1+\epsilon\big)\hat A^{(i)}_t\Big) - \beta\,\mathbb{D}_\text{KL}\big[\pi_\theta \Vert \pi_\text{ref}\big]\Big\}\right]

with DKL\mathbb{D}_\text{KL} evaluated per token by k3k_3, and, for an outcome reward, A^t(i)=A^(i)\hat A^{(i)}_t = \hat A^{(i)} for every tt. In words: sample a group per prompt from the current policy; give each response its group-relative advantage; for every token, take PPO’s clipped surrogate minus a KL penalty; average over each response’s tokens, then over the group; maximize.

DeepSeekMath writesThis course writesMeaning
q∼P(Q)q \sim P(Q)x∼Dx \sim \mathcal{D}prompt (question)
oio_i, oi,to_{i,t}y(i)y^{(i)}, yt(i)y^{(i)}_tii-th sampled response, its tt-th token
πθ(oi,t∣q,oi,<t)πθold(oi,t∣q,oi,<t)\frac{\pi_\theta(o_{i,t} \mid q, o_{i,<t})}{\pi_{\theta_\text{old}}(o_{i,t} \mid q, o_{i,<t})}ρt(i)\rho^{(i)}_tper-token importance ratio
A^i,t=r~i=ri−mean(r)std(r)\hat A_{i,t} = \tilde r_i = \frac{r_i - \text{mean}(\mathbf{r})}{\text{std}(\mathbf{r})}A^(i)\hat A^{(i)}group-relative advantage
ε\varepsilon, β\betaϵ\epsilon, β\betaclip range, KL coefficient

The DeepSeek-R1 paper writes the same objective more compactly, with the ratio of whole-sequence probabilities πθ(oi∣q)/πθold(oi∣q)\pi_\theta(o_i \mid q)/\pi_{\theta_\text{old}}(o_i \mid q). Implementations, including the reference code for this chapter’s lab, use the per-token form.

GRPO, one iteration
1. Draw P prompts x_1..x_P from the dataset.
2. For each prompt, sample G responses with the current policy (call it π_old).
3. Score every response with the verifier: r = 1 if correct, else 0.
4. Per group: A_i = (r_i − mean(r)) / (std(r) + tiny). All tokens of y_i share A_i.
5. Compute once, without gradients: log π_old and log π_ref of every sampled token.
6. Repeat μ times (μ = 1 to a few):
     ρ   = exp(log π_θ − log π_old)                        per token
     obj = min(ρ·A, clip(ρ, 1−ε, 1+ε)·A) − β·k3(π_θ, π_ref)  per token
     loss = −mean over responses( mean over that response's real tokens(obj) )
     one gradient step on θ
7. The updated policy becomes π_old for the next iteration.

That’s all of it. No reward model, no value network, no GAE. Compare that with the four models of PPO-RLHF in Chapter 12: policy, reference, reward model and critic. With a verifier and the KL term, GRPO needs two networks, the policy and a frozen reference. With β=0\beta = 0 it needs only the policy. Dropping the critic matters for memory: the critic is a second network about as large as the policy, with its own gradients and optimizer states.

Quick check In GRPO with exactly one gradient step per batch of samples, what does the clipping do?

Settings in the wild

DeepSeekMath GRPO (2024)DeepSeek-R1-Zero (2025)TRL GRPOTrainer default (Oct 2026)This chapter’s lab
Rewardlearned reward modelrule-based: accuracy + formatyour reward functionsexact match
Group size GG641688
KL coefficient β\beta0.040.001 (reference reset every 400 steps)0 (no reference model loaded)0.04
Learning rate1×10−61 \times 10^{-6}3×10−63 \times 10^{-6}1×10−61 \times 10^{-6}3×10−43 \times 10^{-4} (tiny model)

One more difference hides in the defaults. TRL’s default loss_type is not the per-response averaging of the DeepSeekMath formula above. It averages over all tokens in the batch (DAPO’s choice), and you have to ask for loss_type="grpo" to get the original. Why anyone would change it is a Chapter 16 story.

One historical detail is easy to miss: the paper that introduced GRPO did not use a verifier. DeepSeekMath trained a reward model and used GRPO as a cheaper replacement for PPO, reporting MATH accuracy rising from 46.8% to 51.7% on top of an instruction-tuned 7B model. The combination of GRPO with purely rule-based rewards is what DeepSeek-R1 made famous a year later. The R1-Zero numbers come from the revised R1 paper (arXiv v2 and the Nature version), which gives more hyperparameters than the January 2025 preprint.

DeepSeek-R1-Zero and R1: the recipe goes public

R1-Zero: RL straight from a base model

DeepSeek-R1-Zero skipped supervised fine-tuning entirely. Starting from the pretrained DeepSeek-V3-Base, it ran GRPO with a fixed prompt template:

A conversation between User and Assistant. The user asks a question, and the Assistant solves it. The assistant first thinks about the reasoning process in the mind and then provides the user with the answer. The reasoning process and answer are enclosed within <think> </think> and <answer> </answer> tags, respectively […]

The reward was the sum of two rules: an accuracy reward (is the final answer right, checked by matching a boxed answer for math or running test cases for code) and a format reward (is the thinking enclosed in the think tags). DeepSeek deliberately used no neural reward model, writing that neural reward models “may suffer from reward hacking in the large-scale reinforcement learning process”.

What happened, as the paper reports it:

  • Accuracy climbed a long way. On AIME 2024 (competition math), pass@1 rose from 15.6% to 71.0% over training in the January 2025 preprint (77.9% in the revised version), and to 86.7% with majority voting over many samples.
  • Responses got longer on their own. The average response length on training problems grew steadily, from hundreds to thousands of tokens. Nothing in the reward asked for length. The model learned that spending more tokens on checking and re-trying earns more reward: it learned to use test-time compute.
  • Reflection appeared. The paper reports behaviors such as revisiting earlier steps and trying alternative approaches, and shows an “aha moment” in which an intermediate checkpoint interrupts its own solution with “Wait, wait. Wait. That’s an aha moment I can flag here.” and starts over.
  • Readability suffered. R1-Zero’s reasoning often mixed languages and was hard to read.

R1: four stages

R1-Zero proved the point; DeepSeek-R1 made a usable model. The pipeline has four stages:

  1. Cold-start SFT. Fine-tune the base model on “thousands” of long chain-of-thought examples written in a readable format (reasoning, then a summary). This fixes readability and, the paper says, gives a better starting point than the raw base model.
  2. Reasoning RL. The same large-scale GRPO as R1-Zero on math, code, science and logic problems, plus a language-consistency reward: the fraction of words in the chain of thought that are in the target language. The paper notes this slightly lowers benchmark scores but makes the output readable.
  3. Rejection sampling + SFT. Sample many responses from the RL checkpoint, keep only correct (and readable) ones, about 600k reasoning samples, add about 200k non-reasoning samples (writing, factual QA, translation), and fine-tune the base model again on these 800k examples. This is the STaR idea, with a much stronger generator.
  4. RL for all scenarios. A final RL stage mixing rule-based rewards for reasoning with learned reward models for helpfulness and harmlessness on general prompts.

The pattern of alternating RL (to discover good behavior) with SFT on the model’s own filtered outputs (to consolidate it) recurs in many later pipelines (Chapter 21).

Distillation: the cheap way to a small reasoner

DeepSeek also fine-tuned six smaller open models (Qwen2.5 and Llama, from 1.5B to 70B parameters) on the 800k samples generated by R1. This is pure SFT, no RL, and the resulting “R1-Distill” models reason far better than their bases. The paper then asks the obvious question: could RL alone have done the same for a small model? They ran large-scale RL on Qwen-32B-Base for over 10,000 steps. It reached roughly the level of QwQ-32B-Preview (47.0% versus 50.0% pass@1 on AIME 2024), while the distilled 32B model scored 72.6%. Their conclusion: distilling a stronger model into a smaller one is economical and effective, while pushing the frontier still needs stronger base models and larger-scale RL.

Kimi k1.5, the same week

R1 was not alone. Moonshot AI’s Kimi k1.5 report appeared the same week, also describing long-chain-of-thought RL without Monte Carlo tree search, value functions or process reward models. Its policy update starts from the KL-regularized optimum π∗∝πold er/τ\pi^* \propto \pi_\text{old}\, e^{r/\tau} that you met in Chapter 10 and Chapter 11, and turns it into a loss whose gradient is again a policy gradient with the mean sampled reward as the baseline, plus a squared penalty on the log-ratio to the previous policy. Different derivation, same core move: sample several answers to a prompt and compare each with their average. It also added a length penalty to keep responses from growing without bound.

Quick check Why does R1-Zero's response length grow during training even though the reward never mentions length?

Does RL teach new reasoning? The pass@k debate

pass@k

pass@k is the probability that at least one of kk independent samples solves the problem, averaged over problems. pass@1 is ordinary accuracy. pass@k for large kk measures coverage: can the model solve this problem at all, if you let it try many times? To estimate it without bias, draw n≥kn \ge k samples per problem, count the cc correct ones, and use

pass@k^=1−(n−ck)(nk),\widehat{\text{pass@}k} = 1 - \frac{\binom{n-c}{k}}{\binom{n}{k}},

the probability that a random subset of kk of your nn samples contains at least one correct answer (Chen et al., 2021).

The question

GRPO only reinforces answers the model already produces sometimes. So does RL teach the model to solve problems it could not solve before, or does it just make it produce, more reliably, solutions it could already find? DeepSeekMath noticed the issue first: in their experiments RL improved majority-vote accuracy but not pass@k at large kk, and they read this as RL making the output distribution more robust rather than raising fundamental capability.

Yue et al. (2025) tested this systematically, across model families, RL algorithms and math, code and visual-reasoning benchmarks. Their findings: RLVR-trained models win at small kk, but the base models reach higher pass@k at large kk; the problems RL-trained models solve are largely ones the base model could already solve with enough samples; several popular RL algorithms performed similarly; and distillation from a stronger model, unlike RL, can introduce genuinely new reasoning patterns.

A toy example shows how this can happen. Take two problems. The base model solves problem A with probability 0.6 using one strategy, and problem B with probability 0.05 using a rarer strategy. RL sharpens the model toward the common strategy: problem A goes to 0.98, and, because the policy’s entropy collapses, the rare strategy that cracked problem B fades and problem B drops to 0.01.

pass@1 (average of A and B)pass@64 (average of A and B)
Base model(0.6+0.05)/2≈0.33(0.6 + 0.05)/2 \approx 0.33(1+(1−0.9564))/2≈0.98\big(1 + (1 - 0.95^{64})\big)/2 \approx 0.98
After RL(0.98+0.01)/2≈0.50(0.98 + 0.01)/2 \approx 0.50(1+(1−0.9964))/2≈0.74\big(1 + (1 - 0.99^{64})\big)/2 \approx 0.74

(For problem A, 1−0.4641 - 0.4^{64} and 1−0.02641 - 0.02^{64} are both 1 to many decimal places, which is where the leading 1 comes from.)

RL helped at k=1k = 1 and hurt at k=64k = 64: the curves cross. Your lab reproduces this in miniature. In our run of the lab’s passk.py (300 held-out problems, 64 samples each), GRPO raised the TinyLM’s pass@1 from 0.53 to 0.83, while its pass@64 ended slightly below the SFT model’s (0.977 versus 0.983), and it never solved 7 problems where SFT never solved 5. The crossover fell between k=8k = 8 and k=16k = 16.

The other side

The debate is not settled, and the counter-evidence is serious:

  • Longer, more careful RL can expand coverage. ProRL (Liu et al., NVIDIA, 2025) trained for thousands of steps with KL control, periodic reference resets and a diverse task mix, and reports gains at all kk, including on tasks where the base model failed for every kk they tried.
  • Answer-only pass@k can mislead. A base model that guesses a right answer through wrong reasoning counts as a success. Wen et al. (2025) propose scoring pass@k only when the reasoning is also correct, and report that by this measure RLVR does extend the reasoning boundary.
  • Benchmarks and base models can mislead. Shao et al. (2025) found that GRPO with random or even incorrect rewards substantially improved Qwen2.5-Math-7B on MATH-500, but gave little or no gain on other model families. Wu et al. (2025) argue that Qwen2.5 models are likely contaminated on common math benchmarks, and that on a clean synthetic task only accurate rewards help. Claims about what RL “teaches” should be checked on more than one model family and on uncontaminated data.

A fair summary as of 2026: at the scales most papers study, RLVR mostly sharpens (it raises the probability of good solutions the model can already find), and it can narrow coverage as entropy falls. Whether and when it expands what the model can do depends on training length, exploration, data and how you measure. That is an open question, and Chapter 21 returns to it. For practice, the lesson is concrete: watch pass@k at large kk and the policy’s entropy, not just pass@1.

Watching it train

The group view tells you what happens to one prompt. Training happens on thousands. The demo below runs GRPO on a pool of 24 prompts whose difficulty increases from left to right. Each prompt jj is solved with probability pj=σ(w+uj−dj)p_j = \sigma(w + u_j - d_j), where djd_j is a fixed difficulty, uju_j a parameter specific to that prompt, and ww a shared skill parameter that every prompt’s gradient moves, a stand-in for the way a neural network’s weights are shared across problems. Every iteration samples GG answers per prompt, computes group advantages, and takes one policy-gradient step on the logits.

Interactive GRPO on a pool of prompts, easy to hard
Success probability of each prompt (easy → hard; hollow tick = start)
group had signal this iterationall G answers equal: zero signal
Training curves
mean accuracyfraction of zero-signal groups (20-iteration average)previous run's accuracy
iterationsamples drawn
mean accuracyshared skill w
zero-signal groups this iteration20-iteration average
prompts out of reach (p < 1%)
Advantage:
Shared skill w:

What to try: (1) Press Play. Easy prompts on the left saturate quickly and turn grey: their groups are all-correct and carry no signal. The hard prompts on the right start out of reach (grey, near zero) and only start learning once the shared skill w has lifted them high enough to be solved occasionally. The fraction of zero-signal groups starts high (with G = 8, about two thirds of this pool is too easy or too hard to give signal) and climbs above 90% as training succeeds. (2) Turn Shared skill off and press Play again (the previous run stays as a faint ghost curve). Each prompt now learns alone, and the hardest ones never move: RL cannot reinforce an answer it never samples. (3) With shared skill on, compare G = 2 and G = 32. Look at the samples-drawn readout too: bigger groups give a cleaner signal but cost more generations per iteration. (4) Switch to Mean only. At the same α it learns more slowly, but most of that is step size: its advantages are smaller. Raise α to about 1.2 and it roughly catches up.

This toy has the same qualitative shape as your lab’s training curves and as reports from large runs: accuracy rises, the share of wasted all-correct groups rises with it, and progress on the hardest problems waits until the model occasionally solves them. It also shows why the dataset is a hyperparameter. Problems too hard for the current model are dead weight until the model improves. Problems too easy are dead weight forever.

Why GRPO works, and where it strains

Why it works:

  • The baseline is free. The group mean is a Monte Carlo estimate of V(x)V(x) built from samples you generate anyway. No critic, no value-learning instability, half the trained parameters of PPO-RLHF.
  • It suits sparse, binary, end-of-sequence rewards. A per-token critic must learn to predict a 0/1 outcome from every prefix, a hard regression problem. Comparing complete answers to the same prompt sidesteps it.
  • It inherits PPO’s safety rails (the clip) for batch reuse, and a KL leash when you want one.

Where it strains (each is a later chapter):

  • Wasted groups at both ends of difficulty, and sensitivity to the data mix (dynamic sampling, curricula: Chapter 16).
  • Normalization choices (std division, length averaging) that quietly reweight prompts and responses (Chapter 16).
  • Crude credit assignment: every token gets the same advantage (Chapter 17).
  • Entropy collapse: the policy becomes more deterministic, which helps pass@1 and can hurt exploration and pass@k (Chapter 19). Your lab’s entropy curve falls steadily.
  • Long rollouts dominate the cost, which pushes real systems toward asynchronous, slightly off-policy training (Chapter 20).
  • Multi-turn tasks with tools and environments need more than one response per prompt (Chapter 18).

Summary

  • Verifiable rewards are computed by a program that checks the answer (exact match, unit tests, proof checkers). They lack the fuzzy blind spots of learned reward models, so RL can optimize much harder. They are not unhackable: verifier bugs get exploited.
  • GRPO samples GG responses per prompt and gives each the advantage A^(i)=(r(i)−mean(r))/std(r)\hat A^{(i)} = (r^{(i)} - \text{mean}(r))/\text{std}(r), shared by all its tokens. For rewards 1,0,0,11, 0, 0, 1 that is +1,−1,−1,+1+1, -1, -1, +1.
  • The group mean is a Monte Carlo estimate of the value baseline V(x)V(x) from Chapter 7–8, so GRPO needs no critic. The loss adds PPO’s per-token clipped ratio and a k3k_3 KL penalty to πref\pi_\text{ref} in the loss.
  • Groups where every answer gets the same reward give zero gradient. This happens with probability pG+(1−p)Gp^G + (1-p)^G, so too-hard and too-easy prompts are wasted, and RL can only reinforce answers the model sometimes produces.
  • DeepSeek-R1-Zero showed that GRPO with only accuracy and format rewards, applied directly to a strong base model, raises reasoning accuracy a lot and grows long chains of thought. R1 added cold-start SFT, a language-consistency reward, rejection-sampling SFT and a final general RL stage. Distilling R1 into small models beat running RL on them directly.
  • The pass@k debate: RLVR clearly improves pass@1, but at large kk base models often match or beat RL-trained ones, suggesting RL mostly sharpens existing abilities. Whether longer or better-designed RL expands them is still open.

Exercises

Exercise 15.1Group advantages by handPen & paper●○○

Compute the GRPO advantages (population std, no ϵ\epsilon) for these groups, then the mean-only advantages r(i)−mean(r)r^{(i)} - \text{mean}(r):

  1. G=6G = 6, rewards 1,1,0,0,0,01, 1, 0, 0, 0, 0.
  2. G=4G = 4, rewards 1,1,1,01, 1, 1, 0.
  3. G=4G = 4, a partial-credit reward (say, fraction of unit tests passed): 0.2,0.9,0.5,0.40.2, 0.9, 0.5, 0.4.

For each, check that the advantages sum to zero. In group 2, which response is pushed hardest, and why does that make sense?

Solution
  1. Mean =2/6=1/3= 2/6 = 1/3. Variance =16[2(2/3)2+4(1/3)2]=16⋅129=2/9= \tfrac{1}{6}\big[2(2/3)^2 + 4(1/3)^2\big] = \tfrac{1}{6}\cdot\tfrac{12}{9} = 2/9, so std =0.471= 0.471. Correct answers: (2/3)/0.471=+1.41(2/3)/0.471 = +1.41. Wrong answers: (−1/3)/0.471=−0.71(-1/3)/0.471 = -0.71. Sum: 2(1.41)+4(−0.71)=02(1.41) + 4(-0.71) = 0. Mean-only: +0.667+0.667 and −0.333-0.333.
  2. Mean =0.75= 0.75, std =0.75×0.25=0.433= \sqrt{0.75 \times 0.25} = 0.433. Correct: 0.25/0.433=+0.580.25/0.433 = +0.58. Wrong: −0.75/0.433=−1.73-0.75/0.433 = -1.73. Mean-only: +0.25+0.25 and −0.75-0.75. The single wrong answer is pushed hardest. The model already solves this prompt 3 times in 4, so the most informative event is the rare failure: “whatever you did there, do less of it.”
  3. Mean =2.0/4=0.5= 2.0/4 = 0.5. Deviations: −0.3,+0.4,0,−0.1-0.3, +0.4, 0, -0.1. Variance =(0.09+0.16+0+0.01)/4=0.065= (0.09 + 0.16 + 0 + 0.01)/4 = 0.065, std =0.255= 0.255. Advantages: −1.18,+1.57,0,−0.39-1.18, +1.57, 0, -0.39. Mean-only: −0.3,+0.4,0,−0.1-0.3, +0.4, 0, -0.1. The response at exactly the mean gets no push either way, even though it earned 0.5 reward. GRPO cares only about relative quality within the group.

In general, for binary rewards with kk correct out of GG, the mean is k/Gk/G and the std is (k/G)(1−k/G)\sqrt{(k/G)(1 - k/G)}, so correct answers get (G−k)/k\sqrt{(G-k)/k} and wrong answers −k/(G−k)-\sqrt{k/(G-k)}.

Exercise 15.2When does a group teach nothing?Pen & paper●●○

(a) Show that, for binary rewards, a group of GG independent responses to a prompt with success probability pp has all rewards equal with probability pG+(1−p)Gp^G + (1-p)^G.

(b) Your training set has prompts the current model solves 5% of the time. How large must GG be for at least 90% of their groups to carry signal? What does that cost compared with G=8G = 8?

(c) A colleague says: “An all-correct group gives zero gradient, so it has no effect on training at all.” With β>0\beta > 0, is that true? When exactly is the gradient from such a group zero?

Hint
For (c), write out the per-token loss for a group whose advantages are all zero. Which term is left, and what is its gradient when πθ=πref\pi_\theta = \pi_\text{ref}?
Solution

(a) All equal means all correct (probability pGp^G, by independence) or all wrong (probability (1−p)G(1-p)^G). The two events are disjoint, so the probability is pG+(1−p)Gp^G + (1-p)^G.

(b) We need 0.05G+0.95G≤0.10.05^G + 0.95^G \le 0.1. The first term is negligible, so 0.95G≤0.10.95^G \le 0.1, giving G≥ln⁡0.1/ln⁡0.95=44.9G \ge \ln 0.1 / \ln 0.95 = 44.9. So G=45G = 45. That is 45/8≈5.645/8 \approx 5.6 times the generation cost per prompt. With G=8G = 8, only 1−0.958=34%1 - 0.95^8 = 34\% of these groups carry signal. Per useful group, the costs are 8/0.34≈248/0.34 \approx 24 generations at G=8G = 8 versus 45/0.9=5045/0.9 = 50 at G=45G = 45, but the larger group also gives a much better estimate of the gradient when it fires. In practice people combine a moderate GG with filtering the zero-signal groups and resampling (DAPO’s dynamic sampling, Chapter 16).

(c) Not quite. With all advantages zero, the clipped surrogate is min⁡(0,0)=0\min(0, 0) = 0 for every token, so the policy-gradient term vanishes. The KL term −βk3-\beta k_3 remains, and its gradient with respect to log⁡πθ(yt)\log\pi_\theta(y_t) is −β(1−πref/πθ)-\beta(1 - \pi_\text{ref}/\pi_\theta) in the objective. It is zero only on tokens where πθ=πref\pi_\theta = \pi_\text{ref}. So an all-correct group still pulls the policy back toward the reference on its tokens once the two have diverged. It contributes no reward signal. (In the lab, the test test_task5_step_updates_policy_not_reference needed a reference model different from the policy for exactly this reason: at the very start, πθ=πref\pi_\theta = \pi_\text{ref} and a batch of all-wrong groups produces no gradient at all.)

Exercise 15.3The group mean is a slightly shrunk baselinePen & paper●●●

Consider mean-centred advantages without std division, A^(i)=r(i)−rˉ\hat A^{(i)} = r^{(i)} - \bar r with rˉ=1G∑jr(j)\bar r = \frac{1}{G}\sum_j r^{(j)}, and the estimator

g^=1G∑i=1GA^(i) ∇θlog⁡πθ(y(i)∣x),y(1),…,y(G)∼iidπθ(⋅∣x).\hat g = \frac{1}{G}\sum_{i=1}^G \hat A^{(i)}\, \nabla_\theta \log\pi_\theta(y^{(i)} \mid x), \qquad y^{(1)},\dots,y^{(G)} \overset{\text{iid}}{\sim} \pi_\theta(\cdot \mid x).

(a) Show that E[g^]=G−1G ∇θJ(x)\mathbb{E}[\hat g] = \frac{G-1}{G}\,\nabla_\theta J(x), where J(x)=Ey∼πθ[r(x,y)]J(x) = \mathbb{E}_{y \sim \pi_\theta}[r(x, y)].

(b) Show that the leave-one-out advantage r(i)−1G−1∑j≠ir(j)r^{(i)} - \frac{1}{G-1}\sum_{j \ne i} r^{(j)} gives an exactly unbiased estimator. How is it related to the mean-centred one?

(c) Why is the bias in (a) harmless in practice, while the effect of dividing by the std is not as easy to dismiss?

Hint
Split rˉ\bar r into the ii-th term and the others. Use E[∇log⁡πθ(y)]=0\mathbb{E}[\nabla\log\pi_\theta(y)] = 0 and the independence of y(i)y^{(i)} and y(j)y^{(j)} for j≠ij \ne i.
Solution

Write si=∇θlog⁡πθ(y(i)∣x)s_i = \nabla_\theta \log\pi_\theta(y^{(i)} \mid x). Two facts from Chapter 7: E[si]=0\mathbb{E}[s_i] = 0, and E[r(i)si]=∇θJ(x)\mathbb{E}[r^{(i)} s_i] = \nabla_\theta J(x).

(a) Split the mean: A^(i)=r(i)−1Gr(i)−1G∑j≠ir(j)=G−1Gr(i)−1G∑j≠ir(j)\hat A^{(i)} = r^{(i)} - \frac{1}{G} r^{(i)} - \frac{1}{G}\sum_{j \ne i} r^{(j)} = \frac{G-1}{G} r^{(i)} - \frac{1}{G}\sum_{j\ne i} r^{(j)}. Then

E[A^(i)si]=G−1G E[r(i)si]−1G∑j≠iE[r(j)] E[si]=G−1G∇θJ(x),\mathbb{E}[\hat A^{(i)} s_i] = \tfrac{G-1}{G}\,\mathbb{E}[r^{(i)} s_i] - \tfrac{1}{G}\sum_{j \ne i}\mathbb{E}[r^{(j)}]\,\mathbb{E}[s_i] = \tfrac{G-1}{G}\nabla_\theta J(x),

where the cross terms factor by independence and vanish because E[si]=0\mathbb{E}[s_i] = 0. Averaging over ii gives E[g^]=G−1G∇θJ(x)\mathbb{E}[\hat g] = \frac{G-1}{G}\nabla_\theta J(x).

(b) With the leave-one-out baseline bi=1G−1∑j≠ir(j)b_i = \frac{1}{G-1}\sum_{j\ne i} r^{(j)}, which is independent of y(i)y^{(i)}, E[(r(i)−bi)si]=∇θJ−E[bi]E[si]=∇θJ\mathbb{E}[(r^{(i)} - b_i)s_i] = \nabla_\theta J - \mathbb{E}[b_i]\mathbb{E}[s_i] = \nabla_\theta J. Unbiased. The relation: r(i)−bi=r(i)−Grˉ−r(i)G−1=GG−1(r(i)−rˉ)r^{(i)} - b_i = r^{(i)} - \frac{G\bar r - r^{(i)}}{G-1} = \frac{G}{G-1}(r^{(i)} - \bar r). The leave-one-out advantage is the mean-centred one times the constant G/(G−1)G/(G-1). They point in exactly the same direction.

(c) Because the difference is one constant factor, the same for every prompt and every step: a learning-rate rescale (with G=8G = 8, a factor of 0.875). Dividing by the group std is different: the std depends on the sampled rewards, varies from prompt to prompt, and is correlated with the numerator. It reweights prompts relative to each other, so the expected update is no longer proportional to ∇J\nabla J at all. Whether that reweighting helps (by amplifying rare successes) or hurts (the “difficulty bias”) is one of the debates in Chapter 16.

Exercise 15.4How hard does GRPO push on each prompt?Pen & paper●●○

For binary rewards with kk correct out of GG (0<k<G0 < k < G), define a group’s push as the average absolute advantage 1G∑i∣A^(i)∣\frac{1}{G}\sum_i \lvert \hat A^{(i)}\rvert.

(a) Show that the push is 2k(G−k)G2\frac{2k(G-k)}{G^2} for mean-only advantages and 2k(G−k)G\frac{2\sqrt{k(G-k)}}{G} with GRPO’s std division.

(b) For G=8G = 8, compare a nearly-solved prompt (k=7k = 7) with a 50/50 prompt (k=4k = 4) under both formulas. Which formula treats them more equally?

(c) Connect your answer to the chart in the first demo.

Hint
With kk correct, the correct answers each have deviation 1−k/G1 - k/G and the wrong ones −k/G-k/G. The std is (k/G)(1−k/G)\sqrt{(k/G)(1-k/G)}.
Solution

(a) Mean-only: kk answers with ∣A^∣=1−k/G=(G−k)/G\lvert\hat A\rvert = 1 - k/G = (G-k)/G and G−kG - k answers with ∣A^∣=k/G\lvert\hat A\rvert = k/G. The sum is k(G−k)/G+(G−k)k/G=2k(G−k)/Gk(G-k)/G + (G-k)k/G = 2k(G-k)/G; divide by GG. With std division, divide that by std=k(G−k)/G\text{std} = \sqrt{k(G-k)}/G: the push becomes 2k(G−k)G2⋅Gk(G−k)=2k(G−k)G\frac{2k(G-k)}{G^2}\cdot\frac{G}{\sqrt{k(G-k)}} = \frac{2\sqrt{k(G-k)}}{G}.

(b) Mean-only: k=7k = 7 gives 2⋅7/64=0.2192 \cdot 7/64 = 0.219; k=4k = 4 gives 32/64=0.532/64 = 0.5. Ratio 0.44. GRPO: k=7k = 7 gives 27/8=0.6612\sqrt 7/8 = 0.661; k=4k = 4 gives 1.01.0. Ratio 0.66. GRPO treats them more equally: it gives the nearly-solved prompt relatively more push than mean-only does (and by symmetry the same holds for a nearly-hopeless prompt with k=1k = 1).

(c) Averaging the push over the binomial distribution of kk gives the two solid curves in the first demo. The mean-only curve is 2(G−1)Gp(1−p)\tfrac{2(G-1)}{G}p(1-p), a parabola that heavily favors p≈0.5p \approx 0.5. The GRPO curve is flatter, with a broad plateau: whenever a group has any signal at all, std division brings its push up toward 1. Liu et al. (2025) call this a difficulty bias. Others see it as a feature that amplifies the rare successes on hard prompts, which the second demo hints at.

Exercise 15.5Reading the k₃ termPen & paper●●○

Let u=πref(yt∣⋅)/πθ(yt∣⋅)u = \pi_\text{ref}(y_t \mid \cdot)/\pi_\theta(y_t \mid \cdot) and k3=u−log⁡u−1k_3 = u - \log u - 1.

(a) Prove k3≥0k_3 \ge 0 with equality iff u=1u = 1.

(b) Prove that Eyt∼πθ[k3]=KL(πθ∥πref)\mathbb{E}_{y_t \sim \pi_\theta}[k_3] = \mathrm{KL}(\pi_\theta \Vert \pi_\text{ref}) at a given state.

(c) Compute k3k_3 and ∂k3/∂log⁡πθ(yt)\partial k_3/\partial \log\pi_\theta(y_t) for: (i) πθ=0.5\pi_\theta = 0.5, πref=0.25\pi_\text{ref} = 0.25; (ii) πθ=0.25\pi_\theta = 0.25, πref=0.5\pi_\text{ref} = 0.5. In each case, which way does the +βk3+\beta k_3 term in the loss push the token’s probability?

(d) What happens to the gradient in (c) when the policy has almost eliminated a token the reference likes (πθ≪πref\pi_\theta \ll \pi_\text{ref})? Why might that be a problem?

Hint
For (a), consider f(u)=u−log⁡u−1f(u) = u - \log u - 1 and its derivative. For (b), what is Eπθ[u]\mathbb{E}_{\pi_\theta}[u]? For (c), uu depends on log⁡πθ\log\pi_\theta through u=exp⁡(log⁡πref−log⁡πθ)u = \exp(\log\pi_\text{ref} - \log\pi_\theta).
Solution

(a) f(u)=u−log⁡u−1f(u) = u - \log u - 1 has f′(u)=1−1/uf'(u) = 1 - 1/u, negative for u<1u < 1 and positive for u>1u > 1, so its minimum on u>0u > 0 is at u=1u = 1, where f(1)=0f(1) = 0. Hence f(u)≥0f(u) \ge 0 with equality only at u=1u = 1. (Equivalently: log⁡u≤u−1\log u \le u - 1, the tangent-line bound for the concave log.)

(b) Eπθ[u]=∑yπθ(y)πref(y)πθ(y)=∑yπref(y)=1\mathbb{E}_{\pi_\theta}[u] = \sum_{y} \pi_\theta(y)\frac{\pi_\text{ref}(y)}{\pi_\theta(y)} = \sum_y \pi_\text{ref}(y) = 1 (assuming πθ>0\pi_\theta > 0 wherever πref>0\pi_\text{ref} > 0). And Eπθ[−log⁡u]=∑yπθ(y)log⁡πθ(y)πref(y)=KL(πθ∥πref)\mathbb{E}_{\pi_\theta}[-\log u] = \sum_y \pi_\theta(y)\log\frac{\pi_\theta(y)}{\pi_\text{ref}(y)} = \mathrm{KL}(\pi_\theta\Vert\pi_\text{ref}). So E[k3]=1+KL−1=KL\mathbb{E}[k_3] = 1 + \mathrm{KL} - 1 = \mathrm{KL}.

(c) Since ∂u/∂log⁡πθ=−u\partial u/\partial\log\pi_\theta = -u, we get ∂k3/∂log⁡πθ=−u+1=1−u\partial k_3/\partial\log\pi_\theta = -u + 1 = 1 - u. (i) u=0.5u = 0.5: k3=0.5+0.693−1=0.193k_3 = 0.5 + 0.693 - 1 = 0.193; derivative +0.5+0.5. The loss increases with log⁡πθ\log\pi_\theta, so gradient descent lowers the token’s probability, back toward the reference. (ii) u=2u = 2: k3=2−0.693−1=0.307k_3 = 2 - 0.693 - 1 = 0.307; derivative 1−2=−11 - 2 = -1. Gradient descent raises the token’s probability, toward the reference.

(d) The derivative is 1−πref/πθ1 - \pi_\text{ref}/\pi_\theta, which goes to −∞-\infty as πθ→0\pi_\theta \to 0 with πref\pi_\text{ref} fixed. Such a token is rarely sampled, but when it is, it gets a huge gradient. That is a source of high variance and instability. DeepSeek-V3.2’s report makes this point (plain k3k_3 gives unbounded weight to such tokens) and adds an importance-ratio correction. It is one reason many RLVR recipes use a tiny β\beta or none.

Exercise 15.6Design R1-Zero's format reward, then break itConcept●●○

R1-Zero rewards responses that put reasoning inside <think> </think> and the answer inside <answer> </answer>.

(a) Write precise rules for a format reward (in words or pseudocode) and say how you would combine it with the accuracy reward.

(b) List at least four ways a policy could earn format or accuracy reward without doing what you wanted, and a fix for each.

(c) Why did DeepSeek use rules rather than a neural model to judge format and correctness?

Hint
Think about empty tags, repeated tags, several candidate answers, text outside the tags, and what the accuracy checker extracts.
Solution

(a) One reasonable rule: the response must match ^<think>(.+?)</think>\s*<answer>(.+?)</answer>$ exactly once, with non-empty content in both, nothing outside the tags, and no nested or repeated tags. Format reward 1 if it matches, else 0. Accuracy reward: extract the single answer inside <answer> (for math, the contents of one \boxed{}), normalize, and compare. Total reward = accuracy + format, as in R1-Zero. Variations: give accuracy only if the format is valid (so unparseable answers cannot be lucky), or weight format lower so it is learned early but cannot dominate.

(b) Exploits and fixes:

  1. Empty or trivial thinking (<think> </think>) to collect the format reward cheaply. Fix: require non-trivial content, or accept that format reward is only a scaffold; accuracy will drive real reasoning.
  2. Several answers (<answer>12 or 13 or 14</answer>, or many boxed values), hoping the checker matches any. Fix: require exactly one answer; reject if more than one candidate is extracted.
  3. Answer outside the tags, or text after </answer> that the checker reads. Fix: anchor the regex, extract only from inside the answer tag.
  4. Formatting tricks for the normalizer (e.g. 85.0000001, \frac{170}{2}), if normalization is too lenient or too strict. Fix: a careful verifier with tests (Chapter 14 lab).
  5. Guessing on problems with few possible answers (yes/no, multiple choice): accuracy reward without reasoning. Fix: prefer problems with large answer spaces, or penalize wrong answers more than abstentions.
  6. Endless thinking that never closes the tag (often truncated at the length limit). Fix: treat truncation as format failure; some recipes add a soft length penalty (Chapter 16).

(c) The paper says neural reward models “may suffer from reward hacking in the large-scale reinforcement learning process”, and that retraining them costs resources and complicates the pipeline. A rule is transparent: when it is exploited, you can read the exploit and fix the rule. A neural judge’s blind spots are invisible until the policy finds them.

Exercise 15.7The pass@k debate in your own wordsConcept●●○

(a) A model is sampled n=10n = 10 times on a problem and is right c=2c = 2 times. Compute the unbiased pass@1, pass@3 and pass@10 estimates.

(b) Explain in a few sentences why GRPO, by its construction, has trouble creating solutions the base model never samples. Use the zero-signal formula.

(c) Give one argument that RLVR “only sharpens” and one that it can “expand”, each tied to evidence from the chapter.

(d) If you were evaluating a new RLVR method, what would you measure besides pass@1?

Hint
For (a), (n−ck)/(nk)\binom{n-c}{k}/\binom{n}{k} is the probability that a random kk-subset of your 10 samples contains only wrong ones; what is (810)\binom{8}{10}? For (b), expand 1−pG−(1−p)G1 - p^G - (1-p)^G for small pp.
Solution

(a) pass@k=1−(8k)/(10k)k = 1 - \binom{8}{k}/\binom{10}{k}. pass@1 =1−8/10=0.2= 1 - 8/10 = 0.2. pass@3 =1−(83)/(103)=1−56/120=0.533= 1 - \binom{8}{3}/\binom{10}{3} = 1 - 56/120 = 0.533. pass@10 =1−(810)/(1010)=1−0=1= 1 - \binom{8}{10}/\binom{10}{10} = 1 - 0 = 1 (all ten samples include the two correct ones).

(b) GRPO’s policy gradient comes only from groups with mixed rewards. A prompt the model solves with probability pp produces such a group with probability 1−pG−(1−p)G≈Gp1 - p^G - (1-p)^G \approx Gp for small pp. If pp is essentially zero, there are no correct samples to push up, and pushing down wrong answers only spreads probability among other wrong answers. So the gradient can only reinforce solutions inside the model’s current support, unless generalization from other prompts lifts this one into range (the “shared skill” in the second demo).

(c) “Sharpens”: Yue et al. (2025) found base models reach higher pass@k than their RL-trained versions at large kk across many settings, and the lab’s TinyLM shows the same crossover. Entropy falls during GRPO, concentrating probability on fewer solutions. “Expands”: ProRL reports gains at all kk after prolonged, KL-controlled training with reference resets and diverse tasks, including on tasks where the base model always failed. Wen et al. argue answer-only pass@k overcounts lucky base-model guesses. Also, generalization across prompts (as in the demo) can bring previously unsolvable problems into range.

(d) pass@k for large kk (coverage), policy entropy over training, performance on held-out and uncontaminated problems, results on more than one base-model family, response length, and for reasoning tasks some check of the reasoning itself, not only the final answer.

Exercise 15.8Explore the demosExplore the demo●○○
  1. In the group explorer, with GRPO advantages, find a group of size G=8G = 8 in which a single response gets an advantage above +2.5+2.5. What is the exact value? Which group of size 8 gives the most negative advantage?
  2. Set G=4G = 4 and p=0.9p = 0.9. Press Resample twenty times and count the groups with signal. Compare with the chart’s prediction.
  3. In the prompt-pool demo, with default settings (press Reset first), at roughly what iteration does the 20-iteration average of zero-signal groups first exceed 90%? Step with +10 iterations and watch the readout. How many prompts are still out of reach at that point?
  4. Switch the shared skill off. Which prompts never learn, and what is the final mean accuracy? Explain in one sentence.
Solution
  1. One correct answer out of eight: A^=(G−k)/k=7=+2.65\hat A = \sqrt{(G-k)/k} = \sqrt 7 = +2.65. The most negative advantage is the mirror image: seven correct and one wrong gives the wrong answer −7=−2.65-\sqrt 7 = -2.65.
  2. The chart gives P(signal)=1−0.94−0.14=0.344P(\text{signal}) = 1 - 0.9^4 - 0.1^4 = 0.344, so expect about 7 of 20. Your count will vary (it is binomial with standard deviation about 2).
  3. The demo uses a fixed random seed, so with the default settings you should see the same run we did: the 20-iteration average of zero-signal groups passes 90% at about iteration 80, when mean accuracy is about 0.6 and 7 prompts are still out of reach. By iteration 400, accuracy is 0.91 and only 1 prompt is out of reach, yet more than 90% of groups are still wasted. Most of the remaining progress comes from the few prompts in the middle of their learning curve.
  4. The 8 hardest prompts on the right stay pinned near zero, and accuracy plateaus at about 0.62 instead of passing 0.9. Without a shared parameter, a prompt that is never solved never produces a non-zero advantage, so nothing ever moves it.
Exercise 15.9Build GRPO: the labCode●●○

In the lab exercises/15-rlvr-grpo/, open grpo.py and implement five functions, in order. Run the tests for one task at a time with python -m pytest -q -k task1.

  1. Task 1, sample_group: repeat each prompt GG times (consecutively), sample with tinylm.sample, decode, and score with the verifiable reward.
  2. Task 2, group_advantages: the group-relative advantages, with and without std division. The tests include this chapter’s worked examples.
  3. Task 3, k3_kl: the per-token k3k_3 estimator. A test samples 200,000 tokens and checks that it is unbiased.
  4. Task 4, grpo_loss: the clipped per-token objective minus βk3\beta k_3, masked, averaged per response and then over responses, negated. Tests check the value and the gradient on a hand-computed batch (including which tokens are clipped), padding, and that a zero-signal group gives exactly zero gradient.
  5. Task 5, grpo_step: one iteration (sample, score, advantages, frozen old and reference log-probs, inner_steps gradient steps). The last test trains for 100 iterations from the SFT checkpoint and expects sampled accuracy to rise by at least 6 points.

Then run python run.py (about a minute) and look at grpo_tinylm.png.

Hint
The most common bugs: computing old_logp after the first update (then the ratio is not 1 on the first step); averaging over all tokens in the batch instead of per response first; forgetting the mask, so padding tokens enter the average; and letting gradients flow into old_logp or ref_logp (compute them under torch.no_grad()).
Solution

The reference solution is in solutions/grpo.py. The key lines:

# Task 2: reshape to (P, G); population std; eps keeps all-equal groups at 0
r = rewards.view(-1, G)
adv = r - r.mean(dim=1, keepdim=True)
if scale_std:
    adv = adv / (r.std(dim=1, unbiased=False, keepdim=True) + eps)
return adv.reshape(-1)

# Task 3
d = ref_logp - logp
return torch.exp(d) - d - 1.0

# Task 4
ratio = torch.exp(logp - old_logp)
A = adv[:, None]                                   # same advantage for every token
surrogate = torch.minimum(ratio * A, torch.clamp(ratio, 1 - clip_eps, 1 + clip_eps) * A)
per_token = surrogate - beta * k3_kl(logp, ref_logp)
per_response = (per_token * mask).sum(1) / mask.sum(1).clamp(min=1)
loss = -per_response.mean()

grpo_step computes old_logp and ref_logp once under torch.no_grad(), before the inner loop, then for each inner step recomputes logp with gradients, calls grpo_loss, and takes an optimizer step with gradient-norm clipping.

What you should see from run.py (default settings, 300 iterations, about a minute on a laptop): sampled accuracy on 500 held-out problems rising from about 0.51 to about 0.8, greedy accuracy from about 0.76 to about 0.9, the per-token KL to the reference climbing to roughly 0.1–0.2 (with spikes: k3k_3 on single samples is heavy-tailed), the policy’s entropy falling from about 0.34 to about 0.14 nats per token, and the fraction of zero-signal groups rising from about 10% to about 40% as more prompts become easy.

Exercise 15.10Experiments with your GRPOCode●●●

With your working lab, run these experiments. Before each, write down what you expect.

  1. Why the clip? python run.py --inner-steps 8 --out clip.png versus python run.py --inner-steps 8 --clip 1000 --out noclip.png. Compare the KL and the accuracy curves.
  2. Tiny groups. python run.py --G 2 --prompts 64 --out g2.png uses the same number of samples per iteration as the default (64×2=16×864 \times 2 = 16 \times 8). What fraction of groups carries signal? How does learning compare?
  3. The pass@k debate in miniature. After a default python run.py, run python passk.py. Do the curves cross? Where? How many problems does each model never solve in 64 tries?
Hint
For experiment 2, compute 1−p2−(1−p)2=2p(1−p)1 - p^2 - (1-p)^2 = 2p(1-p) at p=0.5p = 0.5 and p=0.8p = 0.8 before you look at the plot.
Solution

Reference results from our runs (your numbers will differ somewhat):

  1. With 8 inner steps and the clip, training was stable: sampled accuracy reached about 0.75 and greedy about 0.83 after 300 iterations, with the KL mostly between 0.1 and 0.3. That is a little below the default of 2 inner steps (0.82 and 0.91), so reusing each batch more does not pay at this scale. Without the clip, the KL repeatedly jumped to 0.7–1.0, greedy accuracy fell from 0.76 to about 0.52 within the first 10 iterations, and after 300 iterations sampled accuracy was only 0.70 (greedy 0.75, below where it started). Reusing a batch eight times without a trust region lets the policy run away from the data that justified the update, the failure Chapter 9 was built to prevent.
  2. With G=2G = 2, a group has signal with probability 2p(1−p)2p(1-p): 50% at p=0.5p = 0.5, 32% at p=0.8p = 0.8. In our run, about 60% of groups were wasted at the start and about 75% by the end (compare roughly 10% and 40% with G=8G = 8). Learning was nonetheless comparable per sample, even slightly better (sampled accuracy 0.84 after 300 iterations, versus 0.82 for the default): many small groups across 64 prompts give a diverse batch, and each informative pair is a clean “this one, not that one” comparison. Small groups are wasteful but not useless. The waste grows as accuracy rises.
  3. In our run the curves crossed between k=8k = 8 and k=16k = 16. GRPO improved pass@1 from 0.53 to 0.83 and pass@2 from 0.75 to 0.92, but at k=64k = 64 the SFT model was slightly ahead (0.983 vs 0.977 over 300 problems), and GRPO never solved 7 problems versus 5 for SFT. The effect at large kk is small, two problems out of 300, so treat it as suggestive: rerun with another --seed in run.py and see whether the crossing survives. Its direction matches Yue et al., and the falling entropy in grpo_tinylm.png is the mechanism: the policy concentrates on its favourite answers.

Files: grpo.py, test_grpo.py, run.py, passk.py, tinylm.py, README.md, colab_grpo_trl.md

cd 15-rlvr-grpo
python -m pytest -q          # your code: tests fail until you fill in the TODOs
RL_SOLUTIONS=1 python -m pytest -q   # reference solutions: all pass

First time? See Exercises & setup.

Further reading

Next, Chapter 16 takes GRPO apart knob by knob (baseline, normalization, aggregation, clipping, KL) and shows that RLOO, Dr. GRPO, DAPO, GSPO and CISPO are all the same estimator with different settings.