Paper 89~11 min read2017worked math + runnable code
Paper Breakdown

PPO,
explained.

Reinforcement learning has a self-destruct button. Push the policy toward a good action too hard, off one noisy batch of experience, and it lurches somewhere terrible — and now every future batch is collected by a broken policy. The fix that made RL practical for hard problems, and later for aligning language models, is almost embarrassingly simple: clip the step. PPO measures how far the new policy has moved with a probability ratio, and refuses to reward moving too far. No second-order math, no hard constraint — just a min and a clip that keep every update inside a trust region. Here's the objective, and why that one clip is enough.

Video breakdown
The animated walkthrough is in production.
Read the full breakdown below in the meantime ↓
01

The self-destruct button

Policy-gradient RL learns by trial: run the current policy, see which actions did better than expected — a positive advantage A — and nudge the policy to make those actions more likely. Simple in principle, treacherous in practice. The advantage is estimated from data collected by the old policy, so it's only valid nearby. Take a big step and the new policy is a stranger to that data: the estimate no longer applies, and the update can send performance off a cliff. Worse, RL is on-policy — the broken policy now collects the next batch, so a single bad step can spiral.

The earlier fix, TRPO, solved this with a hard trust region: constrain each update so the new policy stays within a bounded KL distance of the old one. It works, but it needs heavy second-order optimization that's fiddly to implement and scale. PPO (Schulman et al., 2017) asked: can we get the same "don't step too far" safety with plain first-order gradient descent and a couple of lines of code? The answer — a clipped objective — is the reason PPO became the default RL algorithm, all the way up to the alignment of large language models.

The one-sentence version

Measure how much the policy changed with the ratio r = π_new/π_old, and maximize min(r·A, clip(r, 1−ε, 1+ε)·A) — so once the ratio leaves the band 1±ε in the helpful direction, the objective stops rewarding it and the step stays inside a soft trust region.

02

The probability ratio

To limit "how far the policy moved," PPO needs to measure it. The tool is the probability ratio: for a state-action pair, r = π_new(a|s) / π_old(a|s) — how much more (or less) likely the new policy is to take an action than the old policy that gathered the data. r = 1 is no change; r > 1 means the new policy now favors the action more; r < 1, less.

This ratio is the lever of the whole update. The surrogate objective — the thing plain policy gradients maximize — is r · A: push the ratio up for good actions (positive A), down for bad ones. But nothing stops r from running to 5 or 0.1 on a single batch, and a ratio far from 1 is exactly the danger sign: the policy has moved so far from the data that A is no longer trustworthy. PPO's entire contribution is a way to cap the reward for moving the ratio too far — to make the objective indifferent to steps that leave the safe neighborhood. That's the clip.

03

Clip the surrogate

PPO takes the surrogate r · A and pins the ratio inside a band [1−ε, 1+ε] (typically ε = 0.2), then takes the minimum of the clipped and unclipped versions. The min is the clever part — it makes the objective a pessimistic bound that only ever removes the incentive to over-step:

What the clip does, by sign of the advantage
A > 0Good action. Raising r helps — but past 1+ε the clip caps it, so no runaway increase.
A < 0Bad action. Lowering r helps — but past 1−ε the clip caps it, so no runaway decrease.
min(·)Takes the more pessimistic of clipped/unclipped → only ever removes incentive to over-step.
EffectOnce r leaves the band in the helpful direction, the gradient goes flat — a soft trust region.

The result is a soft trust region built from a clip instead of a constraint. When the ratio is inside the band, PPO behaves like an ordinary policy gradient. When a good action's ratio tries to climb past 1+ε, the clipped term flattens — the objective stops improving, so the gradient for that sample is zero and the update stops pushing. The min ensures the clip only bites in the "helpful" direction, so it never accidentally encourages a large step. All of this is plain arithmetic on scalars — no KL constraint, no conjugate gradients, no line search. That simplicity, with TRPO-like stability, is the whole point.

04

The min objective

The clipped surrogate is a single expression. With ratio r, advantage A, and clip range ε:

LCLIP  =  min(  r · A ,   clip(r, 1−ε, 1+ε) · A  )

