Policy Gradient for LLMs, Explained Visually

A from-scratch derivation of REINFORCE for language models

Sep 27, 2026

Most RL algorithms used to train language models, from PPO to GRPO, are elaborations of one idea: the policy gradient. This post derives it from scratch for an LLM solving a problem with a checkable answer. It follows one prompt, “What is 17 × 24?”, from next-token probabilities to the gradient that makes correct answers more likely.

Language models as policies

Given a prompt xx, a language model generates a completion y=(y1,…,yT)y = (y_1, \dots, y_T) one token at a time. In RL terms, the model is a policy: at each step it looks at the prefix it has produced so far and outputs a distribution over the next token, from which one token is sampled.

The prompt "What is 17 × 24? Show your work, then give a final answer." and a completion in progress, "17 × 24 = 17 × 20 + 17 × 4 = 340 +", followed by an empty slot. Below it, the model's probabilities for the next token: 68 at 0.82, the slip 58 at 0.07, and small amounts for other tokens. One token is sampled, appended, and the process repeats.

The probability of the full completion is the product of the per-token probabilities:θ\theta is the model’s parameters: its weights, which training adjusts.

pθ(y∣x)=∏t=1Tpθ(yt∣x,y<t) p_\theta(y \mid x) = \prod_{t=1}^{T} p_\theta(y_t \mid x, y_{<t})

Generating a completion traces one path through a tree of possible continuations.Each p(⋅)p(\cdot) in the tree is conditioned on the prompt and on every token before it on the path, so p(24)p(24) means p(24∣x,17,×)p(24 \mid x, 17, \times). The slot from the previous figure is one branch point: 68 leads to the correct answer, and the 58 slip to a wrong one. Once the model emits a stop token, a reward function grades the finished completion.

A tree of possible completions for "What is 17 × 24?". The sampled path starts 17, ×, 24, and its probability is the product 0.6 × 0.9 × 0.7. At "340 +", it branches to 68 with probability 0.82 or 58 with 0.07. The completion reaching 408 gets reward 1 from the verifier, and the one reaching 398 gets reward 0.

For reasoning tasks, the reward function is often a verifier that returns R(x,y)=1R(x, y) = 1 if the final answer is correct and 00 otherwise.This setup is often called RL with verifiable rewards (RLVR). Math problems with a known answer and coding tasks with unit tests are common examples. Our goal is to find the parameters θ\theta that maximize the expected reward, which we call the objective J(θ)J(\theta):Read the objective as: draw a prompt xx from the training set D\mathcal{D}, let the model generate a completion yy, compute its reward, and average over many such draws. The letter JJ comes from optimal control, where it names a cost to minimize. RL borrowed it for a reward to maximize, which is why it isn’t LL, the usual letter for a loss.

J(θ)=Ex∼D,  y∼pθ(⋅∣x)[R(x,y)] J(\theta) = \mathbb{E}_{x \sim \mathcal{D}, \; y \sim p_\theta(\cdot \mid x)}\big[R(x, y)\big]

This is the standard reinforcement learning objective.In general RL, an agent collects a reward after each of many actions, and the objective is the expected total reward over an episode, often discounted. Generating a completion is an episode where each token is an action and the only reward comes at the end, so the total is just R(x,y)R(x, y).

From here on, I’ll drop the prompt xx from the notation; everything is conditioned on it.

The policy gradient

To improve the model, we want to follow the gradient of the objective, ∇θJ(θ)\nabla_\theta J(\theta): the direction in parameter space that most increases the expected reward. This gradient is the policy gradient,The name is short for the gradient of expected reward with respect to the policy’s parameters. It contrasts with value-based methods like Q-learning, which learn how good each action is and act on those estimates instead of adjusting the policy directly. The term became standard with Sutton et al. (2000). and methods that train by estimating and following it are called policy gradient methods. REINFORCE, PPO, and GRPO are all examples. They share this expected-reward goal, but PPO and GRPO also change the update itself, clipping or reweighting it to keep training stable.

The hard part is computing it. Written out, the objective is a sum over every possible completion:

