Proximal Policy Optimization

A robotics team trains a legged robot to walk using policy gradients. One update step is slightly too aggressive. The policy collapses into a pose where all actions produce zero torque. Days of training are lost. This is the central failure mode that Trust-Region Policy Optimization solves. Proximal Policy Optimization (PPO) makes the solution practical at scale. Policy gradient methods improve a policy by taking gradient steps on expected return. But naive gradient ascent can take steps so large that the new policy is catastrophically worse than the old one. Because data is collected by the policy itself, one bad step can poison all future data collection. TRPO fixes this by constraining each update to a trust region using a hard KL-divergence constraint. This constraint is solved via conjugate gradients and a line search. This works but is expensive, hard to implement correctly. It is also awkward to combine with shared actor-critic networks and recurrent architectures. PPO was designed as a first-order approximation to TRPO's guarantees. Instead of a hard constraint enforced by second-order optimization, PPO clips the objective function itself. This makes the incentive to move the policy too far simply vanish from the gradient. This turns a constrained optimization problem into an unconstrained one. It becomes solvable with plain stochastic gradient descent, using only first-order gradients. No Hessian-vector products, conjugate gradient solvers, or backtracking line searches are needed. This article develops the clipped surrogate objective from first principles. It works through the full actor-critic training loop with Generalized Advantage Estimation. It derives why clipping approximates a trust region, and traces a concrete numerical update. It closes by situating PPO among its relatives. It previews how entropy bonuses further stabilize training, foreshadowing Entropy Regularization.

Key takeaways
  • PPO replaces TRPO's hard KL constraint with a clipped probability-ratio objective, enabling simple SGD-based updates.
  • The clipped surrogate objective removes the incentive for the policy to change too much on any single update.
  • Multiple epochs of minibatch SGD can be run on the same batch of trajectories, unlike vanilla policy gradient.
  • GAE supplies the advantage estimates; a value function baseline reduces variance without introducing bias.
  • PPO is a first-order, on-policy method: simple to implement, robust across hyperparameters, but not sample-efficient.
  • It underlies major real-world RL systems, including large-scale robotics and RLHF fine-tuning of language models.
The core insight

PPO clips the policy-update objective so gradients vanish once the new policy strays too far from the old one, approximating a trust region with plain first-order optimization.

The idea

Policy gradient methods optimize a parameterized policy πθ(a∣s)\pi_\theta(a\mid s) by ascending an estimate of the gradient of expected return. The classical REINFORCE-style estimator has high variance, and taking a step of fixed size in parameter space can produce an arbitrarily large change in policy space, since the mapping from parameters to the resulting distribution over trajectories is highly nonlinear. TRPO addresses this by optimizing a surrogate objective — the expected advantage under the new policy, reweighted by the importance-sampling ratio rt(θ)=πθ(at∣st)/πθold(at∣st)r_t(\theta) = \pi_\theta(a_t\mid s_t) / \pi_{\theta_{\text{old}}}(a_t\mid s_t) — subject to a constraint that the average KL divergence between old and new policy stays below a threshold δ\delta. PPO keeps the same surrogate objective but replaces the explicit KL constraint with a clipped objective:

LCLIP(θ)=Et[min⁡(rt(θ) A^t, clip(rt(θ), 1−ϵ, 1+ϵ) A^t)]L^{\text{CLIP}}(\theta) = \mathbb{E}_t\Big[\min\big(r_t(\theta)\,\hat{A}_t,\ \text{clip}(r_t(\theta),\,1-\epsilon,\,1+\epsilon)\,\hat{A}_t\big)\Big]

Here A^t\hat{A}_t is an advantage estimate (typically computed with GAE), and ϵ\epsilon is a small hyperparameter (commonly 0.10.1–0.30.3). The clip function truncates the ratio rt(θ)r_t(\theta) to the interval [1−ϵ,1+ϵ][1-\epsilon, 1+\epsilon]. Taking the minimum of the clipped and unclipped terms produces a pessimistic lower bound: when the advantage is positive, the objective flattens out once rtr_t exceeds 1+ϵ1+\epsilon, removing the incentive to keep increasing the probability of that action indefinitely. When the advantage is negative, symmetric clipping prevents the ratio from collapsing below 1−ϵ1-\epsilon. The result is an objective that behaves like the unclipped surrogate near rt=1r_t = 1 (small policy changes are essentially the same as in vanilla policy gradient) but flattens once the policy has moved "far enough," discouraging further movement in that direction. Because this is achieved purely by reshaping the loss function, it requires no second-order information, no KL penalty coefficient tuning (in the clipped variant), and no constrained optimization solver — only ordinary minibatch stochastic gradient ascent, repeated for several epochs over each batch of collected trajectories.

