Skip to content

PPO: The Algorithm Behind Most RLHF

11 min read · updated August 4, 2026

PPO is an actor-critic method with one addition: a clip that stops a single update from moving the policy further than the collected data can justify. Every design decision in it follows from that one concern, and the objective is much easier to read once you know which disaster it is guarding against.

The failure the clip exists to prevent

Policy gradient data is perishable. You run the current policy, collect a batch, and every advantage in that batch describes the world as seen by that policy. Update, and the batch is now a description of a policy you no longer have.

Usually that is a small inaccuracy. Occasionally it is a catastrophe. Suppose one action in the batch got a large positive advantage by luck. The gradient pushes its probability up hard; the step is large enough that the policy becomes something quite different; the new policy visits states that never appeared in the batch, so the critic’s values there are guesses; the next batch is collected under the damaged policy and reflects its behaviour rather than the good one you had.

There is no path back. Supervised learning recovers from a bad step because the dataset is unchanged and the next epoch sees the same correct labels. Reinforcement learning does not, because the data source is the thing that was damaged. This is the single most characteristic failure mode of the field, and it is why the useful question is not “which direction improves the objective” but “how far can we move before the estimate stops being trustworthy”.

The ratio, and why data goes stale

To reuse a batch collected under pi_old for a policy that has since moved, importance sampling reweights each sample by how much more or less likely the new policy is to have produced it:

r_t(theta)  =  pi_theta(a_t | s_t)  /  pi_old(a_t | s_t)

r = 1.0   the new policy would act identically here
r = 1.2   the new policy is 20% more likely to take this action
r = 5.0   the new policy is five times more likely -- this sample is now
          being counted five times, and it was only observed once

Importance sampling is exactly correct in expectation and increasingly useless in practice as the ratio moves away from 1, because the variance of a reweighted estimate grows with the weights. A handful of samples with large ratios come to dominate the batch. The estimate is unbiased and worthless — which is a specific, recognisable statistical situation and not a vague warning.

The clipped objective

PPO’s answer, from Schulman et al. (2017, arXiv 1707.06347), is to take the pessimistic view of every sample:

L(theta) = E[ min( r_t(theta) * A_t ,
                   clip(r_t(theta), 1 - eps, 1 + eps) * A_t ) ]

with eps typically 0.2

The min is doing something subtler than it looks. It is not symmetric clipping. It removes the incentive to keep moving in the direction you are already moving, once you are outside the trust region, while leaving the incentive to move back untouched. The result is a soft trust region that costs one comparison per sample — no second-order optimisation, no KL constraint solved per step, which is what made PPO practical where its predecessor TRPO was not.

The four cases, with numbers

Take eps = 0.2 and an advantage of magnitude 2, and evaluate both arms of the min.

CaseDescription
A = +2, r = 1.5Unclipped arm 3.0; clipped arm 1.2 * 2 = 2.4. min = 2.4, the clipped one. The objective is flat in theta here, so the gradient is zero: the update has already made this good action much more likely and PPO refuses to go further on this batch.
A = +2, r = 0.5Unclipped 1.0; clipped 0.8 * 2 = 1.6. min = 1.0, the unclipped one. Gradient flows, pushing the probability of this good action back up. Moving back towards pi_old is never blocked.
A = -2, r = 1.5Unclipped -3.0; clipped 1.2 * -2 = -2.4. min = -3.0, the unclipped one. Gradient flows, pushing this bad action down hard. This is the asymmetry: a bad action whose probability went up is always corrected, however far it went.
A = -2, r = 0.5Unclipped -1.0; clipped 0.8 * -2 = -1.6. min = -1.6, the clipped one. Gradient zero. The probability of this bad action has already dropped by more than eps on this batch; that is enough.

Read the four rows together and the rule is: clipping only ever switches off the gradient for a sample the update has already moved far enough in the right direction. Nothing that needs correcting is ever clipped away. A reasonable sanity check while training is the fraction of samples being clipped — commonly reported as a clip fraction, and typically between a few per cent and about 0.3. Near zero means the steps are too small to need the mechanism; near one means almost every gradient is being switched off and the learning rate is far too high.

The hyperparameters that actually move things

