Reinforcement Learning2015advanced12 min read

Trust Region Policy Optimization

أمثَلة السياسة بمنطقة الثقة

Schulman, J. · Levine, S. · Moritz, P. · Jordan, M. I. · Abbeel, P. — ICML

The problem

Vanilla methods update the policy by stepping in the direction of the gradient of expected . But the step size is a minefield: too small and learning crawls; too large and the policy collapses catastrophically. Worse, a collapsed policy collects bad data, which produces bad gradients, which collapse the policy further — a death spiral with no recovery. By 2015, this instability was the main barrier to applying policy gradients to complex continuous-control tasks.

The contribution

TRPO introduces a theoretically-grounded iterative procedure that guarantees monotonic policy improvement. At each step it maximizes a — the expected under the new policy, weighted by ratios — subject to a constraint that keeps the new policy close to the old one. The constraint is enforced via conjugate gradient with Fisher-vector products and a . The result is a practical algorithm that trains neural-network policies on continuous-control tasks and Atari games with stable, monotonic progress and minimal hyperparameter tuning.

The impact

TRPO established the trust-region paradigm that dominates modern policy optimization. It directly inspired PPO — which simplified the constraint to a clipped objective and became the workhorse behind RLHF, ChatGPT, and Claude — as well as GAE for reduction and visuomotor policies for robotic learning from pixels. Every modern on-policy RL algorithm traces its stability guarantees back to TRPO's theoretical foundation.

Imagine you're hiking along a narrow mountain ridge in thick fog. Vanilla policy gradient is walking with long strides — one wrong step and you tumble off the cliff, and there's no climbing back.

TRPO gives you a safety rope anchored at your current position. You can explore freely within the rope's radius — your — knowing that if anything goes wrong, the rope catches you. Each time you find better footing, you re-anchor the rope there and explore again.

The fog never lifts, but with each safe step you guarantee you're no lower than before. That guarantee is what makes the difference between steady progress and catastrophe.

The problem: one bad step and the policy never recovers

In policy gradient methods, we parameterize a policy πθ\pi_\theta and update parameters θ\theta to maximize expected cumulative reward. The update rule looks simple: θ←θ+α∇θJ(θ)\theta \leftarrow \theta + \alpha \nabla_\theta J(\theta). But underneath that simplicity lies a dangerous asymmetry.

A slightly-too-large step can push the policy into a region where it takes terrible actions. Terrible actions produce terrible trajectories. Terrible trajectories produce misleading gradients. Misleading gradients push the policy even further into bad territory. This vicious cycle — the performance collapse spiral — is the central failure mode of vanilla policy gradients.

The core issue is that parameter space doesn't reflect policy space. A tiny change in θ\theta might barely change the policy, or it might completely flip which actions get chosen. Standard has no way to tell the difference — it only sees parameter distance, not behavioral distance.

Open in Lab
Drag the step-size slider. Small steps make slow progress; one step too large triggers a collapse spiral from which vanilla PG cannot recover. TRPO stays safe.
The demo wakes as you arrive…

The theoretical foundation: guaranteed improvement

TRPO's key insight starts with the performance difference lemma (Kakade & Langford, 2002): the difference in total reward between any two policies π′\pi' and π\pi can be written exactly as the expected advantage of π′\pi' over π\pi, evaluated under π′\pi''s own state distribution:

This identity is exact but circular — computing dπ′d^{\pi'} requires running the new policy π′\pi', which is what we're trying to design. Schulman et al. break the circularity by constructing a surrogate objective Lπ(π′)L_\pi(\pi') that uses the old policy's state distribution instead. They then prove a lower bound: the true improvement J(π′)−J(π)J(\pi') - J(\pi) is at least Lπ(π′)−C⋅DKLmax(π,π′)L_\pi(\pi') - C \cdot D_{KL}^{max}(\pi, \pi'), where CC is a penalty constant and DKLmaxD_{KL}^{max} is the maximum KL divergence across states.

In words: if the surrogate goes up and the policies stay close in KL divergence, the true performance is guaranteed to go up too. This transforms a hard RL problem into a tractable optimization with constraints.

J(π′)−J(π)=Eτ∼π′ ⁣[∑t=0∞γt Aπ(st,at)]J(\pi') - J(\pi) = \mathbb{E}_{\tau \sim \pi'}\!\left[\sum_{t=0}^{\infty} \gamma^t\, A_\pi(s_t, a_t)\right]
Performance difference lemma — The exact improvement of π' over π equals the expected discounted advantage of actions taken by π', evaluated using π's value function. Every future state matters.

The surrogate objective: optimizing what we can compute