How it works

PPO is an on-policy actor-critic algorithm. It alternates between two phases: (1) collecting a batch of trajectories using the current policy, and (2) performing several epochs of minibatch gradient updates on that fixed batch using the clipped objective plus auxiliary terms for the value function and entropy.

Step 1 — Rollout. Run the current policy πθold\pi_{\theta_{\text{old}}} in the environment for TT timesteps (across possibly many parallel actors), recording states, actions, rewards, and the log-probabilities log⁡πθold(at∣st)\log \pi_{\theta_{\text{old}}}(a_t\mid s_t).

Step 2 — Advantage estimation. Using the critic Vϕ(s)V_\phi(s), compute TD residuals δt=rt+γVϕ(st+1)−Vϕ(st)\delta_t = r_t + \gamma V_\phi(s_{t+1}) - V_\phi(s_t), then compute GAE advantages

A^t=∑l=0T−t−1(γλ)l δt+l\hat{A}_t = \sum_{l=0}^{T-t-1} (\gamma\lambda)^l \, \delta_{t+l}

and return targets R^t=A^t+Vϕ(st)\hat{R}_t = \hat{A}_t + V_\phi(s_t) for the value regression loss.

Step 3 — Multi-epoch minibatch update. For KK epochs, shuffle the batch into minibatches and, for each minibatch, compute the combined loss

L(θ,ϕ)=LCLIP(θ)−c1 LVF(ϕ)+c2 S[πθ](s)L(\theta,\phi) = L^{\text{CLIP}}(\theta) - c_1 \, L^{VF}(\phi) + c_2 \, S[\pi_\theta](s)

where LVF(ϕ)=(Vϕ(st)−R^t)2L^{VF}(\phi) = (V_\phi(s_t) - \hat{R}_t)^2 is the value function loss and SS is the policy entropy bonus (lightly foreshadowing Entropy Regularization, which encourages continued exploration). Take a gradient ascent step on LL using Adam or a similar first-order optimizer.