At r = 1 it's just A. For A > 0, a large r is capped at (1+ε)·A. The min makes it pessimistic — it can only lower the objective relative to r·A, never raise it, so over-stepping is never rewarded.

Worked: with ε = 0.2, a good action whose ratio jumped to 1.5 is capped — but a bad action whose ratio rose to 1.5 is penalized in full, because the min picks the worse value:

A=+1, r=1.5 → min(1.5, 1.2) = 1.2     A=−1, r=1.5 → min(−1.5, −1.2) = −1.5

Good action, big step up: capped at 1.2 (no runaway reward). Bad action, ratio drifted up: the full −1.5 penalty applies — the clip protects against over-eager increases, not against paying for mistakes. The runnable version below computes the ratio, the clipped objective, and when the ratio leaves the trust region.

RUN IT YOURSELF

The clipped objective, from scratch

PPO's whole trick is one expression: min(r·A, clip(r,1−ε,1+ε)·A), where r = π_new/π_old is the probability ratio and A is the advantage. At r=1 it equals the advantage. For a good action (A>0), a large ratio is capped at (1+ε)·A — no runaway step. For a bad action (A<0), the min applies the penalty in full. A ratio is "clipped" exactly when it leaves the trust region [1−ε, 1+ε]. Change the ratio, advantage, or ε and watch the objective flatten past the band.

CPython · WebAssembly
05

What it showed

PPO delivered TRPO-level stability with first-order simplicity, and became the RL default:

ContributionSignificance
Clip beats hard constraintA simple clipped objective matched TRPO's trust-region stability without second-order optimization.
First-order, easy to implementPlain SGD/Adam on a scalar objective — a few lines — made strong RL accessible.
Sample reuseThe ratio lets PPO take several gradient steps on the same batch safely, improving data efficiency.
Robust across domainsStrong on continuous control and games with little per-task tuning — it just works.

PPO isn't the most sample-efficient RL algorithm, and off-policy methods can beat it on that axis. But its combination of stability, simplicity, and robustness made it the pragmatic first choice for a huge range of problems — the algorithm you reach for when you want something that reliably works rather than something exotic.

06

The RLHF workhorse

PPO's second life is in aligning language models. RLHF — reinforcement learning from human feedback — fine-tunes a model to maximize a reward model's score, and that's an RL problem, optimized with PPO. InstructGPT and the RLHF pipelines that made chat assistants helpful and harmless used PPO as the optimizer, precisely because its clipped objective keeps the model from lurching too far from its previous behavior in any single update — exactly what you want when the "policy" is a giant, hard-won language model you don't dare destabilize.

That role made PPO one of the most consequential algorithms in modern AI, far outside its original control-and-games home. It's also a moving target: newer variants trim its machinery — GRPO drops the learned value network and estimates advantages from groups of sampled outputs, simplifying the RLHF stack that PPO defined, and it's central to reasoning-model training like DeepSeek-R1. But the core idea PPO crystallized endures across all of them: improve the policy from experience, and never let a single update wander outside the region where that experience is still trustworthy.

Worth knowing

In RLHF, PPO's objective usually carries an extra KL penalty against the original (pre-RL) model on top of the clip — a second leash that keeps the fine-tuned policy from drifting too far from the base model's language, preventing reward-model "hacking" where the policy exploits quirks of the reward at the cost of coherent, on-distribution text.

Frequently asked

Quick answers

What is PPO?

A stable, simple policy-gradient RL algorithm that limits each update with a clipped surrogate objective — the RL default and the optimizer behind RLHF.

What is the probability ratio?

r = π_new/π_old — how much more likely the new policy is to take an action than the old one. PPO caps the reward for pushing it far from 1.

How does the clip work?

Maximize min(r·A, clip(r,1−ε,1+ε)·A): once r leaves [1−ε,1+ε] in the helpful direction, the objective flattens — a soft trust region.

Why is PPO used in RLHF?

RLHF is an RL problem; PPO's stability keeps a huge language model from lurching in one update. InstructGPT and successors used it as the optimizer.

Finished this one? 0 / 101 Paper Breakdowns done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More Paper Breakdowns