Since we can't sample from the new policy's state distribution (we haven't deployed it yet), TRPO replaces it with the old policy's distribution. The surrogate objective uses importance sampling to re-weight actions:

Think of it as asking: "If I replay the trajectories I already collected but pretend the new policy chose those actions, how much better would the advantage be?" The probability ratio πθ(a∣s)πθold(a∣s)\frac{\pi_\theta(a|s)}{\pi_{\theta_{old}}(a|s)} corrects for the fact that the new policy would choose actions with different probabilities.

Lθold(θ)=Es∼dπold,  a∼πold ⁣[πθ(a∣s)πθold(a∣s) Aθold(s,a)]L_{\theta_{old}}(\theta) = \mathbb{E}_{s \sim d^{\pi_{old}},\; a \sim \pi_{old}} \!\left[\frac{\pi_\theta(a|s)}{\pi_{\theta_{old}}(a|s)}\, A_{\theta_{old}}(s,a)\right]
Surrogate objective function — The ratio π_θ / π_old re-weights each sampled action. When the new policy makes a good action more likely (ratio > 1), the surrogate increases. States are sampled from the old policy — no new rollouts needed.

But this surrogate alone is dangerous. Without a constraint, the optimizer would push the probability ratios to extreme values — making the new policy wildly different from the old one. The importance sampling correction becomes unreliable, and the surrogate stops predicting true performance. This is exactly the performance-collapse problem dressed in new math.

TRPO's solution: constrain the KL divergence between old and new policies to stay within a small trust region.

max⁡θ  Lθold(θ)s.t.DˉKL(θold,θ)≤δ\max_\theta \; L_{\theta_{old}}(\theta) \quad \text{s.t.} \quad \bar{D}_{KL}(\theta_{old}, \theta) \le \delta
The TRPO optimization problem — Maximize the surrogate objective subject to a KL budget δ (typically 0.01). The bar over D_KL means "averaged over states." This replaces the hard-to-tune step size α with a semantically meaningful constraint on policy change.
Open in Lab
The ellipse is the trust region (KL ≤ δ). Drag δ to see how enlarging the trust region lets the optimizer reach a better surrogate value — but risks overshooting.
The demo wakes as you arrive…

Solving the constrained problem: natural gradient meets conjugate gradient

The TRPO optimization problem is a constrained optimization over thousands or millions of policy parameters. How do we actually solve it?

Step 1: Approximate the KL constraint. Near the current parameters, the KL divergence is well-approximated by a quadratic form using the matrix FF: DˉKL(θold,θ)≈12(θ−θold)TF(θ−θold)\bar{D}_{KL}(\theta_{old}, \theta) \approx \frac{1}{2} (\theta - \theta_{old})^T F (\theta - \theta_{old}). This turns the trust region from an abstract probability-distribution constraint into a concrete ellipsoid in parameter space.

Step 2: Solve for the update direction. With a linear approximation to the objective and the quadratic KL approximation, the optimal update direction is F−1gF^{-1} g, where gg is the policy gradient — this is exactly the . It accounts for the geometry of the policy distribution, stepping more cautiously in directions where the policy is sensitive and more boldly where it's robust.

Step 3: Use conjugate gradient. Computing F−1gF^{-1} g directly requires inverting a matrix with millions of entries — impractical. Instead, TRPO uses the conjugate gradient algorithm to solve Fx=gF x = g iteratively, needing only matrix-vector products FvF v which are computed cheaply via automatic differentiation.

Step 4: Backtracking line search. The quadratic approximation to KL is only accurate locally, so TRPO performs a line search: it tries the full natural-gradient step, checks whether the KL constraint is truly satisfied and the surrogate actually improved, and if not, shrinks the step by a factor (typically 0.8) and tries again.

θnew=θold+2δgTF−1g  F−1g\theta_{new} = \theta_{old} + \sqrt{\frac{2\delta}{g^T F^{-1} g}}\; F^{-1} g
The TRPO update — a scaled natural gradient step — g = policy gradient · F⁻¹g = natural gradient direction · the √(2δ / gᵀF⁻¹g) factor scales the step to exactly fill the trust region. In practice, F⁻¹g is found by conjugate gradient and the step is refined by line search.
Open in Lab
The vanilla gradient (blue) ignores policy geometry and overshoots. The natural gradient (green) follows the KL contours, taking a safe step within the trust region.
The demo wakes as you arrive…

The TRPO algorithm step by step

The full TRPO update cycle brings together all the pieces. At each iteration the algorithm collects trajectories, estimates advantages, solves a constrained optimization, and updates the policy — with a guarantee that performance never degrades.

Open in Lab
Click through each stage of one TRPO iteration to see the algorithm in action.
The demo wakes as you arrive…
TRPO update: the essential looppython

Simplified to show the idea — not the real implementation.

import numpy as np

def conjugate_gradient(Fvp, g, n_iters=10):
    """Solve Fx = g without forming F, using only F-vector products."""
    x = np.zeros_like(g)
    r = g.copy()           # residual
    p = g.copy()           # search direction
    for _ in range(n_iters):
        Fp = Fvp(p)        # Fisher-vector product via autodiff
        alpha = (r @ r) / (p @ Fp + 1e-8)
        x += alpha * p
        r_new = r - alpha * Fp
        beta = (r_new @ r_new) / (r @ r + 1e-8)
        p = r_new + beta * p
        r = r_new
    return x               # ≈ F⁻¹g (the natural gradient)

def trpo_update(policy, trajectories, delta=0.01):
    """One TRPO iteration — surrogate + KL constraint."""
    # 1. Estimate advantages from collected trajectories
    advantages = estimate_advantages(trajectories)

    # 2. Compute policy gradient g = ∇ L(θ)
    g = compute_policy_gradient(policy, trajectories, advantages)

    # 3. Natural gradient direction via conjugate gradient
    Fvp = lambda v: fisher_vector_product(policy, trajectories, v)
    nat_grad = conjugate_gradient(Fvp, g)

    # 4. Scale step to fill trust region: √(2δ / gᵀ F⁻¹g)
    step_size = np.sqrt(2 * delta / (g @ nat_grad + 1e-8))
    full_step = step_size * nat_grad

    # 5. Backtracking line search
    for j in range(10):
        trial = policy.params + (0.8 ** j) * full_step
        if kl_divergence(policy.params, trial) <= delta \
           and surrogate(trial) >= surrogate(policy.params):
            policy.params = trial
            break  # found a safe, improving step

Why measure distance with KL divergence, not Euclidean distance?

Standard gradient descent constrains the step in parameter space: ∥θnew−θold∥2≤ϵ\|\theta_{new} - \theta_{old}\|_2 \le \epsilon. But parameter distance is a poor proxy for behavioral distance. Consider a softmax policy over two actions with logits [0,0][0, 0]: changing them to [0.01,0.01][0.01, 0.01] barely changes anything, but changing to [0,100][0, 100] makes the policy deterministic — both might have the same L2L_2 distance from [0,0][0, 0].

KL divergence measures change in the distribution of actions, which is what actually matters. A step of size δ\delta in KL space guarantees that the probability of every action changes by at most a bounded amount. The Fisher information matrix, which defines the KL geometry locally, automatically scales: it makes the step conservative in high-sensitivity directions and permissive in low-sensitivity ones.

Open in Lab
Same L₂ distance in parameter space, wildly different policy change. KL divergence captures the true behavioral gap.
The demo wakes as you arrive…

Sampling: single path vs vine

TRPO describes two sampling schemes for estimating the surrogate objective:

Single path — the simpler approach. Run the current policy to collect full trajectories, then use all state-action pairs to estimate the objective and constraint. This is what most implementations use, and what you'd choose for environments that are expensive to reset.

Vine — a more sample-efficient scheme for cheap-to-reset environments. From each sampled state, branch out with multiple rollouts using different actions. This gives lower-variance estimates because you compare actions from the same state, reducing the confounding effect of different state visitation.

Experiments: from simulated robots to Atari

Schulman et al. tested TRPO on two challenging domains:

Continuous control (MuJoCo). Simulated robots learning to swim, hop, and walk. TRPO consistently outperformed vanilla policy gradients and the cross-entropy method, learning stable gaits with monotonic reward improvement. The key result: performance never collapsed during , even with minimal hyperparameter tuning.

Atari games. TRPO also learned to play Atari games directly from pixel inputs, using a as the policy. While not matching DQN's peak scores on all games, TRPO demonstrated that a single on-policy algorithm could handle both continuous and discrete action spaces — a significant generality advantage.

Legacy: from TRPO to PPO and beyond

TRPO's theoretical elegance came at a computational cost: the conjugate gradient solve and line search make each update significantly more expensive than a standard gradient step. This motivated Schulman's follow-up work, Proximal Policy Optimization (PPO), which approximates TRPO's trust-region constraint with a simple clipped surrogate objective that can be optimized with first-order methods.

PPO became the dominant RL algorithm in practice — powering RLHF for ChatGPT, Claude, and other language models — but its success is built entirely on TRPO's conceptual framework. TRPO also directly inspired Generalized Advantage Estimation (GAE), which provides variance-reduced advantage estimates that are now standard in all policy-gradient methods.

  1. 2002

    Kakade & Langford

    Prove the performance difference lemma and introduce conservative policy iteration, showing that policies can be improved with bounded performance loss.

  2. 2015

    TRPO (Schulman et al.)

    Trust Region Policy Optimization turns the theoretical bound into a practical neural-network algorithm using surrogate objectives, KL constraints, conjugate gradient, and line search.

  3. 2016

    GAE (Schulman et al.)

    Generalized Advantage Estimation provides a smooth bias-variance tradeoff for advantage estimation, dramatically improving TRPO's sample efficiency.

  4. 2017

    PPO (Schulman et al.)

    Proximal Policy Optimization simplifies TRPO's trust region to a clipped objective, enabling first-order optimization while retaining the core stability guarantee.

  5. 2022

    RLHF powers ChatGPT

    PPO — TRPO's direct descendant — becomes the optimization engine behind instruction-tuned language models, aligning AI with human preferences at scale.

TRPO's lasting contribution is not just an algorithm — it is the idea that policy optimization should be safe by construction. Every time a language model is fine-tuned with RLHF, the underlying machinery is enforcing trust regions in one form or another, ensuring that the model improves without forgetting how to be helpful.

CitationSchulman, Levine, Moritz, Jordan, Abbeel. Trust Region Policy Optimization. ICML, 2015.

Terms in this paper