Skip to content
AI360Xpert
Beta

Apprenticeship Learning via Inverse RL

Instead of trying to copy an expert's raw actions or guess their hidden reward function, an apprentice guarantees expert performance simply by matching the expert's long-term feature visitation frequencies.

Apprenticeship Learning iteratively projects learner feature expectations toward expert demonstrations to guarantee bounded return loss.
Apprenticeship Learning iteratively projects learner feature expectations toward expert demonstrations to guarantee bounded return loss.

Why Does This Exist?

When training autonomous systems from human demonstrations—such as robotic aerobatics, autonomous driving, or robotic surgery—two classical paradigms fail in distinct ways:

  1. Behavioral Cloning (Supervised Imitation): Direct supervised learning fits a policy π(a∣s)\pi(a \mid s) directly to state-action pairs (s,a)(s, a) demonstrated by an expert. However, compounding temporal errors cause covariate shift: a minor steering mistake at time step tt moves the vehicle into unfamiliar states never visited by the human driver. In these unvisited states, the policy makes larger errors, leading to quadratic error growth O(T2)\mathcal{O}(T^2) and catastrophic failure.
  2. Standard Inverse Reinforcement Learning (IRL): Classic IRL attempts to recover the unknown reward function R∗(s)R^*(s) that made the expert's trajectory optimal. But recovering the true reward is fundamentally ill-posed and underdetermined: an infinite family of reward functions (including degenerate constants like R(s)=0R(s) = 0) can make any demonstrated policy optimal.

Pieter Abbeel and Andrew Ng (2004) resolved this impasse with Apprenticeship Learning via Inverse Reinforcement Learning. They asked a foundational question: Do we actually need to uncover the expert's true reward function R∗(s)R^*(s) to match their performance?

Their answer was no. Under the mild assumption that rewards are linear combinations of known state features R(s)=w⊤ϕ(s)R(s) = w^\top \phi(s), an agent does not need to identify the true weight vector w∗w^*. Instead, if the apprentice can find a policy that matches the expert's long-term discounted feature expectations within a tolerance ϵ\epsilon, the Cauchy-Schwarz inequality guarantees that the apprentice's performance will be within ϵ\epsilon of the expert's performance across any possible underlying reward weight vector.

Think of It Like This

The Master Sculptor and the Apprentice

Imagine an apprentice stone sculptor studying in the workshop of a Renaissance master artisan.

If the apprentice relies on behavioral cloning, they try to mimic the master's exact hammer strikes—the precise angle, speed, and timing of each strike. The moment the chisel strikes a hidden marble fissure or slips slightly, the apprentice enters an unfamiliar state. Because they do not understand the broader aesthetic objective, they cannot recover, and they shatter the statue.

Under apprenticeship learning, the apprentice does not mimic hammer blows blow-for-blow. Instead, they inspect the high-level geometric properties (ϕ(s)\phi(s)) of the master's completed statues: the ratio of head height to body height, the smoothness of curved planes, the depth of shadow under the brow, and the polish of the surface.

Even though the master may have used idiosyncratic hand motions, the apprentice focuses on producing a statue whose geometric proportions and surface contours (discounted feature expectations μE\mu_E) match those of the master's portfolio.

Because any classical art critic evaluates a sculpture as a weighted combination (ww) of these exact geometric proportions, matching the master's feature profile guarantees that critics will judge the apprentice's work to be indistinguishable from the master's masterpiece—even though the apprentice never knew the exact aesthetic weights w∗w^* in the master's mind.

The analogy stops when considering materials: in marble sculpting, physical mistakes cannot be erased, whereas in reinforcement learning, the apprentice can repeatedly execute forward rollouts in an MDP under candidate reward functions until its feature expectations converge.

How It Actually Works

The Feature Expectation Formulation and Performance Guarantee

