Part II · Deep RL · Chapter 7
Policy gradients and REINFORCE
Optimize the policy directly. The log-derivative trick, baselines, and variance.
Here is a puzzle. You have a policy with a knob . Turn the knob and the policy’s action probabilities change. You run the policy, it rolls a die to pick an action, the world responds, and at the end you get a score. You want to turn the knob in the direction that raises the average score. So you want a gradient. But the score depends on only through a dice roll, and the world in between is a black box you cannot differentiate. It might be a physics simulator, a human clicking thumbs-up, or a unit test that passes or fails. How do you take a derivative through a dice roll?
The answer is one line of calculus, the log-derivative trick, and it is the foundation of almost everything from here to the end of the course. In Chapter 6 you learned a value function and acted by taking the argmax. In this chapter you skip the middleman: you write down a policy and climb the expected return directly. The algorithm you will build, REINFORCE, is more than thirty years old. It is also, with a better baseline, the core of the methods used to train today’s reasoning models.
Why learn the policy directly?
DQN learns how good each action is, and the policy is implied: pick the action with the largest . That works well for Atari. It has three limitations that matter.
Continuous actions. A robot arm chooses torques, real numbers. To act greedily you would have to solve over a continuum at every step, which is itself an optimization problem. A policy that outputs “a Gaussian with this mean and width” just samples.
Discontinuity. The greedy policy jumps. If and are close, a tiny change in the network flips the action from always-left to always-right. Small parameter changes cause large behavior changes, which makes learning jittery. A parameterized stochastic policy changes smoothly: nudge and the probabilities move a little.
Sometimes the best policy is random. In rock-paper-scissors against an opponent who adapts, any deterministic policy loses; the best you can do is play each move with probability 1/3. The same thing happens when the agent cannot tell two states apart. In Sutton and Barto’s “short corridor” example, two states look identical to the agent but the actions have opposite effects in them. Every deterministic policy loops forever, and the best policy goes right with probability about 0.59. A greedy-over- agent can only express deterministic policies (plus ε of noise it does not choose).
There is a fourth reason, the one that matters most for this course: a language model is already a policy. It outputs a probability distribution over the next token, it is differentiable in its parameters, and it is very good before RL even starts. Nobody trains a -function over 100,000 tokens and takes an argmax. You start from the policy you have and improve it.
Policies with knobs
Softmax policies for discrete actions
Give each action a real-valued score , called a logit (later, a neural network will compute the logits from the state). Turn the logits into probabilities with the softmax:
Physicists will recognize the Boltzmann distribution: action is a state with energy at temperature 1. Dividing all logits by a temperature makes the policy greedier as and more uniform as . That is exactly how sampling temperature works in a language model (Chapter 11). One property will matter later: adding the same constant to every logit changes nothing, since it cancels in the ratio.
Gaussian policies for continuous actions
For a real-valued action, let the policy be a normal distribution whose mean (and maybe width ) comes from a network:
Everything in this chapter works for both kinds. We will mostly use the softmax because you can check every number by hand.
The objective
The quantity to maximize is the expected return of the policy,
where is an episode generated by running in the environment, and is its return. In a bandit (one step, no state) this is just the average reward: , where is arm ‘s true mean reward, as in Chapter 2.
A worked example you will see all chapter
Take a 3-armed bandit with mean rewards , , , and start from logits . The policy is uniform, , and
Because you know here, you can differentiate directly. Using (differentiate the softmax quotient; the next section derives the same fact in log form, and Exercise 7.2 does it in full), you get
Read it in words: raise the logit of every arm that is better than the current average, in proportion to how often you play it. At the uniform policy:
Arm 3 goes up, arm 1 goes down, and arm 2 (slightly below average) goes down a little. Keep these three numbers in mind.
The trouble is that a real agent does not know . It can only pull arms and see noisy rewards. So the question becomes: can you get , on average, from samples alone?
The log-derivative trick
The identity
Write the objective generically as an expectation of some score over samples from a distribution that you control:
The parameters sit inside the distribution, not inside . Differentiate, and use (that is just the chain rule for , read backwards):
That last line is the whole trick. The gradient of an expectation becomes an expectation of something you can compute for each sample. Draw from your own policy, compute , and average. You never differentiate , so can be a black box, discontinuous, or a 0/1 pass/fail signal.
The vector is called the score function (statisticians’ name, from maximum likelihood), and this estimator is called the score-function or likelihood-ratio estimator. In RL it goes by REINFORCE.
The score of a softmax policy
For the softmax, . Differentiating with respect to :
where is the one-hot vector for action . There is a nice picture here. Both and are points of the probability simplex (the triangle of all distributions over 3 arms). So the score of action is the arrow from where your policy is now to the corner “always play ”. The demo below draws these three arrows as dashed lines in the triangle. (The components of sum to zero, so the score, and every gradient in this chapter, lives in a two-dimensional plane. That is what lets the demo draw it flat.)
Back to the worked example
At the uniform policy the three possible scores are
Suppose rewards are noiseless for now, so arm always pays . A single pull gives one of three possible gradient estimates :
| You pull | Probability | Reward | Estimate |
|---|---|---|---|
| arm 1 | 1/3 | 1 | |
| arm 2 | 1/3 | 2 | |
| arm 3 | 1/3 | 4 |
Every single estimate is wrong; none of them is . Average them with weights 1/3:
Exactly the true gradient. The estimator is unbiased: right on average, noisy every time. Look at how noisy: the true gradient has length about 0.72, while a single estimate has length between 0.82 and 3.3. How to tame that noise is the second half of this chapter.
Notice also something odd about the arm-1 row. Arm 1 is the worst arm, yet pulling it gives an estimate that raises arm 1’s logit, because its reward (1) is positive. Every pull pushes the arm you pulled up; good arms just get pushed harder. Hold that thought until the section on baselines.
Quick check For a softmax policy, what is the average of the score e_a − π over actions a drawn from π itself?
Σ_a π(a)(e_a − π) = π − π = 0. In general E[∇ log π] = Σ ∇π = ∇ Σ π = ∇1 = 0. The score alone carries no signal on average; only its correlation with the reward does. This fact is what makes baselines work.
The score of a Gaussian policy
For with parameter ,
Sample and get a good reward, and the update moves toward . Get a bad reward, and moves away, provided “good” and “bad” are measured relative to some reference level, which is again the baseline story. Exercise 7.3 does the width as well.
From one action to whole episodes: the policy gradient theorem
A bandit has a single action. An episode has many, and between them the environment moves the state around according to dynamics you do not know. Apply the same trick with , the whole trajectory, and :
What is the probability of a trajectory? Start state, then alternately the policy picks an action and the environment picks the next state:
Take the log, and the product becomes a sum:
Now take . The start distribution and the transition probabilities do not depend on , so their gradients are zero. Only the policy terms survive:
Putting it together gives the policy gradient theorem in its trajectory form:
Stop and appreciate what just happened. The environment’s dynamics dropped out. You need to sample from (run the episode), but you never need to know , write it down, or differentiate it. The physics simulator, the opponent, the human rater, the code interpreter: all black boxes. The only things you differentiate are your own log-probabilities, which you control. This is why policy gradients apply to almost anything you can run, and why they work for language models whose “environment” is a reward model or a verifier.
∂ The policy gradient theorem, carefully
Setup: episodes of length at most (or discounted, so returns are bounded), a policy differentiable in for every , and rewards drawn from some distribution depending on but not on . Write .
- The objective is an integral over trajectories (sums for discrete parts):
- Under the conditions above (bounded , finite horizon, smooth ), you can move the gradient inside the integral (dominated convergence):
Note that itself has no in it: once the trajectory is fixed, its return is fixed.
- Wherever , . Where in a neighbourhood, the gradient is zero too. So
- The trajectory density factorizes. Including the reward densities :
- In , every factor except is constant in , so
- Substituting into step 3 gives the theorem.
What the proof needs: you can sample from the environment, the policy is differentiable and gives positive probability to the actions it takes, and the environment does not depend on except through your actions. What it does not need: a model, differentiable rewards, or differentiable dynamics.
Quick check Why do the transition probabilities P(s′ | s, a) not appear in the policy gradient?
log p_θ(τ) = log p(s₀) + Σ log π_θ(a_t | s_t) + Σ log P(s_{t+1} | s_t, a_t). Only the policy terms depend on θ. You still need P to generate samples (you run the environment), but never to compute the gradient.
REINFORCE
Replace the expectation by an average over episodes and you have an algorithm. Williams (1992) named it REINFORCE (an acronym: “REward Increment = Nonnegative Factor × Offset Reinforcement × Characteristic Eligibility”; nobody remembers that, everybody remembers the name).
REINFORCE (vanilla, with the whole-episode return)
initialise policy parameters θ
repeat:
1. run the current policy π_θ for N episodes; record (s_t, a_t, r_t) for each
2. for each episode, compute its return G_0 = Σ_t γ^t r_t
3. ĝ = (1/N) Σ_episodes Σ_t G_0 · ∇_θ log π_θ(a_t | s_t)
4. θ ← θ + α ĝ
5. throw the episodes away (they came from the old θ)
Step 5 is not a detail. The expectation in the theorem is over trajectories from the current . After one update, the old episodes come from a different policy, and reusing them naively gives a biased gradient. REINFORCE is on-policy: every update needs fresh samples. Reusing old samples correctly needs importance ratios, which is the subject of Chapter 9.
How you actually code it: a surrogate loss
In PyTorch you don’t assemble by hand. You build a scalar whose gradient is and call backward():
logits = policy(states) # (N, n_actions)
logp = torch.log_softmax(logits, -1) # log π(· | s_t)
logp_taken = logp.gather(1, actions[:, None]).squeeze(1) # log π(a_t | s_t)
loss = -(weights.detach() * logp_taken).mean() # weights = G_0, G_t, or G_t - b
optimizer.zero_grad(); loss.backward(); optimizer.step()
The gradient of with the weights held constant is , exactly minus the REINFORCE estimate. Gradient descent on this loss is gradient ascent on .
Reward-to-go: don’t blame an action for the past
Vanilla REINFORCE multiplies the score of every action in an episode by the same number . Think about what that means. An action at step 50 gets credit for rewards collected at steps 0 to 49, before it was taken. It could not possibly have caused them. Those rewards are pure noise as far as the step-50 action is concerned: on average they contribute nothing, but in any one episode they jostle the estimate.
The fix is to weight each action only by the rewards that come after it, its reward-to-go:
This is still exactly the gradient: no approximation, just fewer noise terms. The reason is the fact you met in the first quiz. Conditioned on everything up to , the score of has mean zero, so multiplying it by anything already determined (like an earlier reward) gives zero on average.
∂ Why dropping past rewards keeps the estimator unbiased
Write and , the history up to state but not including .
- The score has zero mean given the state:
(This uses the Markov property: given , the action is drawn from .)
- Take a reward from the past, with . It is a function of . By the tower rule (the law of total expectation, when is fixed by ),
- Expand the vanilla estimator . All terms with have expectation zero by step 2. Dropping them leaves
The terms we dropped have zero mean but nonzero variance. Removing a zero-mean term from changes the variance by , which is a reduction unless is negatively correlated with the kept terms strongly enough, so this is not a theorem. In practice, reward-to-go almost always reduces the variance a lot.
So the improved estimator is
On CartPole, which you will train in the lab, this one change takes REINFORCE from barely learning to balancing the pole for hundreds of steps in most runs, with the same number of episodes.
Baselines: same gradient, much less noise
The problem: everything gets pushed up
Go back to the bandit and shift every reward by , so the arms pay 11, 12 and 14. Nothing about the problem has changed: arm 3 is still best by the same margins, and is still (the offset cancels in ). But now every single estimate has . Whichever arm you pull, its logit gets a big push up. The true gradient emerges only as a small difference between large, nearly cancelling pushes. In CartPole every reward is , so every action in every episode gets pushed up; the good actions are only distinguished by being pushed up slightly more.
You can measure the damage with the total variance of one estimate, (the trace of its covariance matrix: the mean squared distance of a dot from the true gradient). The demo below calls it the spread. For the uniform policy, for every arm, so
With rewards 1, 2, 4: , so the variance is . With rewards 11, 12, 14: , and the variance is about 102. Same gradient, 25 times the noise.
The fix: subtract a baseline
Measure each reward relative to a reference level , the baseline:
Now an action is pushed up only if it did better than , and pushed down if it did worse. Is this still the right gradient? Yes, by the same zero-mean fact, as long as does not depend on the action :
The baseline can depend on the state, on the time step, on anything from the past, even on other independent episodes. It must not depend on the action whose score it multiplies; Exercise 7.4 shows what goes wrong if it does.
Back to the worked example, with (rewards 1, 2, 4):
| You pull | Estimate | |
|---|---|---|
| arm 1 | ||
| arm 2 | ||
| arm 3 |
The average is still ; check it. But now pulling arm 1 pushes arm 1 down, as it should. The variance is , down from 4.15, an 8-fold reduction. With the offset, gives the same , down from 102. The baseline makes the estimator blind to the offset, which is what you want, because the offset never carried information.
Which baseline is best?
A natural choice is the average return, , or, when there are states, , the expected return from . Then is an estimate of the advantage : how much better this action turned out than the policy’s average from that state. Learning well enough to use as a baseline (and then using it for more than that) is what Chapter 8 is about.
is close to the best constant, but not exactly the best. Minimizing the variance over gives a score-weighted average of the rewards.
∂ The minimum-variance constant baseline
Consider a single-sample estimate , where and is the reward (or return). We want the constant minimizing the total variance .
- Since for every , the variance is
- This is a quadratic in . Differentiate and set to zero:
- Solve:
The second derivative is , so this is a minimum.
So is an average of the rewards, weighted by how large the score was on each sample. If all scores have the same size, . That happens at the uniform softmax policy (every ), so in the worked example exactly. Away from uniform, rarely chosen actions have larger scores and count more; Exercise 7.6 works out a two-arm case where the answer is surprising.
If you allow a different baseline for each parameter component , the same computation gives . In practice nobody uses these exactly: a learned is close enough, and it adapts to the state.
See it
The demo below is the worked example, live. The first panel is the probability triangle. The large dot is the current policy (tap or drag to move it), the dashed lines run from it to the three corners (the three possible scores ), and the orange arrow shows which way a small step along the true gradient moves the policy. The second panel shows single-sample gradient estimates as dots, colored by the arm that was pulled, together with the true gradient (solid orange arrow) and the mean of the dots so far (dashed arrow). It is drawn in the same orientation as the triangle, so “raise arm 3” points up. Each dot lies on the dashed spoke of the arm that was pulled, parallel to that arm’s dashed line in the triangle, at distance from the centre. The strip plot below the baseline slider shows the exact spread of one estimate as a function of (log scale), with markers at and ; the orange dot is your current .
What to try: (1) Press +25 a few times and watch the dashed mean arrow settle onto the solid true gradient: unbiased, but noisy. (2) Press b = J(θ): every dot slides along its own spoke toward the centre. The true gradient does not move; the spread drops from 4.15 to 0.52. (3) Set c = 10 and b = 0. The dots fly off the chart (press Zoom out to find them), and the spread is about 100. Now press b = J(θ). (4) Drag the policy near a corner and compare the b = J and b = b* buttons. They differ; Exercise 7.6 explains why.
Quick check You add +10 to every reward of an environment and run REINFORCE without a baseline. What happens to the gradient estimate?
The offset adds 10·∇ log π to each estimate. That term has mean zero (the score has mean zero), so the expectation is unchanged. But it is large and random, so the variance balloons: about 4.15 to 102 in the worked example. A baseline of about J removes it.
REINFORCE in action, and why it is not enough
Here is the full algorithm as practitioners usually run it.
REINFORCE with reward-to-go and a baseline
initialise policy π_θ and a baseline (a running average, or a small value network V_φ)
repeat:
1. run π_θ for a batch of episodes
2. for every step t of every episode:
G_t = r_t + γ G_{t+1} (backward pass, G_T = 0)
Â_t = G_t − b(s_t) (advantage estimate)
3. loss = −mean_t [ Â_t · log π_θ(a_t | s_t) ] (Â_t held constant)
4. one gradient step on the loss
5. update the baseline toward the new returns (e.g. regress V_φ(s_t) on G_t)
The demo below runs it on the 3-armed bandit, one pull per update: 12 runs without a baseline (orange) and 12 runs with a running-average baseline (blue), from the same start and with the same random seeds. The paths show how each run’s policy moves across the probability triangle.
Each step pulls one arm and updates θ by α(R − b)(e_a − π), with reward noise σ = 1. Orange runs use b = 0; blue runs use b = the running average of the rewards seen so far (it starts at 0). What to try: press Play at c = 5 (rewards about 6, 7, 9). Then try c = 0, and c = 15. Tap near the arm-2 corner to start from a bad policy. Raise α. Count the orange runs that end up stuck in the wrong corner.
Two lessons are hiding in that demo, and both foreshadow the rest of Part II.
Unbiased is not the same as safe. Without a baseline, whichever arm you happen to pull gets reinforced, so early luck compounds: the policy drifts toward an arbitrary corner. Once it is nearly deterministic on arm 2, it almost never tries arm 3 again, and the true gradient there is nearly zero anyway ( is tiny when is tiny). The run is stuck. The estimator was correct on average at every single step; the finite step size plus high variance did the damage. In the demo with and , 5 of the 12 no-baseline runs end up committed to a wrong arm after 400 steps (other random seeds give 3 to 5), and none of the 12 baseline runs do.
The fundamental costs of REINFORCE are:
- High variance. Even with reward-to-go and a baseline, one episode’s return is a noisy measure of how good each action was. Noise forces small learning rates and many samples. A learned critic cuts it further (Chapter 8).
- Sample inefficiency. On-policy: every batch is used for one gradient step, then thrown away. Squeezing several steps out of one batch safely needs importance ratios and a trust region (Chapter 9).
- Fragile steps. One overly large step can make the policy nearly deterministic, and then it stops exploring and can’t collect the data it would need to recover. The demo’s stuck runs are a small version of this. In LLM training the same thing shows up as entropy collapse (Chapter 19).
- Credit assignment. Every action in a long episode shares the noise of the whole return-to-go. The longer the episode, the worse.
Two practical tricks you will see in every codebase. Batching: average over several episodes per update. Return normalization: subtract the batch mean of the weights and divide by their standard deviation. Subtracting the mean is a baseline (estimated from the same batch, so it is very slightly biased); dividing by the standard deviation just rescales the step size per batch.
From CartPole to language models
Everything above carries over to a language model with almost no change. Take a prompt . The model samples a response one token at a time. The probability of the whole response is the product of the next-token probabilities, so its log-probability is a sum of token log-probabilities, and so is its gradient:
That is the trajectory form of the policy gradient theorem, with state and action . The “environment” is trivial (appending a token is deterministic), and usually the only reward is a single number at the end: a reward model’s score, or 1 if the final answer is correct. With and one terminal reward, every token’s reward-to-go is just . So REINFORCE for a language model is
Every token in a good response is pushed up by the same amount; every token in a bad response is pushed down. And the variance problem is acute: one scalar reward is spread over hundreds or thousands of tokens.
So everything hinges on the baseline. Sample a group of responses to the same prompt and suppose they get rewards . Using the group mean as the baseline, , the weights are : correct answers pushed up, wrong ones pushed down. Using the leave-one-out mean (the average of the other three responses) for each response instead, the weights are for the correct ones and for the wrong ones. That is RLOO. If you divide the group-mean version by the group’s standard deviation (0.5 here), you get , and that is the advantage used by GRPO. (Some implementations use the sample standard deviation, , which gives ; Chapter 15 discusses such details.)
Quick check A 5-token response gets reward 1, and the baseline for its prompt is 0.25. In plain REINFORCE with γ = 1, how are the five tokens' log-probabilities weighted?
With γ = 1 and a single terminal reward, every token's reward-to-go equals the final reward, so every token's score is multiplied by r − b = 0.75. (Whether the loss is then averaged per token or per sequence is a separate choice; Chapter 16 shows it matters.)
Summary
- A policy gradient method parameterizes the policy directly and does gradient ascent on the expected return . It handles continuous actions, changes smoothly, can represent stochastic optimal policies, and fits language models, which are already policies.
- The log-derivative trick, , turns the gradient of an expectation into an expectation you can sample. need not be differentiable.
- For trajectories the dynamics drop out: . You need samples from the environment, never its model.
- For a softmax policy the score is : the arrow from the current policy toward always playing .
- REINFORCE is weighted maximum likelihood on your own samples. In code it is the surrogate loss with the weights detached. It is on-policy.
- Reward-to-go and baselines remove terms with zero mean and nonzero variance. Both keep the estimator unbiased because the score has zero mean given the state. A baseline must not depend on the action.
- A good baseline is about the expected return (, leading to the advantage); the exact minimum-variance constant is a score-weighted average of returns. A baseline is a control variate.
- REINFORCE’s weaknesses (variance, one step per batch, fragile steps) motivate actor-critic (Chapter 8) and PPO (Chapter 9). Its strengths (no critic, black-box rewards) are why RLOO and GRPO are REINFORCE at heart.
Exercises
For each problem, say what makes “learn , act greedily” awkward or wrong, and what a parameterized stochastic policy does instead.
- A robot arm that outputs three joint torques, each a real number in .
- Rock-paper-scissors against an opponent that learns to exploit any pattern in your play.
- A language model choosing the next token from a vocabulary of 100,000.
Solution
- Acting greedily means solving at every step, a nonconvex optimization over a continuum, inside the training loop. A Gaussian policy outputs a mean and width and samples an action in one forward pass, and its log-probability is differentiable in .
- Every deterministic policy, and every greedy policy, is exploitable: once the opponent learns what you will play, you lose every round. The optimal (Nash) strategy is uniformly random, which a softmax policy represents exactly with equal logits, and a greedy-over- policy cannot represent at all (ε-greedy adds randomness, but not a chosen amount).
- The action space is huge and the “state” (the text so far) is never seen twice, so learning accurate -values for every token is hopeless. But the model already is a softmax policy over tokens, pretrained to be very good. Policy gradients improve it in place.
Let with temperature .
- Show that .
- Show that the components of the score sum to zero, and explain why that had to be true.
- Show that .
- At and , compute the score of action 3. What happens to its size as , and what does that suggest about learning with a very low temperature?
Hint
Solution
-
. Then , and . Subtract.
-
. It had to be: adding the same constant to every logit leaves unchanged, so the directional derivative of along is zero, and that directional derivative is the sum of the components.
-
for every . (This is the general fact .)
-
At : , with squared length . At the policy is uniform for every , so the score simply grows like : a lower temperature amplifies every update, like a larger step size. With unequal logits it gets worse. As the policy becomes nearly deterministic. The likely action’s score goes to zero (it is already certain), while an unlikely action’s score has size of order , so on the rare occasions it is sampled it produces a huge estimate. Learning at very low temperature combines vanishing gradients for likely actions with rare, enormous ones for unlikely actions: very high variance. This is one reason RL for LLMs usually samples at temperature about 1.
Let with parameters and (parameterizing by keeps positive).
- Compute and .
- Check that both have mean zero under .
- With , , you sample and get return . The baseline is , and the step size is . Compute the REINFORCE update of and , and say in words what the policy learned.
Hint
Solution
-
. For : , and , so .
-
because . .
-
. Scores: , and . Updates: , and , so becomes . The mean moves toward the action that beat the baseline. The width grows, because a better-than-expected outcome came from far out in the tail (more than one standard deviation away), which suggests exploring more widely. A good outcome from close to the mean () would have shrunk instead.
- Prove that for any function , .
- Now cheat: in the 3-armed worked example (uniform policy, noiseless rewards 1, 2, 4), use an action-dependent “baseline” . Compute the expected estimate . Compare with .
- Use for arms 1 and 2 and for arm 3. Compute the expected estimate and show it is biased.
Hint
Solution
-
. Pulling out of the sum is the step that needs not to depend on .
-
With noiseless rewards , so for every arm: every estimate is exactly zero, and so is its expectation. The true gradient is . The “baseline” removed all of the signal, because the signal is the difference between arms. (With an action-dependent baseline you can correct the bias by adding back analytically; that is the idea behind some “action-dependent control variate” methods. Without the correction, it is just wrong.)
-
The estimates are arm 1: ; arm 2: ; arm 3: . The average is , not . The bias is . Here it happens to point roughly the right way, but in general a biased estimator can converge to the wrong policy.
A tiny MDP has two states, A and B, each with actions left and right. The policy is tabular softmax: each state has its own two logits, all initially 0. One episode is: in A take right, receive , move to B; in B take left, receive , episode ends. Use and step size .
- Compute the update to all four logits using vanilla REINFORCE (every action weighted by ).
- Repeat with reward-to-go weights .
- Repeat with reward-to-go and a constant baseline .
- In each case, what is the new probability of
leftin state B? Which update is the most sensible, and why?
Hint
right with respect to that state’s logits (left, right) is , and the score of left is . The other state’s logits get zero.Solution
Returns: , and .
-
Both actions are weighted by . State A (took
right): . State B (tookleft): . -
Step 0 gets , the same as before: . Step 1 gets : .
-
Weights and . . .
-
: (1) ; (2) ; (3) .
Vanilla REINFORCE made left in B more likely, even though it earned nothing: it got credit for the reward collected in A before it was taken. Reward-to-go removes that false credit. With a baseline, earning 0 is below the expected level, so left in B becomes less likely, while right in A, which earned more than expected, is still reinforced. All three are unbiased estimates of the same gradient; the third assigns credit most sensibly. (With the exact factor, step 1’s weight would be rather than ; with this changes only part 3, to .)
Take a 2-armed bandit with a softmax over two logits and policy . Rewards are noiseless: arm 1 pays , arm 2 pays .
- Compute the squared norm of the score for each arm.
- Use the minimum-variance formula to show that .
- Compare with . When are they equal? Explain in words why the optimal baseline weights each arm by the probability of the other arm.
- With , , : compute , , and the variance of a single estimate at , and .
Hint
Solution
-
and .
-
Numerator: . Denominator: . The ratio is .
-
They are equal when (or ). The variance comes from . The rare arm is sampled rarely, but when it is, its score is large ( for arm 2 is near 2 when is near 1), so its term dominates the variance. The best baseline therefore sits close to the rare arm’s reward, to shrink its huge contributions, even though that makes the common arm’s (small) contributions slightly larger. This is why the demo’s b* button differs from J away from the uniform policy.
-
, . The gradient: , so . Score norms: arm 1 , arm 2 .
- : , so the variance is .
- : ; variance .
- : ; variance .
With two arms and noiseless rewards, makes every estimate exactly equal to , so the variance is zero. More striking: is 64 times worse than no baseline at all here. “Use the average reward” is a good rule of thumb, not a theorem.
The policy gradient theorem never uses or .
- What does REINFORCE need from the environment? List everything.
- Suppose you had a perfect differentiable simulator: you know , and the reward is a smooth function of the state. Describe a different way to get , and why it might have lower variance.
- A coding model is rewarded 1 if its program passes all unit tests and 0 otherwise. Explain why the method in part 2 is unavailable here and REINFORCE is not.
Solution
-
The ability to (a) reset to a start state drawn from , (b) execute an action and observe the next state and reward, many times, under the current policy. Plus the ability to compute for your own policy. No model, no reward derivatives, no knowledge of what the dynamics are.
-
With a differentiable simulator and a reparameterized policy (actions ), you can backpropagate the return through the whole rollout: through the reward, through the dynamics , into . This pathwise gradient uses the derivative of the reward with respect to actions, information the score-function estimator ignores, and so often has much lower variance. (It has its own problems: chaotic dynamics give exploding gradients over long horizons.)
-
The reward is a step function of a discrete output: tokens are discrete, so there is no through sampling, and “pass/fail” has zero derivative almost everywhere. There is nothing to backpropagate through. REINFORCE only needs the reward’s value for each sample and the gradient of the model’s own log-probabilities, both of which are available. This is why RL with verifiable rewards (Chapter 15) is built on policy gradients.
You sample responses to a prompt; a verifier gives , and of them are correct.
- Show that the no-baseline REINFORCE estimate equals times the average gradient of over the correct responses, which is the gradient of supervised fine-tuning on your own correct samples, scaled by the success rate .
- Now use the baseline . Write the weight on a correct response and on an incorrect one. What does the baseline add that filtered fine-tuning lacks?
- For responses with rewards 1, 0, 0, 1, write the four weights with and without the baseline. What happens when all four rewards are 1?
Hint
Solution
-
. The last factor is the maximum-likelihood gradient on the correct samples. Fine-tuning on your own filtered successes, known as rejection-sampling fine-tuning or expert iteration, and used in STaR (Zelikman et al., 2022), is therefore REINFORCE with 0/1 rewards and no baseline, up to step size.
-
Correct responses get weight ; incorrect ones get . The baseline adds negative examples: wrong answers are actively pushed down, and the push is strongest on prompts the model usually gets right (when is near 1, a failure is surprising and informative). It also makes easy prompts contribute little positive push, since is small there: no need to reinforce what is already reliable.
-
No baseline: (divided by ). With : . If all four are correct, and every weight is : the group gives no gradient at all. Without a baseline it would still push all four up. That “all-same group gives zero signal” property is central to GRPO (Chapter 15).
Use the two demos in this chapter.
- In the gradient-cloud demo at the uniform policy with and noise , how many distinct dot positions are there, and why? Turn the noise up to 1: what shape does each arm’s set of dots take, and why is it a line segment rather than a blob?
- Still at the uniform policy, with , read off the spread at , and . Which is the largest?
- Drag the policy to about . Is the true gradient bigger or smaller than at the uniform policy? Where do and sit now?
- In the race demo, with , both methods usually work. Explain why, using what you learned about the sign of .
- In the race demo, set and tap near the arm-2 corner to start there. Play. What fraction of no-baseline runs escape to arm 3?
Solution
-
Three: with noiseless rewards each arm always gives the same estimate . With noise, varies but the direction does not, so each arm’s dots spread along a line through the origin, its spoke. A single-sample estimate can only ever point along one of three directions; only averaging produces other directions.
-
About 4.15, 0.52, and . A badly chosen baseline (far above every reward) is as harmful as none: now every pull pushes its own arm down.
-
Smaller: is small when most probability sits on one arm. Here and , of length about 0.42 instead of 0.72. For : the squared score norms are and , so . It is well above , pulled toward the rewards of the rarely chosen arms 2 and 3, whose scores are large (as in Exercise 7.6).
-
With rewards 1, 2, 4, every reward is already positive, so without a baseline every pull still pushes its own arm up, but arm 3’s pushes are four times as large as arm 1’s, so the drift toward arm 3 dominates before the policy can collapse. The relative spread of the rewards is large. With , rewards 16, 17, 19 differ by only about 15%, and the “push whatever you pulled” component dominates the signal.
-
Few: starting at about with the default , only about 2 of the 12 no-baseline runs reach arm 3 within 400 steps (the readout then shows about 10 of 12 not committed to arm 3). Arm 3 is rarely sampled, and every pull of arm 2 (reward about 17) reinforces arm 2 strongly. All 12 baseline runs escape, because pulling arm 2 gives once has adapted, while a rare pull of arm 3 gives . (Exact counts depend on where you tap.)
Download the lab below and implement, in pg.py:
- Task 1
softmax_score(theta, actions): the score . - Task 2
exact_gradient(theta, q): . The test checks the worked example’s . - Task 3
reinforce_estimates(theta, actions, rewards, baseline): per sample. Tests check unbiasedness by Monte Carlo and the variance cut from a baseline. - Task 4
rewards_to_go(rewards, gamma). - Task 5
reinforce_loss(logits, actions, weights): the surrogate loss with detached weights.
Then run python run.py. It plots the bandit estimator’s variance against the baseline, and CartPole learning curves for three weightings: whole return , reward-to-go , and with a small learned value baseline. Before you run it, predict the order of the three curves.
Hint
running = r[t] + gamma * running. In Task 5, torch.log_softmax(logits, -1).gather(1, actions[:, None]) picks out the taken actions’ log-probabilities; don’t forget the minus sign and .detach() on the weights.Solution
Reference code is in solutions/pg.py. The key lines:
# Task 1: one-hot rows minus pi
return np.eye(len(pi))[actions] - pi[None, :]
# Task 3: scale each row by (R - b)
return (rewards - baseline)[:, None] * softmax_score(theta, actions)
# Task 4: one backward pass
running = 0.0
for t in reversed(range(len(rewards))):
running = rewards[t] + gamma * running
out[t] = running
# Task 5: minus the weighted log-likelihood of the taken actions
logp = torch.log_softmax(logits, -1).gather(1, actions[:, None]).squeeze(1)
return -(weights.detach() * logp).mean()What you should see: the variance curve is a valley with its minimum near (about 1 there, versus about 100 at ). The minimum is about 1.2 rather than the chapter’s 0.52 because the lab’s rewards have noise , which adds at every (the noise term ). On CartPole, typical final mean returns over 4 seeds are roughly 40 for the whole return, 300 for reward-to-go (with a wide spread across seeds), and close to 500 for the learned baseline. The algorithm, learning rate and number of episodes are the same in all three. Only the variance of the weights differs.
Files: pg.py, test_pg.py, run.py, cartpole.py, README.md
cd 07-policy-gradients
python -m pytest -q # your code: tests fail until you fill in the TODOs
RL_SOLUTIONS=1 python -m pytest -q # reference solutions: all passFirst time? See Exercises & setup.
Further reading
- Sutton & Barto (2018), Reinforcement Learning: An Introduction, ch. 13. The textbook treatment: the policy gradient theorem for continuing and episodic tasks, REINFORCE with baseline, and the short-corridor example. Read 13.1 to 13.4.
- OpenAI Spinning Up, Part 3: Intro to Policy Optimization. A short, careful derivation with code, including reward-to-go and the “expected grad-log-prob” lemma used throughout this chapter.
- Williams (1992), Simple statistical gradient-following algorithms for connectionist reinforcement learning. The original REINFORCE paper, including the idea of comparing the reward against a reference level (the baseline).
- Sutton, McAllester, Singh & Mansour (1999), Policy Gradient Methods for Reinforcement Learning with Function Approximation. The state-distribution form of the policy gradient theorem, and the bridge to actor-critic (Chapter 8).
- Greensmith, Bartlett & Baxter (2004), Variance Reduction Techniques for Gradient Estimates in Reinforcement Learning. Baselines and critics as control variates, with optimal baselines. Dense, but the source for the control-variate view.
- Mohamed, Rosca, Figurnov & Mnih (2020), Monte Carlo Gradient Estimation in Machine Learning. A survey comparing score-function, pathwise and measure-valued gradient estimators; read it to see where REINFORCE sits among the alternatives.
- Ahmadian et al. (2024), Back to Basics: Revisiting REINFORCE Style Optimization for Learning from Human Feedback in LLMs. Argues that much of PPO’s machinery is unnecessary for RLHF, and reports that REINFORCE with a leave-one-out baseline (RLOO) does as well or better. The direct link from this chapter to Chapters 15 and 16.
- Nota & Thomas (2020), Is the Policy Gradient a Gradient? The careful story behind the dropped factor, for when you want to know exactly what your code is optimizing.
Next, in Chapter 8, you replace the noisy Monte Carlo return with a learned critic and get the advantage estimates that PPO and RLHF are built on.