Step 4 — Repeat. Discard the batch, set θold←θ\theta_{\text{old}} \leftarrow \theta, and collect a fresh batch with the updated policy. ``` Algorithm: Proximal Policy Optimization (PPO-Clip) Input: initial policy parameters θ, value parameters φ, clip range ε, discount γ, GAE parameter λ, epochs K, minibatch size M, learning rate η for iteration = 1, 2, ... do

# --- Step 1: Rollout with current policy --- θ_old ← θ collect trajectories {(s_t, a_t, r_t, logπ_old(a_t|s_t))} by running π_θ_old in the environment for T steps (across N parallel actors if available)

# --- Step 2: Compute advantages and returns via GAE --- for each trajectory, t = T-1 down to 0: δ_t ← r_t + γ V_φ(s_{t+1}) - V_φ(s_t) # δ_T = r_T - V_φ(s_T) at episode end A_t ← δ_t + γ λ * A_{t+1} # A_T = δ_T R_t ← A_t + V_φ(s_t) # value regression target normalize advantages: A_t ← (A_t - mean(A)) / (std(A) + 1e-8)

# --- Step 3: K epochs of minibatch SGD on the fixed batch --- for epoch = 1 .. K do shuffle all timesteps, partition into minibatches of size M for each minibatch B do for t in B: r_t(θ) ← exp( logπ_θ(a_t|s_t) - logπ_old(a_t|s_t) ) unclipped ← r_t(θ) A_t clipped ← clip(r_t(θ), 1-ε, 1+ε) A_t L_clip_t ← min(unclipped, clipped) L_clip ← mean_t( L_clip_t ) L_vf ← mean_t( (V_φ(s_t) - R_t)^2 ) L_ent ← mean_t( entropy(π_θ(·|s_t)) ) L ← L_clip - c1 L_vf + c2 L_ent (θ, φ) ← (θ, φ) + η * ∇_{θ,φ} L # ascent on L_clip, L_ent;

# descent on L_vf via the minus sign end for end for end for ``` Two implementation details matter for correctness. First, the ratio rt(θ)r_t(\theta) must be computed with the same actions that were sampled during rollout — it is an importance-sampling ratio, not a re-sampling of new actions. Second, advantages should be computed once per rollout (using θold\theta_{\text{old}}'s value function) and held fixed across all KK epochs; only the policy and value parameters are updated, not the advantage targets themselves, since those were already used to fix the training batch.

Figure
PPO training loop: rollout, GAE, and clipped multi-epoch update
1. Rollout π_θold in env (s,a,r,logπ_old) 2. GAE δ_t = r+γV(s')-V(s) Â_t, R̂_t (fixed for batch) 3. Fixed Batch {s_t,a_t,Â_t,R̂_t, logπ_old(a_t|s_t)} K epochs × minibatch SGD r_t(θ)= exp(logπ_θ-logπ_old) min(r·Â, clip(r,1±ε)·Â) L_CLIP - c1·L_VF + c2 · entropy bonus S[π_θ] θ,φ ← θ,φ + η∇L next iteration: θ_old ← θ, discard batch

Complexity & correctness

Time complexity per iteration. Rollout costs O(T⋅N)O(T \cdot N) environment steps across NN parallel actors, each involving one forward pass through the policy and value networks — call this O(TN⋅Cnet)O(TN \cdot C_{\text{net}}) where CnetC_{\text{net}} is the per-step network cost. GAE computation is a single backward pass over the trajectory, O(TN)O(TN). The update phase runs KK epochs over a batch of size TNTN split into minibatches of size MM, each requiring one forward-backward pass, giving O ⁣(K⋅TNM⋅Cnet⋅M)=O(K⋅TN⋅Cnet)O\!\big(K \cdot \frac{TN}{M} \cdot C_{\text{net}} \cdot M\big) = O(K \cdot TN \cdot C_{\text{net}}). Since KK is a small constant (typically 3–10), total per-iteration cost is linear in the number of collected environment steps, O(TN)O(TN) up to network cost, with no polynomial blow-up from any linear-system solve — this is precisely the computational advantage over TRPO, which additionally requires O(CG iterations×Hessian-vector products)O(\text{CG iterations} \times \text{Hessian-vector products}) per update, each Hessian-vector product itself costing O(TN⋅Cnet)O(TN \cdot C_{\text{net}}).

Space complexity. The batch of TNTN transitions (states, actions, rewards, log-probabilities, advantages, returns) must be held in memory simultaneously, giving O(TN⋅d)O(TN \cdot d) where dd is the dimensionality of a state/action pair — the same as any batch-based policy gradient method, and substantially less than replay-buffer-based off-policy methods, which store data across many iterations.

Why clipping approximates a trust region. TRPO's guarantee rests on the surrogate objective inequality: for the true objective J(θ)J(\theta) and surrogate Lθold(θ)=E[rt(θ)A^t]L_{\theta_{\text{old}}}(\theta) = \mathbb{E}[r_t(\theta)\hat{A}_t],

J(θ)≥Lθold(θ)−C⋅DKLmax⁡(θold,θ)J(\theta) \geq L_{\theta_{\text{old}}}(\theta) - C \cdot D_{KL}^{\max}(\theta_{\text{old}}, \theta)

for a constant CC depending on the reward range and discount. Maximizing LL subject to a KL bound provably yields monotonic improvement. PPO's clipped objective is a heuristic that mimics this bound's qualitative behavior without computing KL directly: consider a single timestep with advantage A^t>0\hat{A}_t > 0. The unclipped term rtA^tr_t \hat{A}_t increases without bound as rtr_t grows, but the clipped term saturates at (1+ϵ)A^t(1+\epsilon)\hat{A}_t. Taking the minimum means that once rt>1+ϵr_t > 1+\epsilon, the gradient of LCLIPL^{\text{CLIP}} with respect to θ\theta in that term is exactly zero — increasing the action's probability further yields no objective gain, so SGD has no incentive to push rtr_t higher. Symmetric reasoning holds for A^t<0\hat{A}_t < 0: the objective flattens once rt<1−ϵr_t < 1-\epsilon, discouraging the policy from decreasing that action's probability further. The min (rather than clipping alone) ensures the bound is a pessimistic (lower) estimate of the true unclipped objective whenever the ratio moves in the "wrong" direction relative to clipping, which is important because it means the algorithm never rewards moving outside the trust region even transiently within an epoch of optimization.

Honest tradeoffs. This is a heuristic, not a proof: PPO carries no formal monotonic-improvement guarantee analogous to TRPO's, since the clipping bound is local (per-timestep, per-action) rather than a global KL bound on the joint action distribution over an entire trajectory. In practice this means PPO can still occasionally take destructive steps, especially with large minibatches reused for many epochs (the ratio rtr_t for some (s,a) pairs can end up far outside [1−ϵ,1+ϵ][1-\epsilon,1+\epsilon] by the final epoch, since the clip only zeroes the gradient, not the ratio itself, and epoch k+1k{+}1 starts from parameters already shifted by epoch kk). PPO also remains strictly on-policy: each collected batch is used for only a handful of gradient epochs before being discarded, making it considerably less sample-efficient than off-policy alternatives, a cost paid deliberately in exchange for implementation simplicity and stability.

Worked example

Consider a single timestep with clip range ϵ=0.2\epsilon = 0.2, advantage estimates from GAE, and three different scenarios for how far the new policy's action probability has moved from the old one. We compute the clipped surrogate term LtCLIP=min⁡(rtA^t, clip(rt,0.8,1.2)A^t)L^{\text{CLIP}}_t = \min(r_t \hat A_t,\ \text{clip}(r_t, 0.8, 1.2)\hat A_t) in each case.

Caseπθold(a∣s)\pi_{\theta_{\text{old}}}(a|s)πθ(a∣s)\pi_\theta(a|s)rt=πθ/πoldr_t = \pi_\theta/\pi_{\text{old}}A^t\hat{A}_tUnclipped rtA^tr_t\hat A_tClipped ratioClipped termLtCLIP=min⁡(⋅,⋅)L^{\text{CLIP}}_t=\min(\cdot,\cdot)Gradient w.r.t. rtr_t
A: small, good move0.300.331.10+2.02.201.10 (no clip)2.202.20nonzero (normal PG)
B: large, good move0.300.451.50+2.03.001.202.402.40zero (flattened)
C: large, bad move0.300.120.40−1.5−0.600.80−1.20−1.20zero (flattened)
D: small, bad move0.300.270.90−1.5−1.350.90 (no clip)−1.35−1.35nonzero (normal PG)

Walk through Case B in detail. The advantage is strongly positive (A^t=2.0\hat A_t = 2.0), meaning action aa was much better than average at state ss; an unconstrained policy gradient step would push πθ(a∣s)\pi_\theta(a|s) up aggressively. The ratio has already grown to rt=1.5r_t = 1.5, well past 1+ϵ=1.21+\epsilon = 1.2. The unclipped surrogate value is 3.003.00, but the clipped surrogate caps at (1+ϵ)A^t=1.2×2.0=2.40(1+\epsilon)\hat A_t = 1.2 \times 2.0 = 2.40. Since PPO takes the minimum, the effective objective is 2.402.40, and — critically — because this minimum is achieved by the constant clipped branch on this data point, its derivative with respect to θ\theta (through rtr_t) is zero: this timestep contributes no gradient signal in this minibatch, exactly as intended, because the policy has already moved far enough in the profitable direction for this action. Case C shows the symmetric protection: the advantage is negative, so the policy gradient wants to decrease πθ(a∣s)\pi_\theta(a|s), and it already has, aggressively (rt=0.40≪0.8r_t = 0.40 \ll 0.8). The clipped branch, clip(rt,0.8,1.2)A^t=0.8×(−1.5)=−1.2\text{clip}(r_t,0.8,1.2)\hat A_t = 0.8 \times (-1.5) = -1.2, is larger than the unclipped value −0.60×-0.60 \times wait — recompute: unclipped is rtA^t=0.40×(−1.5)=−0.60r_t \hat A_t = 0.40 \times (-1.5) = -0.60, clipped is 0.8×(−1.5)=−1.200.8 \times (-1.5) = -1.20. The min of {−0.60,−1.20}\{-0.60, -1.20\} is −1.20-1.20, so again the clipped (flattened) branch is selected, and gradient flow stops — the policy is not punished further for having already decreased this action's probability substantially. Cases A and D show the "normal" regime: rtr_t stays inside [0.8,1.2][0.8, 1.2], so the unclipped and clipped branches coincide, the min equals the ordinary surrogate value, and gradients flow exactly as in unclipped policy gradient — this is the region where PPO behaves identically to a plain surrogate objective, only intervening once the ratio threatens to leave the trust region.

Common pitfalls & traps

PitfallWhy it happensConsequence
Recomputing advantages every epoch instead of once per batchConflating advantage estimation with policy updateAdvantages drift with θ\theta mid-batch, invalidating the fixed-batch importance-sampling assumption
Forgetting to detach/stop-gradient the old log-probabilitiesTreating log⁡πθold\log\pi_{\theta_{\text{old}}} as a function of current parametersRatio rtr_t gradient becomes wrong; effectively double-differentiates through the wrong variable
Using too large a clip range ϵ\epsilon or too many epochs KKAssuming clipping alone guarantees safety regardless of reuseRatios can drift far outside [1−ϵ,1+ϵ][1-\epsilon,1+\epsilon] across successive epochs, degrading the policy despite clipping
Not normalizing advantages per minibatchIgnoring scale sensitivity of the surrogate objectiveLearning rate becomes reward-scale dependent; training destabilizes on high-variance reward signals
Sharing actor-critic weights without balancing loss coefficients c1,c2c_1, c_2Treating policy and value losses as independentValue loss gradients dominate or starve policy gradients through the shared trunk

Pioneers & history

Origins · 1 minJohn Schulman and how this was discovered
JS
John Schulman
1990s–present · UC Berkeley (Pieter Abbeel's lab), later OpenAI

Schulman developed both Trust Region Policy Optimization and Proximal Policy Optimization, driven by a search for policy gradient methods that could reliably train neural network policies on high-dimensional continuous-control and robotics tasks without the instability that plagued earlier actor-critic approaches. PPO was explicitly designed to retain TRPO's stability benefits while discarding its implementation complexity, becoming OpenAI's default RL algorithm for years, used in Dota 2 agents, robotic manipulation, and later reinforcement learning from human feedback for large language models.

History
2015
Schulman, Levine, Moritz, Jordan, and Abbeel introduce Trust Region Policy Optimization (TRPO), establishing the monotonic-improvement surrogate bound.
2015
Generalized Advantage Estimation (Schulman et al.) provides a low-variance, tunable-bias advantage estimator built for actor-critic policy gradients.
2017
Schulman, Wolski, Dhariwal, Radford, and Klimov publish "Proximal Policy Optimization Algorithms," introducing the clipped surrogate objective.
2017–2019
PPO becomes the default policy optimizer at OpenAI, used in Dota 2 (OpenAI Five) and robotic hand manipulation (Dactyl).
2022
onward: PPO becomes the standard optimizer in reinforcement learning from human feedback (RLHF) pipelines for aligning large language models.

Where this matters

PPO's combination of stability and implementation simplicity has made it the default choice across a wide range of production and research RL systems. OpenAI Five used a large-scale distributed variant of PPO to train agents that defeated professional Dota 2 teams, relying on PPO's robustness to scale across thousands of parallel actors. OpenAI's Dactyl used PPO to train a robotic hand for in-hand manipulation transferred from simulation to the real world, where training instability would be catastrophic given the cost of physical rollouts. In reinforcement learning from human feedback (RLHF), the dominant paradigm for aligning large language models such as instruction-tuned chatbots, PPO fine-tunes a language model policy against a learned reward model, with the clipped objective preventing the policy from drifting so far from its pretrained initialization that fluent, coherent text degenerates. Physics-based character animation, continuous-control benchmarks (MuJoCo, Isaac Gym), and general-purpose RL libraries (Stable-Baselines3, RLlib, CleanRL) all ship PPO as a default baseline, precisely because it tends to work reasonably well with minimal hyperparameter tuning across very different domains — a property few other deep RL algorithms share as consistently.

Ask the tutor: How does changing the clip parameter ε or the number of epochs K affect the empirical KL divergence between successive PPO policies?

Why does PPO use a "min" of the clipped and unclipped objective instead of just clipping the ratio directly?

Clipping the ratio directly and using it uniformly would mean the objective still increases when moving further in the wrong direction relative to the desired trust region, because the clipped value might exceed the unclipped one and mask a bad update. Taking the minimum ensures the surrogate is always a pessimistic (lower) bound on the true unclipped surrogate. Concretely, when the advantage is positive and the ratio has already exceeded 1+ε, the min guarantees the objective cannot be increased further by continuing to push probability up, since the flat clipped branch is selected. Without the min, gradients could occasionally reward moving even further outside the trusted range, undermining the entire point of clipping.

How does GAE fit into the PPO training loop?

Generalized Advantage Estimation supplies the A^t\hat A_t values that appear inside the clipped surrogate objective. PPO itself is agnostic to how advantages are computed, but GAE is used almost universally because it offers a tunable bias-variance tradeoff via the λ\lambda parameter, interpolating between low-variance, high-bias one-step TD advantages (λ=0\lambda=0) and high-variance, low-bias Monte Carlo advantages (λ=1\lambda=1). GAE is computed once per rollout using the old value function, held fixed throughout all epochs of the PPO update, and used both to weight the clipped policy objective and to form the regression target for the value function loss.

What is a typical value for the clip parameter ε, and how sensitive is PPO to it?

The original PPO paper uses ϵ=0.2\epsilon = 0.2 across most benchmarks, and this remains the most common default. Values in the range 0.1–0.3 are typical; smaller values enforce more conservative updates (closer to a tighter trust region) at the cost of slower learning, while larger values allow faster but riskier policy changes. PPO is generally considered more robust to this hyperparameter than TRPO is to its KL threshold, but ε still interacts with the number of epochs KK and minibatch size — aggressive epoch counts with a loose clip can still produce large net policy shifts, so the two should be tuned jointly rather than independently.

Is PPO on-policy or off-policy, and what does that imply for sample efficiency?

PPO is on-policy: it uses only data collected under the current (or very recently updated) policy, discarding the batch after a handful of gradient epochs. This contrasts with off-policy methods like DDPG, SAC, or Q-learning variants that reuse data from a replay buffer spanning many past policies. The tradeoff is that PPO typically needs more total environment interactions to reach a given performance level than sample-efficient off-policy methods, but in exchange gains substantially simpler, more stable training dynamics — an important reason PPO dominates settings like robotics simulation and RLHF where implementation robustness matters more than sample count.

How does PPO relate to TRPO in terms of the trust-region guarantee?

TRPO enforces a hard constraint that the average KL divergence between the old and new policy stays below a threshold, solved via a constrained optimization procedure (conjugate gradient plus line search) that comes with a theoretical monotonic-improvement guarantee under certain approximations. PPO drops the explicit constraint entirely, replacing it with a clipped objective that removes the gradient incentive for large ratio deviations. This achieves similar qualitative behavior — small, safe updates — using ordinary SGD, but sacrifices the formal guarantee: PPO can occasionally still take a step that increases the true KL divergence more than intended, since the per-timestep clip does not bound the aggregate trajectory-level KL directly.

Why does PPO use multiple parallel actors for rollout collection?

Parallel actors reduce the variance and improve the diversity of the collected batch, since a single actor's trajectory is highly correlated across time (states within one episode are sequentially dependent). Running NN independent actors — each potentially in a different environment instance or starting state — produces a batch that better approximates the true state-action distribution under the current policy, which matters because the clipped objective and value function updates both depend on this batch being a reasonably faithful, low-variance sample. Parallelism also directly reduces wall-clock training time, which is why most PPO implementations couple it with vectorized or distributed environment simulation.

What role does the entropy bonus play, and how does it connect to later ideas?

The entropy term c2⋅S[πθ]c_2 \cdot S[\pi_\theta] added to the PPO objective rewards the policy for maintaining a higher-entropy (more stochastic) action distribution, counteracting the tendency of policy gradient methods to collapse prematurely into deterministic behavior before adequately exploring the state-action space. This is a lightweight, first-order stand-in for more principled exploration bonuses and connects directly to the broader technique of Entropy Regularization, which formalizes entropy maximization as part of the optimization objective itself, most fully realized in maximum-entropy RL frameworks such as Soft Actor-Critic.

Before this

Where this leads