Consider a Markov Decision Process without a predefined reward function, denoted MDP∖R=(S,A,P,γ,D)\text{MDP}\setminus R = (\mathcal{S}, \mathcal{A}, P, \gamma, D), where S\mathcal{S} is the state space, A\mathcal{A} is the action space, P(s′∣s,a)P(s' \mid s, a) represents transition dynamics, γ∈[0,1)\gamma \in [0, 1) is the discount factor, and DD is the initial state distribution.

We assume a known feature mapping ϕ:S→[0,1]k\phi: \mathcal{S} \to [0, 1]^k such that ∥ϕ(s)∥2≤1\|\phi(s)\|_2 \le 1. The true environmental reward is assumed to be linear in these features:

R(s)=w⊤ϕ(s)where∥w∥2≤1R(s) = w^\top \phi(s) \quad \text{where} \quad \|w\|_2 \le 1

For any policy π\pi, we define the discounted feature expectation vector μ(π)∈Rk\mu(\pi) \in \mathbb{R}^k as:

μ(π)=E[∑t=0∞γtϕ(st)  |  π]\mu(\pi) = \mathbb{E}\left[ \sum_{t=0}^\infty \gamma^t \phi(s_t) \;\middle|\; \pi \right]

Given an empirical demonstration dataset of mm expert trajectories DE={τ(1),…,τ(m)}\mathcal{D}_E = \{\tau^{(1)}, \dots, \tau^{(m)}\}, the expert's feature expectations are estimated empirically:

μ^E=1m∑i=1m∑t=0Tiγtϕ(st(i))\hat{\mu}_E = \frac{1}{m} \sum_{i=1}^m \sum_{t=0}^{T_i} \gamma^t \phi(s_t^{(i)})

The total expected discounted return of any policy π\pi under reward weights ww is a linear inner product:

J(π)=E[∑t=0∞γtR(st)]=E[∑t=0∞γtw⊤ϕ(st)]=w⊤μ(π)J(\pi) = \mathbb{E}\left[ \sum_{t=0}^\infty \gamma^t R(s_t) \right] = \mathbb{E}\left[ \sum_{t=0}^\infty \gamma^t w^\top \phi(s_t) \right] = w^\top \mu(\pi)

This formulation yields the Fundamental Apprenticeship Performance Guarantee:

∣J(π)−J(πE)∣=∣w⊤(μ(π)−μE)∣≤∥w∥2⋅∥μ(π)−μE∥2≤∥μ(π)−μE∥2\left| J(\pi) - J(\pi_E) \right| = \left| w^\top \left(\mu(\pi) - \mu_E\right) \right| \le \|w\|_2 \cdot \|\mu(\pi) - \mu_E\|_2 \le \|\mu(\pi) - \mu_E\|_2

If the learning agent discovers a policy π~\tilde{\pi} satisfying ∥μ(π~)−μE∥2≤ϵ\|\mu(\tilde{\pi}) - \mu_E\|_2 \le \epsilon, then for any true weight vector ww with ∥w∥2≤1\|w\|_2 \le 1, the return gap is strictly bounded:

∣J(π~)−J(πE)∣≤ϵ\left| J(\tilde{\pi}) - J(\pi_E) \right| \le \epsilon

The agent achieves near-optimal expert performance without ever identifying the true reward parameters w∗w^*.

The Projection Algorithm

To find a policy whose feature expectations match μE\mu_E, Abbeel and Ng introduced two iterative algorithms: the Max-Margin algorithm (which solves a support vector machine quadratic program) and the more computationally efficient Projection Algorithm.

The Projection Algorithm maintains the convex hull of feature expectations discovered by the learner's previous policies, conv(μ(0),μ(1),…,μ(i))\text{conv}(\mu^{(0)}, \mu^{(1)}, \dots, \mu^{(i)}), and iteratively projects μE\mu_E onto this hull:

  1. Initialization: Run an arbitrary initial policy π(0)\pi^{(0)} (e.g., uniform random) to compute feature expectation μ(0)\mu^{(0)}. Set μˉ(0)=μ(0)\bar{\mu}^{(0)} = \mu^{(0)}.
  2. Compute Separating Hyperplane: At iteration ii, compute the vector from the current convex hull projection μˉ(i−1)\bar{\mu}^{(i-1)} toward the expert: w(i)=μE−μˉ(i−1)w^{(i)} = \mu_E - \bar{\mu}^{(i-1)}
  3. Check Termination: Compute the margin t(i)=∥w(i)∥2t^{(i)} = \|w^{(i)}\|_2. If t(i)≤ϵt^{(i)} \le \epsilon, terminate.
  4. Forward RL Inner Loop: Normalize candidate weights w^(i)=w(i)/∥w(i)∥2\hat{w}^{(i)} = w^{(i)} / \|w^{(i)}\|_2. Train an RL agent to find the optimal policy π(i)\pi^{(i)} for reward function: R(i)(s)=(w^(i))⊤ϕ(s)R^{(i)}(s) = (\hat{w}^{(i)})^\top \phi(s)
  5. Evaluate New Features: Compute μ(i)=μ(π(i))\mu^{(i)} = \mu(\pi^{(i)}).
  6. Update Convex Projection: Project μE\mu_E onto the line segment connecting μˉ(i−1)\bar{\mu}^{(i-1)} and μ(i)\mu^{(i)}: μˉ(i)=μˉ(i−1)+β(μ(i)−μˉ(i−1))\bar{\mu}^{(i)} = \bar{\mu}^{(i-1)} + \beta \left(\mu^{(i)} - \bar{\mu}^{(i-1)}\right) where β\beta is computed via orthogonal projection and clipped to [0,1][0, 1]: β=clip((μ(i)−μˉ(i−1))⊤(μE−μˉ(i−1))∥μ(i)−μˉ(i−1)∥22,0,1)\beta = \text{clip}\left( \frac{(\mu^{(i)} - \bar{\mu}^{(i-1)})^\top (\mu_E - \bar{\mu}^{(i-1)})}{\|\mu^{(i)} - \bar{\mu}^{(i-1)}\|_2^2}, 0, 1 \right)
  7. Iterate: Repeat steps 2–6 until t≤ϵt \le \epsilon.

Abbeel and Ng proved that this algorithm converges in at most O(k(1−γ)2ϵ2log⁡k(1−γ)ϵ)\mathcal{O}\left(\frac{k}{(1 - \gamma)^2 \epsilon^2} \log \frac{k}{(1 - \gamma) \epsilon}\right) iterations, where kk is the feature dimension.

Worked numerical example

Let the state feature dimension be k=2k = 2. The expert's feature expectation vector is:

μE=[0.800.60]with∥μE∥2=0.802+0.602=1.00\mu_E = \begin{bmatrix} 0.80 \\ 0.60 \end{bmatrix} \quad \text{with} \quad \|\mu_E\|_2 = \sqrt{0.80^2 + 0.60^2} = 1.00

Our convergence threshold is ϵ=0.10\epsilon = 0.10.

Iteration 0: Baseline Policy

  1. An initial random policy π(0)\pi^{(0)} yields feature expectation: μ(0)=[0.200.20]\mu^{(0)} = \begin{bmatrix} 0.20 \\ 0.20 \end{bmatrix}
  2. The initial convex projection point is μˉ(0)=μ(0)=[0.20,0.20]⊤\bar{\mu}^{(0)} = \mu^{(0)} = [0.20, 0.20]^\top.
  3. Difference vector: w(1)=μE−μˉ(0)=[0.80−0.200.60−0.20]=[0.600.40]w^{(1)} = \mu_E - \bar{\mu}^{(0)} = \begin{bmatrix} 0.80 - 0.20 \\ 0.60 - 0.20 \end{bmatrix} = \begin{bmatrix} 0.60 \\ 0.40 \end{bmatrix}
  4. Initial margin: t(0)=∥w(1)∥2=0.602+0.402=0.36+0.16=0.52≈0.7211t^{(0)} = \|w^{(1)}\|_2 = \sqrt{0.60^2 + 0.40^2} = \sqrt{0.36 + 0.16} = \sqrt{0.52} \approx 0.7211 Since 0.7211>0.100.7211 > 0.10, the algorithm continues.
  5. Normalized candidate reward vector: w^(1)=w(1)∥w(1)∥2=[0.60/0.72110.40/0.7211]≈[0.83210.5547]\hat{w}^{(1)} = \frac{w^{(1)}}{\|w^{(1)}\|_2} = \begin{bmatrix} 0.60 / 0.7211 \\ 0.40 / 0.7211 \end{bmatrix} \approx \begin{bmatrix} 0.8321 \\ 0.5547 \end{bmatrix}

Iteration 1: First RL Inner Loop

  1. The forward RL solver optimizes R(s)=0.8321ϕ1(s)+0.5547ϕ2(s)R(s) = 0.8321 \phi_1(s) + 0.5547 \phi_2(s), returning policy π(1)\pi^{(1)} with feature expectation: μ(1)=[0.550.35]\mu^{(1)} = \begin{bmatrix} 0.55 \\ 0.35 \end{bmatrix}
  2. Direction vector along the line segment: v1=μ(1)−μˉ(0)=[0.55−0.200.35−0.20]=[0.350.15]v_1 = \mu^{(1)} - \bar{\mu}^{(0)} = \begin{bmatrix} 0.55 - 0.20 \\ 0.35 - 0.20 \end{bmatrix} = \begin{bmatrix} 0.35 \\ 0.15 \end{bmatrix}
  3. Projection scalar β1\beta_1: v1⊤(μE−μˉ(0))=(0.35×0.60)+(0.15×0.40)=0.210+0.060=0.270v_1^\top (\mu_E - \bar{\mu}^{(0)}) = (0.35 \times 0.60) + (0.15 \times 0.40) = 0.210 + 0.060 = 0.270 ∥v1∥22=0.352+0.152=0.1225+0.0225=0.1450\|v_1\|_2^2 = 0.35^2 + 0.15^2 = 0.1225 + 0.0225 = 0.1450 β1=0.2700.1450≈1.8621  ⟹  clipped to 1.0\beta_1 = \frac{0.270}{0.1450} \approx 1.8621 \implies \text{clipped to } 1.0
  4. Since β1\beta_1 is clipped to 1.01.0, the closest point on the segment is the endpoint: μˉ(1)=μ(1)=[0.550.35]\bar{\mu}^{(1)} = \mu^{(1)} = \begin{bmatrix} 0.55 \\ 0.35 \end{bmatrix}
  5. New difference vector: w(2)=μE−μˉ(1)=[0.80−0.550.60−0.35]=[0.250.25]w^{(2)} = \mu_E - \bar{\mu}^{(1)} = \begin{bmatrix} 0.80 - 0.55 \\ 0.60 - 0.35 \end{bmatrix} = \begin{bmatrix} 0.25 \\ 0.25 \end{bmatrix}
  6. New margin: t(1)=∥w(2)∥2=0.252+0.252=0.0625+0.0625=0.125≈0.3536t^{(1)} = \|w^{(2)}\|_2 = \sqrt{0.25^2 + 0.25^2} = \sqrt{0.0625 + 0.0625} = \sqrt{0.125} \approx 0.3536 The margin has shrunk from 0.7211→0.35360.7211 \to 0.3536.
  7. Normalized candidate reward vector: w^(2)=w(2)∥w(2)∥2=[0.25/0.35360.25/0.3536]≈[0.70710.7071]\hat{w}^{(2)} = \frac{w^{(2)}}{\|w^{(2)}\|_2} = \begin{bmatrix} 0.25 / 0.3536 \\ 0.25 / 0.3536 \end{bmatrix} \approx \begin{bmatrix} 0.7071 \\ 0.7071 \end{bmatrix}

Iteration 2: Second RL Inner Loop

  1. The forward RL solver optimizes R(s)=0.7071ϕ1(s)+0.7071ϕ2(s)R(s) = 0.7071 \phi_1(s) + 0.7071 \phi_2(s), returning policy π(2)\pi^{(2)} with feature expectation: μ(2)=[0.750.52]\mu^{(2)} = \begin{bmatrix} 0.75 \\ 0.52 \end{bmatrix}
  2. Direction vector along segment [μˉ(1),μ(2)][\bar{\mu}^{(1)}, \mu^{(2)}]: v2=μ(2)−μˉ(1)=[0.75−0.550.52−0.35]=[0.200.17]v_2 = \mu^{(2)} - \bar{\mu}^{(1)} = \begin{bmatrix} 0.75 - 0.55 \\ 0.52 - 0.35 \end{bmatrix} = \begin{bmatrix} 0.20 \\ 0.17 \end{bmatrix}
  3. Projection scalar β2\beta_2: v2⊤(μE−μˉ(1))=(0.20×0.25)+(0.17×0.25)=0.050+0.0425=0.0925v_2^\top (\mu_E - \bar{\mu}^{(1)}) = (0.20 \times 0.25) + (0.17 \times 0.25) = 0.050 + 0.0425 = 0.0925 ∥v2∥22=0.202+0.172=0.0400+0.0289=0.0689\|v_2\|_2^2 = 0.20^2 + 0.17^2 = 0.0400 + 0.0289 = 0.0689 β2=0.09250.0689≈1.3425  ⟹  clipped to 1.0\beta_2 = \frac{0.0925}{0.0689} \approx 1.3425 \implies \text{clipped to } 1.0
  4. The projection updates to the endpoint: μˉ(2)=μ(2)=[0.750.52]\bar{\mu}^{(2)} = \mu^{(2)} = \begin{bmatrix} 0.75 \\ 0.52 \end{bmatrix}
  5. New difference vector: w(3)=μE−μˉ(2)=[0.80−0.750.60−0.52]=[0.050.08]w^{(3)} = \mu_E - \bar{\mu}^{(2)} = \begin{bmatrix} 0.80 - 0.75 \\ 0.60 - 0.52 \end{bmatrix} = \begin{bmatrix} 0.05 \\ 0.08 \end{bmatrix}
  6. New margin: t(2)=∥w(3)∥2=0.052+0.082=0.0025+0.0064=0.0089≈0.0943t^{(2)} = \|w^{(3)}\|_2 = \sqrt{0.05^2 + 0.08^2} = \sqrt{0.0025 + 0.0064} = \sqrt{0.0089} \approx 0.0943
  7. Because t(2)=0.0943≤ϵ=0.10t^{(2)} = 0.0943 \le \epsilon = 0.10, the algorithm terminates.

By the performance guarantee, the expected return gap between policy π(2)\pi^{(2)} and the expert is bounded:

∣J(π(2))−J(πE)∣≤0.0943\left| J(\pi^{(2)}) - J(\pi_E) \right| \le 0.0943

The apprentice is guaranteed to perform within 0.09430.0943 return units of the expert under any arbitrary linear combination of features.

Code

The following type-hinted implementation demonstrates the Abbeel & Ng Projection Algorithm, performing iterative convex projection, candidate reward weight calculation, and margin tracking.

from typing import Listimport numpy as np

class ApprenticeshipLearningProjection:    """    Abbeel & Ng (2004) Projection Algorithm for Apprenticeship Learning.    Matches feature expectations between learner and expert via iterative projection.    """
    def __init__(self, mu_expert: np.ndarray, epsilon: float = 0.10) -> None:        self.mu_expert = np.asarray(mu_expert, dtype=np.float64)        self.epsilon = epsilon        self.history_mu: List[np.ndarray] = []        self.history_w: List[np.ndarray] = []        self.history_margins: List[float] = []
    def compute_projection(        self, mu_bar_prev: np.ndarray, mu_new: np.ndarray    ) -> np.ndarray:        """        Projects mu_expert onto the line segment connecting mu_bar_prev and mu_new.        """        v = mu_new - mu_bar_prev        denom = float(np.dot(v, v))        if denom < 1e-12:            return mu_new
        numer = float(np.dot(v, self.mu_expert - mu_bar_prev))        beta = np.clip(numer / denom, 0.0, 1.0)        return mu_bar_prev + beta * v
    def run_demonstration(        self, simulated_responses: List[np.ndarray]    ) -> None:        """        Executes the outer apprenticeship loop across iterations.        """        # Step 0: Initial random policy feature expectation        mu_0 = np.array([0.20, 0.20])        self.history_mu.append(mu_0)
        mu_bar = mu_0.copy()        w = self.mu_expert - mu_bar        margin = float(np.linalg.norm(w))        self.history_margins.append(margin)        self.history_w.append(w / margin if margin > 0 else w)
        print(f"Iteration 0: Initial margin t = {margin:.4f}")
        iteration = 1        for mu_new in simulated_responses:            candidate_w = w / margin            self.history_mu.append(mu_new)
            # Update orthogonal projection onto convex hull            mu_bar = self.compute_projection(mu_bar, mu_new)
            # Recompute separating hyperplane and margin            w = self.mu_expert - mu_bar            margin = float(np.linalg.norm(w))            self.history_margins.append(margin)            self.history_w.append(w / margin if margin > 0 else w)
            print(                f"Iteration {iteration}: "                f"w = [{candidate_w[0]:.4f}, {candidate_w[1]:.4f}], "                f"mu_new = [{mu_new[0]:.4f}, {mu_new[1]:.4f}], "                f"mu_bar = [{mu_bar[0]:.4f}, {mu_bar[1]:.4f}], "                f"margin t = {margin:.4f}"            )            iteration += 1
            if margin <= self.epsilon:                break
        print(f"\nFinal Convergence: Margin {margin:.4f} <= epsilon {self.epsilon}")        print(f"Expert Performance Guarantee: |J(pi) - J(pi_E)| <= {margin:.4f}")

if __name__ == "__main__":    expert_features = np.array([0.80, 0.60])    learner = ApprenticeshipLearningProjection(        mu_expert=expert_features, epsilon=0.10    )
    # Simulated policies produced by forward RL on candidate rewards    policy_rollouts = [        np.array([0.55, 0.35]),        np.array([0.75, 0.52]),        np.array([0.79, 0.58]),    ]
    learner.run_demonstration(simulated_responses=policy_rollouts)

Output:

Iteration 0: Initial margin t = 0.7211Iteration 1: w = [0.8321, 0.5547], mu_new = [0.5500, 0.3500], mu_bar = [0.5500, 0.3500], margin t = 0.3536Iteration 2: w = [0.7071, 0.7071], mu_new = [0.7500, 0.5200], mu_bar = [0.7500, 0.5200], margin t = 0.0943
Final Convergence: Margin 0.0943 <= epsilon 0.1Expert Performance Guarantee: |J(pi) - J(pi_E)| <= 0.0943

Watch Out For

Nested Inner-Loop RL: The Computational Bottleneck

The defining operational challenge of Apprenticeship Learning via IRL is the nested bilevel loop. In step (4), the algorithm requires solving a full forward reinforcement learning problem from scratch for every newly proposed candidate reward vector w^(i)\hat{w}^{(i)}.

In small discrete tabular MDPs, solving the inner loop using Value Iteration or Policy Iteration takes fractions of a second. However, in continuous high-dimensional robotics with neural network function approximators (such as PPO or SAC), training a policy to convergence inside each outer iteration requires millions of environment interactions, rendering the algorithm computationally prohibitive.

The Fix: Two practical remedies exist:

  1. Warm-Starting: Rather than training a neural policy from random initialization at each outer step, warm-start the network parameters from the policy obtained in iteration i−1i-1. Because candidate weights shift smoothly, the policy requires only fine-tuning.
  2. Adversarial Single-Step Formulation (GAIL): In modern applications, practitioners replace the nested double loop with Generative Adversarial Imitation Learning (GAIL). GAIL translates feature expectation matching into a minimax game where a discriminator updates reward signals in single gradient steps concurrently with policy updates.

The Quick Version

  • Feature Expectation Matching: Apprenticeship Learning guarantees near-expert performance by matching the expert's discounted feature expectation vector μE\mu_E, bounding return error by ∣J(π)−J(πE)∣≤∥μ(π)−μE∥2|J(\pi) - J(\pi_E)| \le \|\mu(\pi) - \mu_E\|_2.
  • Reward Agnosticism: The apprentice achieves expert competence without ever identifying or recovering the expert's true underlying reward weight vector w∗w^*.
  • Geometric Margin Optimization: Abbeel and Ng's Projection Algorithm iteratively builds candidate reward vectors pointing from the convex hull of past learner policies toward the expert, shrinking the margin monotonically.
  • Inner-Loop Complexity: Solving a full forward RL MDP for every candidate reward vector is computationally expensive, motivating warm-start heuristics and modern single-loop adversarial frameworks like GAIL.