SettingDescription
eps (clip range)0.1 to 0.3, commonly 0.2. Smaller is more conservative and slower. This is the width of the trust region and the first thing to lower when training goes unstable.
epochs per batchHow many gradient passes over the same collected data, commonly 3 or 4. This is the reason the clip exists at all: on the first pass every ratio is exactly 1 and the clip does nothing. Raising this raises sample efficiency and the risk of drifting outside the trust region.
minibatch sizeThe batch is split for the gradient passes. Smaller minibatches mean more updates per batch, so the ratio drifts further within an epoch.
gamma and lambda0.99 and 0.95 are the usual control-task defaults. In language model post-training gamma is normally 1, because episodes are short and there is no reason to prefer an early token.
value coefficientWeight on the critic loss in the combined objective, commonly 0.5. Only relevant when actor and critic share a trunk.
entropy coefficientA small bonus, often 0 to 0.01, that resists premature determinism. In language model training this interacts with sampling temperature and is frequently set to zero in favour of a KL term.

PPO inside an RLHF pipeline

The version used for RLHF is the same algorithm in an unusual environment. The episode is one completion. The state is the prompt plus the tokens so far, the action is the next token, and the environment is a text buffer with no dynamics of its own.

Four models are resident. The policy is being trained. The reference is a frozen copy of the starting model. The reward model is frozen and scores completed responses. The value model is trained alongside the policy. That is roughly four times the memory of a fine-tune, plus a generation loop in the middle of training, and it is the practical reason lighter methods attract so much interest.

The reward is sparse in a specific way: the reward model scores the whole response, so the environment returns zero at every token except the last. On top of that, a per-token KL penalty against the reference model is added to the reward. This is the point most often confused, so it is worth stating flatly:

  • The clip is a constraint against the previous iterate. It stops one optimisation step from being too large. It resets every time a new batch is collected.
  • The KL penalty is an anchor to the starting model. It stops the policy drifting arbitrarily far from the supervised fine-tuned model over the whole run, which is what keeps the reward model inside the distribution it was trained on. It accumulates across the entire training run.

They solve different problems and you need both. Remove the clip and individual updates go wild; remove the KL and the policy walks somewhere the reward model scores highly and humans do not, which is reward hacking in its most predictable form.

Reading a PPO run from its metrics

PPO exposes an unusually informative set of diagnostics, and knowing what each one says turns a mysterious run into a readable one. These are the six worth plotting, and what a bad value of each means.

MetricDescription
mean rewardThe thing you care about, and the least diagnostic. It tells you something is wrong and never what. Plot it, then look at the others.
clip fractionShare of samples where the clipped arm of the min was selected. Near zero means updates are too small for the mechanism to matter; above roughly 0.3 means most gradients are being switched off and the learning rate or the epoch count is too high.
approximate KL per updateHow far the policy moved on this batch, estimated from the log-ratios. This is the quantity the clip is trying to bound indirectly. Many implementations stop the epoch loop early when it exceeds a threshold, which is a more direct trust region than the clip alone.
KL from the referenceCumulative distance from the starting model over the whole run. Distinct from the previous line, and it is the one that predicts reward model over-optimisation: reward rising while this rises steeply is the shape to stop on.
policy entropyHow much the policy still varies. A steep fall early is entropy collapse and it usually precedes a plateau by some margin, so it is an early warning rather than a post-mortem.
explained variance of the value model1 - Var(returns - values) / Var(returns). At 0 the critic is no better than predicting the mean, and every advantage it produces is noise. If this is near zero, fix the critic before touching anything on the actor.

The pairing that resolves most confusion is entropy against clip fraction. High clip fraction with falling entropy is a policy being pushed too hard and collapsing; low clip fraction with flat entropy and flat reward is a policy that is barely moving, which is a learning rate problem and not a trust region one. The two look identical on a reward curve.

What PPO does not fix

PPO is a variance and step-size solution. It has nothing to say about three things that will decide whether your run works.

  1. A wrong reward. PPO will optimise a bad reward function very effectively. The clip constrains how fast the policy moves, not where it is going.
  2. Exploration. Nothing in PPO seeks out unvisited states. It improves what the current policy already does occasionally, which is fine for text and inadequate for problems where the reward is behind a door the agent has never opened.
  3. Seed variance. Two identical runs with different random seeds can end at meaningfully different performance. Henderson et al. (2018), “Deep Reinforcement Learning that Matters”, documented this across algorithms and it has not stopped being true. Report several seeds or report nothing.

The direction the field moved after PPO is towards dropping pieces of it. DPO drops the reward model, the value model and the sampling loop. GRPO keeps the sampling and the clip and drops the value model, replacing the learned baseline with the mean reward of a group of samples for the same prompt.