Part II · Deep RL · Chapter 7

Policy gradients and REINFORCE

Optimize the policy directly. The log-derivative trick, baselines, and variance.

~150 minBefore this: Bandits, MDPs, DQN

Here is a puzzle. You have a policy with a knob θ\theta. 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 θ\theta 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 QQ and acted by taking the argmax. In this chapter you skip the middleman: you write down a policy πθ\pi_\theta 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 QQ. 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 max⁡aQ(s,a)\max_a Q(s, a) 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 Q(s,left)Q(s, \text{left}) and Q(s,right)Q(s, \text{right}) 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 θ\theta 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-QQ 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 QQ-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 aa a real-valued score θa\theta_a, called a logit (later, a neural network will compute the logits from the state). Turn the logits into probabilities with the softmax:

πθ(a)=eθa∑beθb.\pi_\theta(a) = \frac{e^{\theta_a}}{\sum_{b} e^{\theta_b}}.

Physicists will recognize the Boltzmann distribution: action aa is a state with energy −θa-\theta_a at temperature 1. Dividing all logits by a temperature τ\tau makes the policy greedier as τ→0\tau \to 0 and more uniform as τ→∞\tau \to \infty. 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 μθ(s)\mu_\theta(s) (and maybe width σθ(s)\sigma_\theta(s)) comes from a network:

πθ(a∣s)=12π σexp⁡ ⁣(−(a−μθ(s))22σ2).\pi_\theta(a \mid s) = \frac{1}{\sqrt{2\pi}\,\sigma} \exp\!\left(-\frac{(a - \mu_\theta(s))^2}{2\sigma^2}\right).

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,

J(θ)=Eτ∼πθ[G0],J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta}\big[G_0\big],

where τ=(s0,a0,r0,s1,… )\tau = (s_0, a_0, r_0, s_1, \dots) is an episode generated by running πθ\pi_\theta in the environment, and G0=∑tγtrtG_0 = \sum_t \gamma^t r_t is its return. In a bandit (one step, no state) this is just the average reward: J(θ)=∑aπθ(a) q∗(a)J(\theta) = \sum_a \pi_\theta(a)\, q_*(a), where q∗(a)q_*(a) is arm aa‘s true mean reward, as in Chapter 2.

A worked example you will see all chapter

Take a 3-armed bandit with mean rewards q∗(1)=1q_*(1) = 1, q∗(2)=2q_*(2) = 2, q∗(3)=4q_*(3) = 4, and start from logits θ=(0,0,0)\theta = (0, 0, 0). The policy is uniform, π=(13,13,13)\pi = (\tfrac13, \tfrac13, \tfrac13), and

J=13⋅1+13⋅2+13⋅4=73≈2.33.J = \tfrac13 \cdot 1 + \tfrac13 \cdot 2 + \tfrac13 \cdot 4 = \tfrac73 \approx 2.33.

Because you know q∗q_* here, you can differentiate JJ directly. Using ∂π(a)/∂θk=π(a) (1[a=k]−π(k))\partial \pi(a) / \partial \theta_k = \pi(a)\,(\mathbb{1}[a = k] - \pi(k)) (differentiate the softmax quotient; the next section derives the same fact in log form, and Exercise 7.2 does it in full), you get

∂J∂θk=∑aq∗(a) π(a)(1[a=k]−π(k))=π(k) (q∗(k)−J).\frac{\partial J}{\partial \theta_k} = \sum_a q_*(a)\, \pi(a)\big(\mathbb{1}[a=k] - \pi(k)\big) = \pi(k)\,\big(q_*(k) - J\big).

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:

∇θJ=13 (1−73,  2−73,  4−73)=(−49,  −19,  59)≈(−0.44,  −0.11,  0.56).\nabla_\theta J = \tfrac13\,(1 - \tfrac73,\; 2 - \tfrac73,\; 4 - \tfrac73) = \left(-\tfrac49,\; -\tfrac19,\; \tfrac59\right) \approx (-0.44,\; -0.11,\; 0.56).

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 q∗q_*. It can only pull arms and see noisy rewards. So the question becomes: can you get (−0.44,−0.11,0.56)(-0.44, -0.11, 0.56), on average, from samples alone?

The log-derivative trick

The identity

Write the objective generically as an expectation of some score f(x)f(x) over samples xx from a distribution pθp_\theta that you control:

J(θ)=Ex∼pθ[f(x)]=∑xpθ(x) f(x).J(\theta) = \mathbb{E}_{x \sim p_\theta}[f(x)] = \sum_x p_\theta(x)\, f(x).

The parameters sit inside the distribution, not inside ff. Differentiate, and use ∇p=p ∇log⁡p\nabla p = p\, \nabla \log p (that is just the chain rule for log⁡\log, read backwards):

∇θJ=∑xf(x) ∇θpθ(x)=∑xpθ(x) f(x) ∇θlog⁡pθ(x)=Ex∼pθ[f(x) ∇θlog⁡pθ(x)].\nabla_\theta J = \sum_x f(x)\, \nabla_\theta p_\theta(x) = \sum_x p_\theta(x)\, f(x)\, \nabla_\theta \log p_\theta(x) = \mathbb{E}_{x \sim p_\theta}\big[f(x)\, \nabla_\theta \log p_\theta(x)\big].

That last line is the whole trick. The gradient of an expectation becomes an expectation of something you can compute for each sample. Draw xx from your own policy, compute f(x) ∇θlog⁡pθ(x)f(x)\,\nabla_\theta \log p_\theta(x), and average. You never differentiate ff, so ff can be a black box, discontinuous, or a 0/1 pass/fail signal.

The vector ∇θlog⁡pθ(x)\nabla_\theta \log p_\theta(x) 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, log⁡πθ(a)=θa−log⁡∑beθb\log \pi_\theta(a) = \theta_a - \log \sum_b e^{\theta_b}. Differentiating with respect to θk\theta_k:

∂log⁡πθ(a)∂θk=1[a=k]−πθ(k),that is,∇θlog⁡πθ(a)=ea−πθ,\frac{\partial \log \pi_\theta(a)}{\partial \theta_k} = \mathbb{1}[a = k] - \pi_\theta(k), \qquad\text{that is,}\qquad \nabla_\theta \log \pi_\theta(a) = e_a - \pi_\theta,