J(θ)=∑ypθ(y) R(y) J(\theta) = \sum_y p_\theta(y) \, R(y)

θ\theta appears only in pθ(y)p_\theta(y), how likely each completion is, and not in the reward R(y)R(y). If we could evaluate this sum, we could differentiate it directly, but there are far too many completions to enumerate.With a vocabulary of about 150,000 tokens, even a 100-token completion has more than 1050010^{500} possibilities.

The usual fix for an expectation we can’t enumerate is to estimate it by sampling: generate NN completions, compute their rewards, and average them. That gives a fine estimate of JJ, but not one we can differentiate. The completions are discrete token sequences,At each step, the model’s probabilities define a categorical distribution over the vocabulary, and we draw one token from it. The result is an integer token ID: a small change to θ\theta either leaves it unchanged or flips it, so there is no smooth gradient. (Sampling often reshapes the distribution with a temperature or top-p cutoff. The derivations here assume we sample from the model’s probabilities as-is.) and their rewards come from a verifier, a unit test, or a person, none of which we can backpropagate through. There is no path for autograd to follow from the reward back to θ\theta.

Compare supervised fine-tuning, where the completion yy is fixed training data and θ\theta appears directly in the loss −log⁡pθ(y)-\log p_\theta(y). Here, θ\theta decides which completions we get, not how any one of them is graded. What we need is a way to rewrite ∇θJ\nabla_\theta J as an average, over sampled completions, of something we can differentiate.

The log-derivative trick

The workaround is a one-line identity, ∇θpθ=pθ∇θlog⁡pθ\nabla_\theta p_\theta = p_\theta \nabla_\theta \log p_\theta,By the chain rule, ∇θlog⁡pθ=∇θpθ/pθ\nabla_\theta \log p_\theta = \nabla_\theta p_\theta / p_\theta. Multiply both sides by pθp_\theta. which moves the gradient inside the expectation:

∇θJ(θ)=∇θ Ey∼pθ[R(y)]=∇θ∑ypθ(y) R(y)=∑y∇θpθ(y)⏟depends on θ R(y)=∑ypθ(y) ∇θlog⁡pθ(y)⏟the identity R(y)=Ey∼pθ[R(y) ∇θlog⁡pθ(y)⏟the score] \begin{aligned} \nabla_\theta J(\theta) &= \nabla_\theta \, \mathbb{E}_{y \sim p_\theta}\big[R(y)\big] \\ &= \nabla_\theta \sum_y p_\theta(y) \, R(y) \\ &= \sum_y \underbrace{\nabla_\theta p_\theta(y)}_{\mathclap{\text{depends on } \theta}} \, R(y) \\ &= \sum_y \underbrace{p_\theta(y) \, \nabla_\theta \log p_\theta(y)}_{\mathclap{\text{the identity}}} \, R(y) \\ &= \mathbb{E}_{y \sim p_\theta}\big[R(y) \, \underbrace{\nabla_\theta \log p_\theta(y)}_{\mathclap{\text{the score}}}\big] \end{aligned}

The quantity ∇θlog⁡pθ(y)\nabla_\theta \log p_\theta(y) is called the score.Don’t read much into the word: it doesn’t rate how good a completion is. The name comes from statistics, where ∇θlog⁡p\nabla_\theta \log p is the score function of maximum-likelihood estimation. REINFORCE is sometimes called the score-function estimator for the same reason. It points in the direction in parameter space that most increases the log-probability of the completion yy. The final line is an expectation over completions sampled from the policy pθp_\theta itself,This is the language-model case of the policy gradient theorem (Sutton et al., 2000). In general RL, it reads ∇θJ=E[∑tQπ(st,at) ∇θlog⁡πθ(at∣st)]\nabla_\theta J = \mathbb{E}\big[\sum_t Q^\pi(s_t, a_t)\, \nabla_\theta \log \pi_\theta(a_t \mid s_t)\big] (πθ\pi_\theta is the usual RL notation for the policy pθp_\theta), where Qπ(st,at)Q^\pi(s_t, a_t) is the expected future reward after taking action ata_t in state sts_t. For a completion, the state is the prefix and the action is the next token. With only a final reward, QπQ^\pi is the expected reward of finishing from that prefix, and the sampled RR is a one-sample estimate of it. so we can estimate it by sampling. Perform NN rollouts (that is, draw NN completions from the policy), score each one, and average:

∇θJ(θ)≈1N∑i=1NR(yi) ∇θlog⁡pθ(yi),yi∼pθ \nabla_\theta J(\theta) \approx \frac{1}{N} \sum_{i=1}^{N} R(y_i) \, \nabla_\theta \log p_\theta(y_i), \qquad y_i \sim p_\theta

This is the REINFORCE estimator,Introduced by Ronald Williams in Simple Statistical Gradient-Following Algorithms for Connectionist Reinforcement Learning (1992). PPO, GRPO, DAPO, and most other RL algorithms used for LLMs today are elaborations of this estimator. also known as the Monte Carlo policy gradient: it estimates the gradient by averaging over complete sampled rollouts, using each one’s actual reward rather than a learned estimate of how good it was.It is unbiased: averaged over many batches, it equals the true gradient. Any single batch, though, can point well away from it. Each term pairs a direction with a weight: the score points toward making that rollout’s completion more likely, and the reward sets how much that direction counts.

Four rollouts for "What is 17 × 24?": A and C reach 408 and earn reward 1, while B (an arithmetic slip) and D (an estimate) earn 0. A bar holding all the probability for this prompt shows A rising from 0.22 to 0.27 and C from 0.03 to 0.05 after one update, B and D barely changing, and unsampled completions shrinking.

Because all completions share a total probability of 1, A’s and C’s gains come from elsewhere, here mostly from completions nobody sampled. B barely changes, because it shares everything up to “340 +” with A, so reinforcing A also lifts most of B’s path. The numbers are only illustrative: A and C are pushed up, but how every other completion moves depends on how the model’s parameters are shared.

With the reward held fixed, R ∇θlog⁡pθ(y)R \, \nabla_\theta \log p_\theta(y) is exactly the gradient of Rlog⁡pθ(y)R \log p_\theta(y): a log-likelihood on one of the model’s own samples, weighted by its reward. So policy gradient is supervised fine-tuning on your own samples, weighted by reward. With +1/0+1/0 rewards, as in the figure above, it is literally SFT on the correct completions, so incorrect completions are never pushed down directly; they only lose share.Training on your own correct samples is also used on its own, as rejection-sampling fine-tuning or expert iteration. STaR is an early example for reasoning.

From sequences to tokens

A completion’s log-probability is a sum of per-token log-probabilities, so its score breaks into one term per token:

∇θlog⁡pθ(y)=∑t=1T∇θlog⁡pθ(yt∣y<t) \nabla_\theta \log p_\theta(y) = \sum_{t=1}^{T} \nabla_\theta \log p_\theta(y_t \mid y_{<t})

Each term is the score of a single token: the direction that most increases the probability of choosing yty_t, given everything generated before it. So we can study the update one position at a time. Pick a single position, such as the slot right after “340 +” in the 17 × 24 example, and hold its prefix y<ty_{<t} fixed. For each token vv in the vocabulary, write

pv=pθ(v∣y<t)andsv=∇θlog⁡pv p_v = p_\theta(v \mid y_{<t}) \qquad \text{and} \qquad s_v = \nabla_\theta \log p_v

for the model’s probability of choosing vv at this position and that token’s score. In the example, p68=0.82p_{68} = 0.82 and p58=0.07p_{58} = 0.07.

Only one token is actually sampled at each position. Its contribution to the update is R sytR \, s_{y_t}: that token’s score, multiplied by the reward the whole completion earned.

To see what a token’s score looks like, look at the last layer. At one position, the network outputs a logit zuz_u for every token uu in the vocabulary, and p=softmax⁡(z)p = \operatorname{softmax}(z). Differentiating the log-softmax gives the logit gradient of the chosen token vv:

log⁡pv=zv−log⁡∑uezu⟹∂log⁡pv∂zu={1−pvu=v−puu≠v \log p_v = z_v - \log \sum_u e^{z_u} \qquad\Longrightarrow\qquad \frac{\partial \log p_v}{\partial z_u} = \begin{cases} 1 - p_v & u = v \\ -p_u & u \neq v \end{cases}

It is positive on the chosen token’s own logit, negative on every other logit in proportion to that token’s probability, and sums to zero. The score is this vector carried back through the network to the parameters by the chain rule:

sv=∑u(1[u=v]−pu) ∇θzu s_v = \sum_u \big(\mathbb{1}[u = v] - p_u\big) \, \nabla_\theta z_u

As pv→1p_v \to 1, every coefficient in this sum goes to zero, so the score does too. Across completions A and B from the figure above:

Completions A (reward 1) and B (reward 0) as rows of tokens, each labeled with its probability and its own-logit gradient, 1 − p, with an arrow of that length. In A, uncertain tokens like 17, 24, and 68 get large gradients and confident filler almost none. Zoom-ins show the full logit gradient summing to zero. In B, every score is multiplied by 0, so nothing updates.

The reward only says whether the finished completion was right, so every position gets the same RR, whatever its token did:This is the credit assignment problem. Methods that learn a value function, or use process reward models that grade intermediate steps, try to give individual tokens their own credit. B’s correct opening steps get nothing, and A’s filler tokens get the full reward. What differs from token to token is the score, which is tiny for tokens the model was already sure of.The actual step also scales with the learning rate and depends on how the network maps parameters to logits, and a token’s probability can still change because of other tokens’ gradients.

The score has zero mean

The score has a simple but important property. On-policy, when the token is sampled from the same distribution pp whose score we compute, the expected score is exactly zero:

Eyt∼p[syt]=∑vpv ∇θlog⁡pv=∑v∇θpv=∇θ∑vpv=∇θ1=0 \begin{aligned} \mathbb{E}_{y_t \sim p}[s_{y_t}] &= \sum_v p_v \, \nabla_\theta \log p_v = \sum_v \nabla_\theta p_v \\ &= \nabla_\theta \sum_v p_v = \nabla_\theta 1 = 0 \end{aligned}

Intuitively, probability is conserved. Any change to θ\theta that makes some tokens more likely must make others less likely by the same total amount. Weighted by how often each token is sampled, the pushes cancel.

We can check this at the logits. In vector form, the logit gradient from the previous section is ev−pe_v - p, where eve_v is the one-hot vector for vv; the zoom-ins in the figure above show it for 68 and for “=”. Averaging these vectors over which token gets sampled, weighted by pp, gives ∑vpv(ev−p)=p−p=0\sum_v p_v (e_v - p) = p - p = 0.

Baselines and group centering

Nothing so far required the rewards to be +1/0+1/0. What if we use +1/−1+1/-1 instead? That doubles every reward and then subtracts 1. Doubling just doubles the gradient. For the shift, the zero-mean identity is the answer: we can subtract any baseline bb from the reward without changing the expected gradient, as long as bb does not depend on the sampled token:

Ep[(R−b) syt]=Ep[R syt]−b Ep[syt]⏟= 0=Ep[R syt] \mathbb{E}_{p}\big[(R - b) \, s_{y_t}\big] = \mathbb{E}_{p}[R \, s_{y_t}] - b \, \underbrace{\mathbb{E}_{p}[s_{y_t}]}_{=\,0} = \mathbb{E}_{p}[R \, s_{y_t}]

The quantity A=R−bA = R - b is called the advantage. Subtracting a baseline adds no bias: REINFORCE stays unbiased, with exactly the same expected gradient. What it can change is the variance, and a well-chosen baseline reduces it dramatically.See Greensmith, Bartlett, and Baxter (2004) for a thorough treatment of baselines as variance reduction for policy gradient estimates. To see why, split each rollout’s term in two:

R syt=b syt⏟mean zero, but noisy+(R−b) syt⏟the advantage-weighted part R \, s_{y_t} = \underbrace{b \, s_{y_t}}_{\text{mean zero, but noisy}} + \underbrace{(R - b) \, s_{y_t}}_{\text{the advantage-weighted part}}

The first part contributes nothing to the expected gradient, but each sample of it is a large vector pointing somewhere different. In the extreme case where every completion earns R=1R = 1, the true gradient is zero, yet each sample still pushes its own log-probabilities up at random. With b=1b = 1, every term vanishes. How much a baseline helps depends on bb. The standard choice is the prompt’s expected reward. It isn’t exactly optimal,The variance depends on bb only through E[(R−b)2∥s∥2]\mathbb{E}\big[(R - b)^2 \lVert s \rVert^2\big], which is minimized at b⋆=E[R∥s∥2]/E[∥s∥2]b^\star = \mathbb{E}\big[R \lVert s \rVert^2\big] / \mathbb{E}\big[\lVert s \rVert^2\big]. This is close to E[R]\mathbb{E}[R] only when the reward is roughly unrelated to the size of the score. They can differ a lot: for a binary choice that succeeds with probability 0.1, successes have the larger score, so b⋆=0.9b^\star = 0.9 while E[R]=0.1\mathbb{E}[R] = 0.1. but it is simple to estimate, and because some prompts are far easier than others, estimating it per prompt removes a large source of noise.

GRPOIntroduced in DeepSeekMath. GRPO also divides by the group’s reward standard deviation. Dr. GRPO argues that this normalization introduces a bias toward easy and hard prompts. Here I use mean-centering only. Because the group mean includes the completion’s own reward, the expected gradient is scaled by 1−1/G1 - 1/G. When every prompt uses the same GG, that is just a slightly smaller step size. A leave-one-out baseline, as in RLOO, removes the factor. popularized a simple, critic-freeA critic is a second network trained to predict the expected reward, the value V(x)V(x), to use as the baseline. PPO usually trains one alongside the policy. GRPO replaces it with the group’s mean reward, which saves a model of similar size to the policy. baseline for LLMs: sample a group of GG completions for each prompt and use the group’s mean reward as the baseline for each of them:

Ai=Ri−1G∑j=1GRj A_i = R_i - \frac{1}{G} \sum_{j=1}^{G} R_j

Correct completions now get a positive advantage and are reinforced. Incorrect completions get a negative advantage and are suppressed. Prompts where every completion succeeds, or every completion fails, contribute nothing. For the four rollouts from earlier:

The same four rollouts with group-centered advantages. The group mean reward is 0.5, so A and C get advantage +0.5 and are pushed up, while B and D get −0.5 and are pushed down. Along the prefix A and B share, their pushes cancel.

REINFORCE with group-centered advantages fits in a few lines of PyTorch:

def reinforce_loss(logprobs, rewards, mask, group_size):
    # logprobs: (B, T) per-token log p_θ(y_t | y_<t)
    # rewards:  (B,)   one per completion, grouped by prompt
    # mask:     (B, T) 1 on completion tokens, else 0
    r = rewards.view(-1, group_size)
    advantages = (r - r.mean(dim=1, keepdim=True)).view(-1)
    seq_logprobs = (logprobs * mask).sum(dim=1)  # log p_θ(y)
    return -(advantages * seq_logprobs).mean()

The advantages are constants that carry no gradient, so differentiating this loss gives exactly the estimator from the previous sections, with advantages in place of rewards.Many implementations instead divide the summed loss by the total number of completion tokens in the batch. That changes more than the scale: the denominator varies with the sampled lengths, so it reweights completions by length. Dr. GRPO discusses this bias. PPO, GRPO, DAPO, and most other RL algorithms used for LLMs start from this loss and add clipping, masking, or reweighting.

The on-policy assumption

Both identities in this post, the log-derivative rewrite and the zero-mean score, assume that the completions are sampled from the same distribution pθp_\theta that we differentiate. In the rewrite, pθp_\theta is both the distribution we average over and the model we differentiate. In the zero-mean identity, averaging over pp itself is what makes the pushes cancel. If the samples come from even a slightly different distribution, the expected score is no longer guaranteed to be zero, and subtracting a baseline shifts the expected gradient instead of leaving it unchanged.

In practice, this assumption rarely holds exactly. In the reinforce_loss above, logprobs comes from the training framework’s forward pass, but the completions were generated by a separate inference engine, such as vLLM or SGLang. The two are supposed to compute the same distribution, but they seldom do. They can run at different numerical precisions, and in asynchronous setups the inference engine may still be serving weights from a few updates ago. Either way, the completions come from a slightly different model than the one being trained. That gap is where the trouble starts.

Further reading

References

Ahmadian, A., Cremer, C., Gallé, M., Fadaee, M., Kreutzer, J., Pietquin, O., Üstün, A., & Hooker, S. (2024). Back to Basics: Revisiting REINFORCE Style Optimization for Learning from Human Feedback in LLMs. https://arxiv.org/abs/2402.14740
Anthony, T., Tian, Z., & Barber, D. (2017). Thinking Fast and Slow with Deep Learning and Tree Search. https://arxiv.org/abs/1705.08439
Fisher, R. A. (1925). Theory of Statistical Estimation. Mathematical Proceedings of the Cambridge Philosophical Society, 22(5), 700–725. https://doi.org/10.1017/S0305004100009580
Greensmith, E., Bartlett, P. L., & Baxter, J. (2004). Variance Reduction Techniques for Gradient Estimates in Reinforcement Learning. Journal of Machine Learning Research, 5, 1471–1530. https://jmlr.org/papers/v5/greensmith04a.html
Lambert, N., & others. (2024). Tulu 3: Pushing Frontiers in Open Language Model Post-Training. https://arxiv.org/abs/2411.15124
Lightman, H., Kosaraju, V., Burda, Y., Edwards, H., Baker, B., Lee, T., Leike, J., Schulman, J., Sutskever, I., & Cobbe, K. (2023). Let’s Verify Step by Step. https://arxiv.org/abs/2305.20050
Liu, Z., Chen, C., Li, W., Qi, P., Pang, T., Du, C., Lee, W. S., & Lin, M. (2025). Understanding R1-Zero-Like Training: A Critical Perspective. https://arxiv.org/abs/2503.20783
Schulman, J., Wolski, F., Dhariwal, P., Radford, A., & Klimov, O. (2017). Proximal Policy Optimization Algorithms. https://arxiv.org/abs/1707.06347
Shao, Z., Wang, P., Zhu, Q., Xu, R., Song, J., Bi, X., Zhang, H., Zhang, M., Li, Y. K., Wu, Y., & Guo, D. (2024). DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models. https://arxiv.org/abs/2402.03300
Sutton, R. S., & Barto, A. G. (2018). Reinforcement Learning: An Introduction (2nd ed.). MIT Press. http://incompleteideas.net/book/the-book-2nd.html
Sutton, R. S., McAllester, D., Singh, S., & Mansour, Y. (2000). Policy Gradient Methods for Reinforcement Learning with Function Approximation. Advances in Neural Information Processing Systems, 12. https://papers.nips.cc/paper/1713-policy-gradient-methods-for-reinforcement-learning-with-function-approximation
Watkins, C. J. C. H., & Dayan, P. (1992). Q-learning. Machine Learning, 8, 279–292. https://doi.org/10.1007/BF00992698
Williams, R. J. (1992). Simple Statistical Gradient-Following Algorithms for Connectionist Reinforcement Learning. Machine Learning, 8, 229–256. https://link.springer.com/article/10.1007/BF00992696
Yu, Q., & others. (2025). DAPO: An Open-Source LLM Reinforcement Learning System at Scale. https://arxiv.org/abs/2503.14476
Zelikman, E., Wu, Y., Mu, J., & Goodman, N. D. (2022). STaR: Bootstrapping Reasoning With Reasoning. https://arxiv.org/abs/2203.14465