where eae_a is the one-hot vector for action aa. There is a nice picture here. Both eae_a and πθ\pi_\theta are points of the probability simplex (the triangle of all distributions over 3 arms). So the score of action aa is the arrow from where your policy is now to the corner “always play aa”. The demo below draws these three arrows as dashed lines in the triangle. (The components of ea−πe_a - \pi 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

e1−π=(23,−13,−13),e2−π=(−13,23,−13),e3−π=(−13,−13,23).e_1 - \pi = \left(\tfrac23, -\tfrac13, -\tfrac13\right),\quad e_2 - \pi = \left(-\tfrac13, \tfrac23, -\tfrac13\right),\quad e_3 - \pi = \left(-\tfrac13, -\tfrac13, \tfrac23\right).

Suppose rewards are noiseless for now, so arm aa always pays q∗(a)q_*(a). A single pull gives one of three possible gradient estimates g^=R⋅(ea−π)\hat g = R \cdot (e_a - \pi):

You pullProbabilityReward RREstimate g^=R (ea−π)\hat g = R\,(e_a - \pi)
arm 11/31(23,−13,−13)(\tfrac23, -\tfrac13, -\tfrac13)
arm 21/32(−23,43,−23)(-\tfrac23, \tfrac43, -\tfrac23)
arm 31/34(−43,−43,83)(-\tfrac43, -\tfrac43, \tfrac83)

Every single estimate is wrong; none of them is (−49,−19,59)(-\tfrac49, -\tfrac19, \tfrac59). Average them with weights 1/3:

13[(23−23−43),  (−13+43−43),  (−13−23+83)]=(−49,  −19,  59).\tfrac13\left[\left(\tfrac23 - \tfrac23 - \tfrac43\right),\; \left(-\tfrac13 + \tfrac43 - \tfrac43\right),\; \left(-\tfrac13 - \tfrac23 + \tfrac83\right)\right] = \left(-\tfrac49,\; -\tfrac19,\; \tfrac59\right).

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?

The score of a Gaussian policy

For π(a)=N(a;μ,σ2)\pi(a) = \mathcal{N}(a; \mu, \sigma^2) with parameter μ\mu,

∇μlog⁡π(a)=a−μσ2.\nabla_\mu \log \pi(a) = \frac{a - \mu}{\sigma^2}.

Sample a=μ+0.5a = \mu + 0.5 and get a good reward, and the update moves μ\mu toward aa. Get a bad reward, and μ\mu 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 σ\sigma 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 x=τx = \tau, the whole trajectory, and f(τ)=G0f(\tau) = G_0:

∇θJ=Eτ∼πθ[G0 ∇θlog⁡pθ(τ)].\nabla_\theta J = \mathbb{E}_{\tau \sim \pi_\theta}\big[G_0\, \nabla_\theta \log p_\theta(\tau)\big].

What is the probability of a trajectory? Start state, then alternately the policy picks an action and the environment picks the next state:

pθ(τ)=p(s0)∏t=0T−1πθ(at∣st)  P(st+1∣st,at).p_\theta(\tau) = p(s_0)\prod_{t=0}^{T-1} \pi_\theta(a_t \mid s_t)\; P(s_{t+1} \mid s_t, a_t).

Take the log, and the product becomes a sum:

log⁡pθ(τ)=log⁡p(s0)+∑tlog⁡πθ(at∣st)+∑tlog⁡P(st+1∣st,at).\log p_\theta(\tau) = \log p(s_0) + \sum_{t} \log \pi_\theta(a_t \mid s_t) + \sum_t \log P(s_{t+1} \mid s_t, a_t).

Now take ∇θ\nabla_\theta. The start distribution and the transition probabilities do not depend on θ\theta, so their gradients are zero. Only the policy terms survive:

∇θlog⁡pθ(τ)=∑t∇θlog⁡πθ(at∣st).\nabla_\theta \log p_\theta(\tau) = \sum_{t} \nabla_\theta \log \pi_\theta(a_t \mid s_t).

Putting it together gives the policy gradient theorem in its trajectory form:

∇θJ(θ)=Eτ∼πθ ⁣[ G0∑t=0T−1∇θlog⁡πθ(at∣st)].\nabla_\theta J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta}\!\left[\,G_0 \sum_{t=0}^{T-1} \nabla_\theta \log \pi_\theta(a_t \mid s_t)\right].

Stop and appreciate what just happened. The environment’s dynamics dropped out. You need to sample from PP (run the episode), but you never need to know PP, 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 TT (or discounted, so returns are bounded), a policy πθ(a∣s)\pi_\theta(a \mid s) differentiable in θ\theta for every (s,a)(s, a), and rewards rtr_t drawn from some distribution depending on (st,at,st+1)(s_t, a_t, s_{t+1}) but not on θ\theta. Write R(τ)=G0=∑tγtrtR(\tau) = G_0 = \sum_t \gamma^t r_t.

  1. The objective is an integral over trajectories (sums for discrete parts):
J(θ)=∫pθ(τ) R(τ) dτ.J(\theta) = \int p_\theta(\tau)\, R(\tau)\, d\tau .
  1. Under the conditions above (bounded RR, finite horizon, smooth πθ\pi_\theta), you can move the gradient inside the integral (dominated convergence):
∇θJ=∫∇θpθ(τ) R(τ) dτ.\nabla_\theta J = \int \nabla_\theta p_\theta(\tau)\, R(\tau)\, d\tau .

Note that R(τ)R(\tau) itself has no θ\theta in it: once the trajectory is fixed, its return is fixed.

  1. Wherever pθ(τ)>0p_\theta(\tau) > 0, ∇θpθ(τ)=pθ(τ) ∇θlog⁡pθ(τ)\nabla_\theta p_\theta(\tau) = p_\theta(\tau)\,\nabla_\theta \log p_\theta(\tau). Where pθ(τ)=0p_\theta(\tau) = 0 in a neighbourhood, the gradient is zero too. So
∇θJ=∫pθ(τ) ∇θlog⁡pθ(τ) R(τ) dτ=Eτ∼πθ[R(τ) ∇θlog⁡pθ(τ)].\nabla_\theta J = \int p_\theta(\tau)\, \nabla_\theta \log p_\theta(\tau)\, R(\tau)\, d\tau = \mathbb{E}_{\tau \sim \pi_\theta}\big[R(\tau)\,\nabla_\theta \log p_\theta(\tau)\big].
  1. The trajectory density factorizes. Including the reward densities p(rt∣st,at,st+1)p(r_t \mid s_t, a_t, s_{t+1}):
pθ(τ)=p(s0)∏tπθ(at∣st) P(st+1∣st,at) p(rt∣st,at,st+1).p_\theta(\tau) = p(s_0) \prod_{t} \pi_\theta(a_t \mid s_t)\, P(s_{t+1} \mid s_t, a_t)\, p(r_t \mid s_t, a_t, s_{t+1}).
  1. In log⁡pθ(τ)\log p_\theta(\tau), every factor except πθ\pi_\theta is constant in θ\theta, so
∇θlog⁡pθ(τ)=∑t∇θlog⁡πθ(at∣st).\nabla_\theta \log p_\theta(\tau) = \sum_t \nabla_\theta \log \pi_\theta(a_t \mid s_t).
  1. Substituting into step 3 gives the theorem. ■\blacksquare

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 θ\theta 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?

REINFORCE

Replace the expectation by an average over NN 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 πθ\pi_\theta. 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 g^\hat g by hand. You build a scalar whose gradient is g^\hat g 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 −1N∑twtlog⁡πθ(at∣st)-\frac1N\sum_t w_t \log \pi_\theta(a_t \mid s_t) with the weights held constant is −1N∑twt∇θlog⁡πθ(at∣st)-\frac1N \sum_t w_t \nabla_\theta\log\pi_\theta(a_t \mid s_t), exactly minus the REINFORCE estimate. Gradient descent on this loss is gradient ascent on JJ.

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 G0G_0. 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:

∇θJ=Eτ∼πθ ⁣[∑t∇θlog⁡πθ(at∣st) ∑t′≥tγt′rt′].\nabla_\theta J = \mathbb{E}_{\tau \sim \pi_\theta}\!\left[\sum_{t} \nabla_\theta \log \pi_\theta(a_t \mid s_t)\, \sum_{t' \ge t} \gamma^{t'} r_{t'}\right].

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 sts_t, the score of ata_t 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 ψt=∇θlog⁡πθ(at∣st)\psi_t = \nabla_\theta \log \pi_\theta(a_t \mid s_t) and ht=(s0,a0,r0,…,st)h_t = (s_0, a_0, r_0, \dots, s_t), the history up to state sts_t but not including ata_t.

  1. The score has zero mean given the state:
E[ψt∣ht]=∑aπθ(a∣st) ∇θlog⁡πθ(a∣st)=∑a∇θπθ(a∣st)=∇θ∑aπθ(a∣st)=∇θ1=0.\mathbb{E}[\psi_t \mid h_t] = \sum_a \pi_\theta(a \mid s_t)\, \nabla_\theta \log \pi_\theta(a \mid s_t) = \sum_a \nabla_\theta \pi_\theta(a \mid s_t) = \nabla_\theta \sum_a \pi_\theta(a \mid s_t) = \nabla_\theta 1 = 0.

(This uses the Markov property: given hth_t, the action is drawn from πθ(⋅∣st)\pi_\theta(\cdot \mid s_t).)

  1. Take a reward from the past, rt′r_{t'} with t′<tt' < t. It is a function of hth_t. By the tower rule (the law of total expectation, E[XY]=E[X E[Y∣h]]\mathbb{E}[XY] = \mathbb{E}[X\,\mathbb{E}[Y \mid h]] when XX is fixed by hh),
E[rt′ ψt]=E[ rt′ E[ψt∣ht] ]=E[rt′⋅0]=0.\mathbb{E}[r_{t'}\, \psi_t] = \mathbb{E}\big[\, r_{t'}\, \mathbb{E}[\psi_t \mid h_t] \,\big] = \mathbb{E}[r_{t'} \cdot 0] = 0.
  1. Expand the vanilla estimator G0∑tψt=∑t∑t′γt′rt′ ψtG_0 \sum_t \psi_t = \sum_t \sum_{t'} \gamma^{t'} r_{t'}\, \psi_t. All terms with t′<tt' < t have expectation zero by step 2. Dropping them leaves
∇θJ=E[∑tψt∑t′≥tγt′rt′]=E[∑tγt Gt ψt],Gt=∑k≥0γkrt+k.■\nabla_\theta J = \mathbb{E}\Big[\sum_t \psi_t \sum_{t' \ge t} \gamma^{t'} r_{t'}\Big] = \mathbb{E}\Big[\sum_t \gamma^{t}\, G_t\, \psi_t\Big], \qquad G_t = \sum_{k \ge 0} \gamma^{k} r_{t+k}. \qquad \blacksquare

The terms we dropped have zero mean but nonzero variance. Removing a zero-mean term YY from X+YX + Y changes the variance by −Var(Y)−2 Cov(X,Y)-\mathrm{Var}(Y) - 2\,\mathrm{Cov}(X, Y), which is a reduction unless YY 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

∇J^=1N∑episodes∑tGt ∇θlog⁡πθ(at∣st).\widehat{\nabla J} = \frac1N \sum_{\text{episodes}} \sum_{t} G_t\, \nabla_\theta \log \pi_\theta(a_t \mid s_t).

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 +10+10, so the arms pay 11, 12 and 14. Nothing about the problem has changed: arm 3 is still best by the same margins, and ∇J\nabla J is still (−49,−19,59)(-\tfrac49, -\tfrac19, \tfrac59) (the offset cancels in q∗(k)−Jq_*(k) - J). But now every single estimate R (ea−π)R\,(e_a - \pi) has R≥11R \ge 11. 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 +1+1, 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, E∥g^−∇J∥2\mathbb{E}\lVert \hat g - \nabla J \rVert^2 (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, ∥ea−π∥2=49+19+19=23\lVert e_a - \pi \rVert^2 = \tfrac49 + \tfrac19 + \tfrac19 = \tfrac23 for every arm, so

E∥g^∥2=23 E[R2],Var=23 E[R2]−∥∇J∥2,∥∇J∥2=16+1+2581≈0.52.\mathbb{E}\lVert \hat g \rVert^2 = \tfrac23\, \mathbb{E}[R^2], \qquad \mathrm{Var} = \tfrac23\,\mathbb{E}[R^2] - \lVert \nabla J \rVert^2, \qquad \lVert \nabla J \rVert^2 = \tfrac{16 + 1 + 25}{81} \approx 0.52.

With rewards 1, 2, 4: E[R2]=7\mathbb{E}[R^2] = 7, so the variance is 143−0.52≈4.15\tfrac{14}{3} - 0.52 \approx 4.15. With rewards 11, 12, 14: E[R2]=4613\mathbb{E}[R^2] = \tfrac{461}{3}, 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 bb, the baseline:

∇J^=1N∑episodes∑t(Gt−b(st)) ∇θlog⁡πθ(at∣st).\widehat{\nabla J} = \frac1N \sum_{\text{episodes}} \sum_t \big(G_t - b(s_t)\big)\, \nabla_\theta \log \pi_\theta(a_t \mid s_t).

Now an action is pushed up only if it did better than bb, and pushed down if it did worse. Is this still the right gradient? Yes, by the same zero-mean fact, as long as bb does not depend on the action ata_t:

E[b(st) ∇θlog⁡πθ(at∣st)]=E[b(st) E[∇θlog⁡πθ(at∣st)∣st]⏟= 0]=0.\mathbb{E}\big[b(s_t)\, \nabla_\theta \log \pi_\theta(a_t \mid s_t)\big] = \mathbb{E}\Big[b(s_t)\, \underbrace{\mathbb{E}\big[\nabla_\theta \log \pi_\theta(a_t \mid s_t) \mid s_t\big]}_{=\,0}\Big] = 0.

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 b=J=73b = J = \tfrac73 (rewards 1, 2, 4):

You pullR−bR - bEstimate (R−b)(ea−π)(R - b)(e_a - \pi)
arm 1−43-\tfrac43(−89,49,49)(-\tfrac89, \tfrac49, \tfrac49)
arm 2−13-\tfrac13(19,−29,19)(\tfrac19, -\tfrac29, \tfrac19)
arm 3+53+\tfrac53(−59,−59,109)(-\tfrac59, -\tfrac59, \tfrac{10}9)

The average is still (−49,−19,59)(-\tfrac49, -\tfrac19, \tfrac59); check it. But now pulling arm 1 pushes arm 1 down, as it should. The variance is 23Var(R)−0.52=23⋅149−0.52≈0.52\tfrac23 \mathrm{Var}(R) - 0.52 = \tfrac23 \cdot \tfrac{14}{9} - 0.52 \approx 0.52, down from 4.15, an 8-fold reduction. With the +10+10 offset, b=J=12.33b = J = 12.33 gives the same 0.520.52, 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, b≈Jb \approx J, or, when there are states, b(st)≈Vπ(st)b(s_t) \approx V^\pi(s_t), the expected return from sts_t. Then Gt−Vπ(st)G_t - V^\pi(s_t) is an estimate of the advantage Aπ(st,at)=Qπ(st,at)−Vπ(st)A^\pi(s_t, a_t) = Q^\pi(s_t, a_t) - V^\pi(s_t): how much better this action turned out than the policy’s average from that state. Learning VV well enough to use as a baseline (and then using it for more than that) is what Chapter 8 is about.

JJ is close to the best constant, but not exactly the best. Minimizing the variance over bb gives a score-weighted average of the rewards.

∂ The minimum-variance constant baseline

Consider a single-sample estimate g^(b)=(R−b) ψ\hat g(b) = (R - b)\,\psi, where ψ=∇θlog⁡πθ(a)\psi = \nabla_\theta \log \pi_\theta(a) and RR is the reward (or return). We want the constant bb minimizing the total variance E∥g^(b)−∇J∥2\mathbb{E}\lVert \hat g(b) - \nabla J \rVert^2.

  1. Since E[g^(b)]=∇J\mathbb{E}[\hat g(b)] = \nabla J for every bb, the variance is
E∥g^(b)∥2−∥∇J∥2=E[(R−b)2∥ψ∥2]−∥∇J∥2.\mathbb{E}\lVert \hat g(b)\rVert^2 - \lVert \nabla J\rVert^2 = \mathbb{E}\big[(R - b)^2 \lVert\psi\rVert^2\big] - \lVert \nabla J\rVert^2 .
  1. This is a quadratic in bb. Differentiate and set to zero:
ddb E[(R−b)2∥ψ∥2]=−2 E[(R−b)∥ψ∥2]=0.\frac{d}{db}\,\mathbb{E}\big[(R - b)^2 \lVert\psi\rVert^2\big] = -2\,\mathbb{E}\big[(R - b)\lVert\psi\rVert^2\big] = 0 .
  1. Solve:
b∗=E[R ∥ψ∥2]E[∥ψ∥2].b^* = \frac{\mathbb{E}\big[R\,\lVert \psi \rVert^2\big]}{\mathbb{E}\big[\lVert \psi \rVert^2\big]} .

The second derivative is 2 E∥ψ∥2>02\,\mathbb{E}\lVert\psi\rVert^2 > 0, so this is a minimum.

So b∗b^* is an average of the rewards, weighted by how large the score was on each sample. If all scores have the same size, b∗=E[R]=Jb^* = \mathbb{E}[R] = J. That happens at the uniform softmax policy (every ∥ea−π∥2=23\lVert e_a - \pi\rVert^2 = \tfrac23), so in the worked example b∗=J=73b^* = J = \tfrac73 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 kk, the same computation gives bk∗=E[R ψk2]/E[ψk2]b_k^* = \mathbb{E}[R\,\psi_k^2] / \mathbb{E}[\psi_k^2]. In practice nobody uses these exactly: a learned V(s)V(s) 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 ea−πe_a - \pi), 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 ∣R−b∣ ∥ea−π∥\lvert R - b\rvert\,\lVert e_a - \pi\rVert from the centre. The strip plot below the baseline slider shows the exact spread of one estimate as a function of bb (log scale), with markers at JJ and b∗b^*; the orange dot is your current bb.

Interactive Single-sample policy gradients, and what a baseline does to them
Policy π (tap or drag to move it)
Gradient estimates (one dot per sample)
π J(θ)
true ∇J
mean of samples
spread (total variance) of one estimate exact , measured

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?

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.

Interactive REINFORCE with and without a baseline
Policy paths (tap to choose the start)
Expected reward Σ π(a) q(a) (offset c not included)
no baseline: weight Rrunning-average baseline: weight R − b
step
no baseline mean J runs not yet committed to arm 3 (π₃ < 0.5):
with baseline mean J runs not yet committed to arm 3:

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 (π(k)(q∗(k)−J)\pi(k)(q_*(k) - J) is tiny when π(3)\pi(3) 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 c=10c = 10 and α=0.1\alpha = 0.1, 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 xx. The model samples a response y=(y1,…,y∣y∣)y = (y_1, \dots, y_{|y|}) 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:

log⁡πθ(y∣x)=∑t=1∣y∣log⁡πθ(yt∣x,y<t),∇θlog⁡πθ(y∣x)=∑t∇θlog⁡πθ(yt∣x,y<t).\log \pi_\theta(y \mid x) = \sum_{t=1}^{|y|} \log \pi_\theta(y_t \mid x, y_{\lt t}), \qquad \nabla_\theta \log \pi_\theta(y \mid x) = \sum_{t} \nabla_\theta \log \pi_\theta(y_t \mid x, y_{\lt t}).

That is the trajectory form of the policy gradient theorem, with state (x,y<t)(x, y_{\lt t}) and action yty_t. The “environment” is trivial (appending a token is deterministic), and usually the only reward is a single number r(x,y)r(x, y) at the end: a reward model’s score, or 1 if the final answer is correct. With γ=1\gamma = 1 and one terminal reward, every token’s reward-to-go is just r(x,y)r(x, y). So REINFORCE for a language model is

∇J^=1N∑i=1N(r(x,y(i))−b)∑t∇θlog⁡πθ(yt(i)∣x,y<t(i)).\widehat{\nabla J} = \frac1N \sum_{i=1}^N \big(r(x, y^{(i)}) - b\big) \sum_{t} \nabla_\theta \log \pi_\theta\big(y^{(i)}_t \mid x, y^{(i)}_{\lt t}\big).

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 G=4G = 4 responses to the same prompt and suppose they get rewards 1,0,0,11, 0, 0, 1. Using the group mean as the baseline, b=0.5b = 0.5, the weights are +0.5,−0.5,−0.5,+0.5+0.5, -0.5, -0.5, +0.5: 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 1−13=+231 - \tfrac13 = +\tfrac23 for the correct ones and 0−23=−230 - \tfrac23 = -\tfrac23 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 ±1\pm 1, and that is the advantage used by GRPO. (Some implementations use the sample standard deviation, 0.580.58, which gives ±0.87\pm 0.87; 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?

Summary

  • A policy gradient method parameterizes the policy πθ\pi_\theta directly and does gradient ascent on the expected return J(θ)J(\theta). It handles continuous actions, changes smoothly, can represent stochastic optimal policies, and fits language models, which are already policies.
  • The log-derivative trick, ∇θEpθ[f]=Epθ[f ∇θlog⁡pθ]\nabla_\theta \mathbb{E}_{p_\theta}[f] = \mathbb{E}_{p_\theta}[f \,\nabla_\theta \log p_\theta], turns the gradient of an expectation into an expectation you can sample. ff need not be differentiable.
  • For trajectories the dynamics drop out: ∇J=E[∑t∇θlog⁡πθ(at∣st)⋅(return)]\nabla J = \mathbb{E}[\sum_t \nabla_\theta \log \pi_\theta(a_t \mid s_t)\cdot(\text{return})]. You need samples from the environment, never its model.
  • For a softmax policy the score is ea−πθe_a - \pi_\theta: the arrow from the current policy toward always playing aa.
  • REINFORCE is weighted maximum likelihood on your own samples. In code it is the surrogate loss −mean(wtlog⁡πθ(at∣st))-\text{mean}(w_t \log \pi_\theta(a_t \mid s_t)) 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 (V(s)V(s), 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

Exercise 7.1Where argmax strugglesConcept●○○

For each problem, say what makes “learn QQ, act greedily” awkward or wrong, and what a parameterized stochastic policy does instead.

  1. A robot arm that outputs three joint torques, each a real number in [−1,1][-1, 1].
  2. Rock-paper-scissors against an opponent that learns to exploit any pattern in your play.
  3. A language model choosing the next token from a vocabulary of 100,000.
Solution
  1. Acting greedily means solving max⁡a∈[−1,1]3Q(s,a)\max_{a \in [-1,1]^3} Q(s, a) 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 θ\theta.
  2. 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-QQ policy cannot represent at all (ε-greedy adds randomness, but not a chosen amount).
  3. The action space is huge and the “state” (the text so far) is never seen twice, so learning accurate QQ-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.
Exercise 7.2The score of a softmax, with temperaturePen & paper●●○

Let πθ(a)=eθa/τ/∑beθb/τ\pi_\theta(a) = e^{\theta_a/\tau} / \sum_b e^{\theta_b/\tau} with temperature τ>0\tau > 0.

  1. Show that ∂log⁡πθ(a)/∂θk=(1[a=k]−πθ(k))/τ\partial \log \pi_\theta(a) / \partial \theta_k = (\mathbb{1}[a = k] - \pi_\theta(k))/\tau.
  2. Show that the components of the score sum to zero, and explain why that had to be true.
  3. Show that ∑aπθ(a) ∇θlog⁡πθ(a)=0\sum_a \pi_\theta(a)\, \nabla_\theta \log \pi_\theta(a) = 0.
  4. At τ=1\tau = 1 and θ=(0,0,0)\theta = (0, 0, 0), compute the score of action 3. What happens to its size as τ→0\tau \to 0, and what does that suggest about learning with a very low temperature?
Hint
Write log⁡πθ(a)=θa/τ−log⁡Z\log \pi_\theta(a) = \theta_a/\tau - \log Z with Z=∑beθb/τZ = \sum_b e^{\theta_b/\tau}, and remember that ∂log⁡Z/∂θk\partial \log Z / \partial \theta_k is a probability.
Solution
  1. log⁡πθ(a)=θa/τ−log⁡Z\log \pi_\theta(a) = \theta_a/\tau - \log Z. Then ∂(θa/τ)/∂θk=1[a=k]/τ\partial(\theta_a/\tau)/\partial\theta_k = \mathbb{1}[a=k]/\tau, and ∂log⁡Z/∂θk=1Zeθk/τ⋅1τ=πθ(k)/τ\partial \log Z / \partial \theta_k = \frac{1}{Z} e^{\theta_k/\tau}\cdot\frac1\tau = \pi_\theta(k)/\tau. Subtract.

  2. ∑k(1[a=k]−πθ(k))/τ=(1−1)/τ=0\sum_k (\mathbb{1}[a=k] - \pi_\theta(k))/\tau = (1 - 1)/\tau = 0. It had to be: adding the same constant cc to every logit leaves π\pi unchanged, so the directional derivative of log⁡πθ(a)\log \pi_\theta(a) along (1,1,…,1)(1, 1, \dots, 1) is zero, and that directional derivative is the sum of the components.

  3. ∑aπ(a)(1[a=k]−π(k))/τ=(π(k)−π(k))/τ=0\sum_a \pi(a)(\mathbb{1}[a=k] - \pi(k))/\tau = (\pi(k) - \pi(k))/\tau = 0 for every kk. (This is the general fact E[∇log⁡π]=∇∑π=0\mathbb{E}[\nabla\log\pi] = \nabla\sum\pi = 0.)

  4. At τ=1\tau = 1: e3−π=(−13,−13,23)e_3 - \pi = (-\tfrac13, -\tfrac13, \tfrac23), with squared length 23\tfrac23. At θ=0\theta = 0 the policy is uniform for every τ\tau, so the score (e3−π)/τ(e_3 - \pi)/\tau simply grows like 1/τ1/\tau: a lower temperature amplifies every update, like a larger step size. With unequal logits it gets worse. As τ→0\tau \to 0 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 1/τ1/\tau, 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.

Exercise 7.3The Gaussian scorePen & paper●●○

Let π(a)=N(a;μ,σ2)\pi(a) = \mathcal{N}(a; \mu, \sigma^2) with parameters μ\mu and η=log⁡σ\eta = \log \sigma (parameterizing by log⁡σ\log\sigma keeps σ\sigma positive).

  1. Compute ∂log⁡π(a)/∂μ\partial \log \pi(a)/\partial \mu and ∂log⁡π(a)/∂η\partial \log \pi(a)/\partial \eta.
  2. Check that both have mean zero under a∼πa \sim \pi.
  3. With μ=0\mu = 0, σ=1\sigma = 1, you sample a=1.5a = 1.5 and get return G=3G = 3. The baseline is b=1b = 1, and the step size is α=0.1\alpha = 0.1. Compute the REINFORCE update of μ\mu and η\eta, and say in words what the policy learned.
Hint
log⁡π(a)=−(a−μ)22e−2η−η−12log⁡2π\log \pi(a) = -\frac{(a-\mu)^2}{2}e^{-2\eta} - \eta - \tfrac12\log 2\pi. For the mean-zero check you need E[(a−μ)2]=σ2\mathbb{E}[(a-\mu)^2] = \sigma^2.
Solution
  1. ∂log⁡π/∂μ=(a−μ)/σ2\partial \log\pi/\partial\mu = (a - \mu)/\sigma^2. For η\eta: ∂/∂η[−12(a−μ)2e−2η]=(a−μ)2e−2η\partial/\partial\eta\left[-\tfrac12(a-\mu)^2 e^{-2\eta}\right] = (a-\mu)^2 e^{-2\eta}, and ∂(−η)/∂η=−1\partial(-\eta)/\partial\eta = -1, so ∂log⁡π/∂η=(a−μ)2/σ2−1\partial \log\pi/\partial\eta = (a-\mu)^2/\sigma^2 - 1.

  2. E[(a−μ)/σ2]=0\mathbb{E}[(a-\mu)/\sigma^2] = 0 because E[a]=μ\mathbb{E}[a] = \mu. E[(a−μ)2/σ2−1]=σ2/σ2−1=0\mathbb{E}[(a-\mu)^2/\sigma^2 - 1] = \sigma^2/\sigma^2 - 1 = 0.

  3. G−b=2G - b = 2. Scores: ∂μ=1.5/1=1.5\partial_\mu = 1.5/1 = 1.5, and ∂η=1.52−1=1.25\partial_\eta = 1.5^2 - 1 = 1.25. Updates: Δμ=0.1⋅2⋅1.5=0.3\Delta\mu = 0.1 \cdot 2 \cdot 1.5 = 0.3, and Δη=0.1⋅2⋅1.25=0.25\Delta\eta = 0.1 \cdot 2 \cdot 1.25 = 0.25, so σ\sigma becomes e0.25≈1.28e^{0.25} \approx 1.28. 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 (∣a−μ∣<σ|a - \mu| < \sigma) would have shrunk σ\sigma instead.

Exercise 7.4Baselines may depend on the state, not on the actionPen & paper●●○
  1. Prove that for any function b(s)b(s), Ea∼πθ(⋅∣s)[b(s) ∇θlog⁡πθ(a∣s)]=0\mathbb{E}_{a \sim \pi_\theta(\cdot \mid s)}\big[b(s)\,\nabla_\theta \log \pi_\theta(a \mid s)\big] = 0.
  2. Now cheat: in the 3-armed worked example (uniform policy, noiseless rewards 1, 2, 4), use an action-dependent “baseline” b(a)=q∗(a)b(a) = q_*(a). Compute the expected estimate E[(R−b(a)) (ea−π)]\mathbb{E}[(R - b(a))\,(e_a - \pi)]. Compare with ∇J\nabla J.
  3. Use b(a)=2b(a) = 2 for arms 1 and 2 and b(a)=0b(a) = 0 for arm 3. Compute the expected estimate and show it is biased.
Hint
In part 1, b(s)b(s) is a constant for the sum over aa, and π ∇log⁡π=∇π\pi\,\nabla\log\pi = \nabla\pi. In parts 2 and 3, write out the three possible estimates and average them with weight 1/3.
Solution
  1. ∑aπθ(a∣s) b(s) ∇θlog⁡πθ(a∣s)=b(s)∑a∇θπθ(a∣s)=b(s) ∇θ∑aπθ(a∣s)=b(s) ∇θ1=0\sum_a \pi_\theta(a\mid s)\, b(s)\, \nabla_\theta \log\pi_\theta(a \mid s) = b(s)\sum_a \nabla_\theta \pi_\theta(a\mid s) = b(s)\,\nabla_\theta \sum_a \pi_\theta(a \mid s) = b(s)\,\nabla_\theta 1 = 0. Pulling b(s)b(s) out of the sum is the step that needs bb not to depend on aa.

  2. With noiseless rewards R=q∗(a)R = q_*(a), so R−b(a)=0R - b(a) = 0 for every arm: every estimate is exactly zero, and so is its expectation. The true gradient is (−49,−19,59)(-\tfrac49, -\tfrac19, \tfrac59). 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 Ea[b(a)∇log⁡π(a)]\mathbb{E}_a[b(a)\nabla\log\pi(a)] analytically; that is the idea behind some “action-dependent control variate” methods. Without the correction, it is just wrong.)

  3. The estimates are arm 1: (1−2)(23,−13,−13)=(−23,13,13)(1 - 2)(\tfrac23, -\tfrac13, -\tfrac13) = (-\tfrac23, \tfrac13, \tfrac13); arm 2: (2−2)(⋯ )=0(2 - 2)(\cdots) = 0; arm 3: 4 (−13,−13,23)=(−43,−43,83)4\,(-\tfrac13, -\tfrac13, \tfrac23) = (-\tfrac43, -\tfrac43, \tfrac83). The average is 13(−2,−1,3)=(−23,−13,1)\tfrac13(-2, -1, 3) = (-\tfrac23, -\tfrac13, 1), not (−49,−19,59)(-\tfrac49, -\tfrac19, \tfrac59). The bias is E[−b(a)(ea−π)]=−13[2(e1−π)+2(e2−π)]=(−29,−29,49)\mathbb{E}[-b(a)(e_a - \pi)] = -\tfrac13[2(e_1 - \pi) + 2(e_2 - \pi)] = (-\tfrac29, -\tfrac29, \tfrac49). Here it happens to point roughly the right way, but in general a biased estimator can converge to the wrong policy.

Exercise 7.5A REINFORCE update by handPen & paper●●○

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 r0=1r_0 = 1, move to B; in B take left, receive r1=0r_1 = 0, episode ends. Use γ=0.9\gamma = 0.9 and step size α=0.5\alpha = 0.5.

  1. Compute the update to all four logits using vanilla REINFORCE (every action weighted by G0G_0).
  2. Repeat with reward-to-go weights GtG_t.
  3. Repeat with reward-to-go and a constant baseline b=0.5b = 0.5.
  4. In each case, what is the new probability of left in state B? Which update is the most sensible, and why?
Hint
At a uniform 2-action softmax, the score of right with respect to that state’s logits (left, right) is (−12,12)(-\tfrac12, \tfrac12), and the score of left is (12,−12)(\tfrac12, -\tfrac12). The other state’s logits get zero.
Solution

Returns: G0=r0+γr1=1G_0 = r_0 + \gamma r_1 = 1, and G1=r1=0G_1 = r_1 = 0.

  1. Both actions are weighted by G0=1G_0 = 1. State A (took right): ΔθA=0.5⋅1⋅(−12,12)=(−0.25,+0.25)\Delta\theta_A = 0.5 \cdot 1 \cdot (-\tfrac12, \tfrac12) = (-0.25, +0.25). State B (took left): ΔθB=0.5⋅1⋅(12,−12)=(+0.25,−0.25)\Delta\theta_B = 0.5 \cdot 1 \cdot (\tfrac12, -\tfrac12) = (+0.25, -0.25).

  2. Step 0 gets G0=1G_0 = 1, the same as before: ΔθA=(−0.25,+0.25)\Delta\theta_A = (-0.25, +0.25). Step 1 gets G1=0G_1 = 0: ΔθB=(0,0)\Delta\theta_B = (0, 0).

  3. Weights G0−b=0.5G_0 - b = 0.5 and G1−b=−0.5G_1 - b = -0.5. ΔθA=0.5⋅0.5⋅(−12,12)=(−0.125,+0.125)\Delta\theta_A = 0.5\cdot 0.5\cdot(-\tfrac12, \tfrac12) = (-0.125, +0.125). ΔθB=0.5⋅(−0.5)⋅(12,−12)=(−0.125,+0.125)\Delta\theta_B = 0.5\cdot(-0.5)\cdot(\tfrac12, -\tfrac12) = (-0.125, +0.125).

  4. π(left∣B)=σ(θB,left−θB,right)\pi(\text{left} \mid B) = \sigma(\theta_{B,\text{left}} - \theta_{B,\text{right}}): (1) σ(0.5)≈0.62\sigma(0.5) \approx 0.62; (2) σ(0)=0.5\sigma(0) = 0.5; (3) σ(−0.25)≈0.44\sigma(-0.25) \approx 0.44.

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 γt\gamma^t factor, step 1’s weight would be γ (G1−b)\gamma\,(G_1 - b) rather than G1−bG_1 - b; with G1=0G_1 = 0 this changes only part 3, to ΔθB=(−0.1125,+0.1125)\Delta\theta_B = (-0.1125, +0.1125).)

Exercise 7.6The optimal baseline can be surprisingPen & paper●●●

Take a 2-armed bandit with a softmax over two logits and policy π=(p,1−p)\pi = (p, 1-p). Rewards are noiseless: arm 1 pays q1q_1, arm 2 pays q2q_2.

  1. Compute the squared norm of the score ∥ea−π∥2\lVert e_a - \pi\rVert^2 for each arm.
  2. Use the minimum-variance formula b∗=E[R∥ψ∥2]/E[∥ψ∥2]b^* = \mathbb{E}[R\lVert\psi\rVert^2] / \mathbb{E}[\lVert\psi\rVert^2] to show that b∗=(1−p) q1+p q2b^* = (1-p)\,q_1 + p\,q_2.
  3. Compare with J=p q1+(1−p) q2J = p\,q_1 + (1-p)\,q_2. When are they equal? Explain in words why the optimal baseline weights each arm by the probability of the other arm.
  4. With p=0.9p = 0.9, q1=1q_1 = 1, q2=0q_2 = 0: compute JJ, b∗b^*, and the variance of a single estimate at b=0b = 0, b=Jb = J and b=b∗b = b^*.
Hint
The score of arm 1 is (1−p,−(1−p))(1-p, -(1-p)) and that of arm 2 is (−p,p)(-p, p). For part 4, use Var(b)=E[(R−b)2∥ψ∥2]−∥∇J∥2\mathrm{Var}(b) = \mathbb{E}[(R-b)^2\lVert\psi\rVert^2] - \lVert\nabla J\rVert^2, and note that ∇J=π⊙(q−J)\nabla J = \pi \odot (q - J).
Solution
  1. ∥e1−π∥2=2(1−p)2\lVert e_1 - \pi\rVert^2 = 2(1-p)^2 and ∥e2−π∥2=2p2\lVert e_2 - \pi\rVert^2 = 2p^2.

  2. Numerator: p⋅q1⋅2(1−p)2+(1−p)⋅q2⋅2p2=2p(1−p) [(1−p)q1+p q2]p \cdot q_1 \cdot 2(1-p)^2 + (1-p)\cdot q_2 \cdot 2p^2 = 2p(1-p)\,[(1-p)q_1 + p\,q_2]. Denominator: p⋅2(1−p)2+(1−p)⋅2p2=2p(1−p) [(1−p)+p]=2p(1−p)p\cdot 2(1-p)^2 + (1-p)\cdot 2p^2 = 2p(1-p)\,[(1-p) + p] = 2p(1-p). The ratio is b∗=(1−p) q1+p q2b^* = (1-p)\,q_1 + p\,q_2.

  3. They are equal when p=12p = \tfrac12 (or q1=q2q_1 = q_2). The variance comes from (R−b)2∥ψ∥2(R - b)^2\lVert\psi\rVert^2. The rare arm is sampled rarely, but when it is, its score is large (∥ψ∥2=2p2\lVert\psi\rVert^2 = 2p^2 for arm 2 is near 2 when pp 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.

  4. J=0.9J = 0.9, b∗=0.1b^* = 0.1. The gradient: ∇J=(0.9(1−0.9),0.1(0−0.9))=(0.09,−0.09)\nabla J = (0.9(1 - 0.9), 0.1(0 - 0.9)) = (0.09, -0.09), so ∥∇J∥2=0.0162\lVert\nabla J\rVert^2 = 0.0162. Score norms: arm 1 2(0.1)2=0.022(0.1)^2 = 0.02, arm 2 2(0.9)2=1.622(0.9)^2 = 1.62.

    • b=0b = 0: E[(R−b)2∥ψ∥2]=0.9⋅1⋅0.02+0.1⋅0⋅1.62=0.018\mathbb{E}[(R-b)^2\lVert\psi\rVert^2] = 0.9\cdot 1\cdot 0.02 + 0.1\cdot 0\cdot 1.62 = 0.018, so the variance is 0.018−0.0162=0.00180.018 - 0.0162 = 0.0018.
    • b=J=0.9b = J = 0.9: 0.9⋅0.01⋅0.02+0.1⋅0.81⋅1.62=0.00018+0.1312=0.13140.9 \cdot 0.01 \cdot 0.02 + 0.1\cdot 0.81\cdot 1.62 = 0.00018 + 0.1312 = 0.1314; variance ≈0.115\approx 0.115.
    • b=b∗=0.1b = b^* = 0.1: 0.9⋅0.81⋅0.02+0.1⋅0.01⋅1.62=0.01458+0.00162=0.01620.9\cdot 0.81 \cdot 0.02 + 0.1 \cdot 0.01 \cdot 1.62 = 0.01458 + 0.00162 = 0.0162; variance =0= 0.

    With two arms and noiseless rewards, b∗b^* makes every estimate exactly equal to ∇J\nabla J, so the variance is zero. More striking: b=Jb = J is 64 times worse than no baseline at all here. “Use the average reward” is a good rule of thumb, not a theorem.

Exercise 7.7What the environment has to provideConcept●●○

The policy gradient theorem never uses P(s′∣s,a)P(s' \mid s, a) or ∂r/∂a\partial r/\partial a.

  1. What does REINFORCE need from the environment? List everything.
  2. Suppose you had a perfect differentiable simulator: you know PP, and the reward is a smooth function of the state. Describe a different way to get ∇θJ\nabla_\theta J, and why it might have lower variance.
  3. 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
  1. The ability to (a) reset to a start state drawn from p(s0)p(s_0), (b) execute an action and observe the next state and reward, many times, under the current policy. Plus the ability to compute ∇θlog⁡πθ(a∣s)\nabla_\theta \log\pi_\theta(a\mid s) for your own policy. No model, no reward derivatives, no knowledge of what the dynamics are.

  2. With a differentiable simulator and a reparameterized policy (actions at=μθ(st)+σεta_t = \mu_\theta(s_t) + \sigma\varepsilon_t), you can backpropagate the return through the whole rollout: through the reward, through the dynamics st+1=f(st,at)s_{t+1} = f(s_t, a_t), into θ\theta. 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.)

  3. The reward is a step function of a discrete output: tokens are discrete, so there is no ∂y/∂θ\partial y/\partial\theta 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.

Exercise 7.8REINFORCE with 0/1 rewards is fine-tuning on your successesPen & paper●●○

You sample NN responses y(1),…,y(N)y^{(1)}, \dots, y^{(N)} to a prompt; a verifier gives r(i)∈{0,1}r^{(i)} \in \lbrace 0, 1\rbrace, and kk of them are correct.

  1. Show that the no-baseline REINFORCE estimate equals kN\tfrac{k}{N} times the average gradient of log⁡πθ\log\pi_\theta over the kk correct responses, which is the gradient of supervised fine-tuning on your own correct samples, scaled by the success rate p^=k/N\hat p = k/N.
  2. Now use the baseline b=p^b = \hat p. Write the weight on a correct response and on an incorrect one. What does the baseline add that filtered fine-tuning lacks?
  3. For G=4G = 4 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
Split the sum over ii into correct and incorrect responses; the incorrect ones have r(i)=0r^{(i)} = 0.
Solution
  1. 1N∑ir(i)∇log⁡πθ(y(i))=1N∑i: r(i)=1∇log⁡πθ(y(i))=kN⋅1k∑i: r(i)=1∇log⁡πθ(y(i))\frac1N\sum_i r^{(i)}\nabla\log\pi_\theta(y^{(i)}) = \frac1N\sum_{i:\,r^{(i)}=1}\nabla\log\pi_\theta(y^{(i)}) = \frac{k}{N}\cdot\frac1k\sum_{i:\,r^{(i)}=1}\nabla\log\pi_\theta(y^{(i)}). 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.

  2. Correct responses get weight 1−p^1 - \hat p; incorrect ones get −p^-\hat p. The baseline adds negative examples: wrong answers are actively pushed down, and the push is strongest on prompts the model usually gets right (when p^\hat p is near 1, a failure is surprising and informative). It also makes easy prompts contribute little positive push, since 1−p^1 - \hat p is small there: no need to reinforce what is already reliable.

  3. No baseline: (1,0,0,1)(1, 0, 0, 1) (divided by N=4N = 4). With b=0.5b = 0.5: (+0.5,−0.5,−0.5,+0.5)(+0.5, -0.5, -0.5, +0.5). If all four are correct, p^=1\hat p = 1 and every weight is 1−1=01 - 1 = 0: 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).

Exercise 7.9Explore the demosExplore the demo●○○

Use the two demos in this chapter.

  1. In the gradient-cloud demo at the uniform policy with c=0c = 0 and noise σ=0\sigma = 0, 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?
  2. Still at the uniform policy, with σ=0\sigma = 0, read off the spread at b=0b = 0, b=Jb = J and b=10b = 10. Which is the largest?
  3. Drag the policy to about π=(0.8,0.1,0.1)\pi = (0.8, 0.1, 0.1). Is the true gradient bigger or smaller than at the uniform policy? Where do JJ and b∗b^* sit now?
  4. In the race demo, with c=0c = 0, both methods usually work. Explain why, using what you learned about the sign of R−bR - b.
  5. In the race demo, set c=15c = 15 and tap near the arm-2 corner to start there. Play. What fraction of no-baseline runs escape to arm 3?
Solution
  1. Three: with noiseless rewards each arm always gives the same estimate q∗(a)(ea−π)q_*(a)(e_a - \pi). With noise, RR varies but the direction ea−πe_a - \pi 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.

  2. About 4.15, 0.52, and 23(E[(R−10)2])−0.52=23⋅81+64+363−0.52≈39.7\tfrac23(\mathbb{E}[(R-10)^2]) - 0.52 = \tfrac23\cdot\tfrac{81+64+36}{3} - 0.52 \approx 39.7. A badly chosen baseline (far above every reward) is as harmful as none: now every pull pushes its own arm down.

  3. Smaller: ∇J=π⊙(q∗−J)\nabla J = \pi \odot (q_* - J) is small when most probability sits on one arm. Here J=0.8+0.2+0.4=1.4J = 0.8 + 0.2 + 0.4 = 1.4 and ∇J=(0.8⋅(−0.4), 0.1⋅0.6, 0.1⋅2.6)=(−0.32,0.06,0.26)\nabla J = (0.8 \cdot (-0.4),\ 0.1 \cdot 0.6,\ 0.1 \cdot 2.6) = (-0.32, 0.06, 0.26), of length about 0.42 instead of 0.72. For b∗b^*: the squared score norms are ∥e1−π∥2=0.04+0.01+0.01=0.06\lVert e_1 - \pi\rVert^2 = 0.04 + 0.01 + 0.01 = 0.06 and ∥e2−π∥2=∥e3−π∥2=0.64+0.81+0.01=1.46\lVert e_2 - \pi\rVert^2 = \lVert e_3 - \pi\rVert^2 = 0.64 + 0.81 + 0.01 = 1.46, so b∗=(0.8⋅1⋅0.06+0.1⋅2⋅1.46+0.1⋅4⋅1.46)/(0.8⋅0.06+0.2⋅1.46)=0.924/0.34≈2.72b^* = (0.8 \cdot 1 \cdot 0.06 + 0.1 \cdot 2 \cdot 1.46 + 0.1 \cdot 4 \cdot 1.46)/(0.8 \cdot 0.06 + 0.2 \cdot 1.46) = 0.924/0.34 \approx 2.72. It is well above JJ, pulled toward the rewards of the rarely chosen arms 2 and 3, whose scores are large (as in Exercise 7.6).

  4. 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 c=15c = 15, rewards 16, 17, 19 differ by only about 15%, and the “push whatever you pulled” component dominates the signal.

  5. Few: starting at about π=(0.05,0.9,0.05)\pi = (0.05, 0.9, 0.05) with the default α=0.1\alpha = 0.1, 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 R−b≈0R - b \approx 0 once bb has adapted, while a rare pull of arm 3 gives R−b≈+2R - b \approx +2. (Exact counts depend on where you tap.)

Exercise 7.10Build REINFORCE: the labCode●●○

Download the lab below and implement, in pg.py:

  • Task 1 softmax_score(theta, actions): the score ea−πe_a - \pi.
  • Task 2 exact_gradient(theta, q): π⊙(q−J)\pi \odot (q - J). The test checks the worked example’s (−49,−19,59)(-\tfrac49, -\tfrac19, \tfrac59).
  • Task 3 reinforce_estimates(theta, actions, rewards, baseline): (R−b)(ea−π)(R - b)(e_a - \pi) 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 G0G_0, reward-to-go GtG_t, and Gt−V(st)G_t - V(s_t) with a small learned value baseline. Before you run it, predict the order of the three curves.

Hint
Task 4 is one backward loop, 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 b=J=12.33b = J = 12.33 (about 1 there, versus about 100 at b=0b = 0). The minimum is about 1.2 rather than the chapter’s 0.52 because the lab’s rewards have noise σ=1\sigma = 1, which adds 23σ2≈0.67\tfrac23 \sigma^2 \approx 0.67 at every bb (the noise term E[ε2] ∥ea−π∥2\mathbb{E}[\varepsilon^2]\,\lVert e_a - \pi\rVert^2). 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 pass

First time? See Exercises & setup.

Further reading

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.