Ru00y.
Jul 3, 2026 · 13 min

From TD(lambda) to GAE: The Forward-Backward View

Explains TD(lambda)'s forward-backward equivalence, how it leads to GAE for advantage estimation in PPO, and how eligibility traces work with O(1) memory.

From TD(lambda) to GAE: Eligibility Traces and the Forward-Backward Equivalence#

From TD(lambda) to Generalized Advantage Estimation — Eligibility Traces and the Forward-Backward Equivalence

Starting from TD(lambda)‘s forward-backward equivalence, this post explains why PPO uses GAE to estimate advantage, how eligibility traces achieve n-step credit assignment with O(1)O(1) extra memory, and how it all connects to the reward signal backpropagation in RLHF training.

Prerequisites: you should know what advantage is and the basics of TD learning.


0. Notation#

SymbolMeaning
st,at,rts_t, a_t, r_tState, action, and immediate reward at time tt
τ=(s1,a1,r1,,sT,aT,rT)\tau = (s_1, a_1, r_1, \dots, s_T, a_T, r_T)A complete trajectory
πθ(atst)\pi_\theta(a_t \mid s_t)Policy: given state, outputs a distribution over actions
Vϕ(st)V_\phi(s_t)Value function: expected cumulative reward starting from sts_t
AtA_tAdvantage: how much better action ata_t is than expected
γ[0,1]\gamma \in [0,1]Discount factor
λ[0,1]\lambda \in [0,1]Decay parameter for TD(lambda) / GAE
δt\delta_tTD error: rt+γV(st+1)V(st)r_t + \gamma V(s_{t+1}) - V(s_t)

1. Motivation: The Fundamental Bias-Variance Tradeoff#

In RL, evaluating how good an action is requires estimating the return — the total reward from the current step until the end of the episode:

Gt=rt+γrt+1+γ2rt+2++γTtrTG_t = r_t + \gamma r_{t+1} + \gamma^2 r_{t+2} + \dots + \gamma^{T-t} r_T

But the true return is unknowable until the episode finishes. Every method trades off between bias and variance:

MethodBiasVarianceProblem
TD(0)HighLowIf VV is misestimated, errors propagate through bootstrapping
Monte CarloNoneHighAll the randomness across the entire trajectory piles up; needs massive samples
n-step TDMediumMediumA fixed nn is rigid — who decided n=4n=4 is better than n=5n=5?

2. Three Basic Methods#

2.1 TD(0): One Step at a Time#

Gt(1)=rt+γV(st+1)G_t^{(1)} = r_t + \gamma V(s_{t+1})

δt=rt+γV(st+1)V(st)\delta_t = r_t + \gamma V(s_{t+1}) - V(s_t)

One-step bootstrap. Lowest variance, but bias in VV directly contaminates the update.

2.2 n-step TD: A Fixed Window#

Gt(n)=rt+γrt+1++γn1rt+n1n steps of real reward+γnV(st+n)bootstrapG_t^{(n)} = \underbrace{r_t + \gamma r_{t+1} + \dots + \gamma^{n-1} r_{t+n-1}}_{n \text{ steps of real reward}} + \underbrace{\gamma^n V(s_{t+n})}_{\text{bootstrap}}

Larger nn means closer to MC (low bias, high variance). Smaller nn means closer to TD(0). The problem: the optimal nn is task-dependent, and tuning it is painful.

2.3 Monte Carlo: All the Way#

GtMC=k=0Ttγkrt+kG_t^{\text{MC}} = \sum_{k=0}^{T-t} \gamma^k r_{t+k}

Zero bias, no bootstrap. But variance is (Tt)σr2\propto (T-t) \cdot \sigma_r^2, making long sequences nearly unusable.


3. TD(lambda): Mixing All n-step Returns with Geometric Weighting#

The issue with a fixed nn is that the reward at step n+1n+1 is completely cut off from the update — it can only leak through indirectly via the bootstrap, which is painfully slow.

TD(lambda)‘s solution: mix together returns for n=1,2,3,,n = 1, 2, 3, \dots, \infty:

Gtλ=(1λ)n=1λn1Gt(n)G_t^\lambda = (1-\lambda)\sum_{n=1}^{\infty} \lambda^{n-1} G_t^{(n)}

The weight distribution:

(1λ), (1λ)λ, (1λ)λ2, (1-\lambda),\ (1-\lambda)\lambda,\ (1-\lambda)\lambda^2,\ \dots


3.1 Why Geometric Weighting?#

1. Continuous Bias-Variance Tradeoff

λ=0\lambda = 0 gives only Gt(1)G_t^{(1)}, i.e. TD(0). λ=1\lambda = 1 gives only Gt()G_t^{(\infty)}, i.e. MC (in finite-horizon settings).

Any intermediate λ\lambda interpolates continuously between the two. No need to agonize over a fixed nn.

2. Eligibility Traces

If the weights weren’t geometric, implementing an n-step mixture would require storing all data from the next n steps in memory — you’d have to wait until step t+nt+n to receive the reward before updating step tt. This is the forward view — you must wait for the episode to end; it cannot run online.

Geometric weights have a special property: the current weight equals the previous weight times lambda. From this, we derive the equivalent backward view — each state only needs to maintain a single scalar trace (the accumulating trace):

Et(s)=γλEt1(s)+I{St=s}E_t(s) = \gamma\lambda \cdot E_{t-1}(s) + \mathbb{I}_{\{S_t = s\}}

Once we have δt\delta_t, we update all states simultaneously:

V(s)V(s)+αδtEt(s)V(s) \leftarrow V(s) + \alpha \cdot \delta_t \cdot E_t(s)

No n-step buffer needed, no waiting for the episode to end. O(1)O(1) extra memory per state, fully online.

3. Robustness to Noise

If you only use a fixed nn, one unusually noisy step at position nn can contaminate the entire update. A geometric mixture is effectively a weighted smoothing filter over all nn — the noise from any single long-step return gets diluted. Lambda serves as a single knob, far less sensitive to hyperparameters than a fixed nn.


3.2 Lemma: Expanding Gt:t+nV(St)G_{t:t+n} - V(S_t) via TD Errors#

This identity underpins all subsequent derivations, so let’s prove it separately:

Gt:t+nV(St)=i=0n1γiδt+iG_{t:t+n} - V(S_t) = \sum_{i=0}^{n-1} \gamma^i \delta_{t+i}

Proof (telescoping sum):

Gt:t+nV(St)=(i=1nγi1Rt+i+γnV(St+n))V(St)G_{t:t+n} - V(S_t) = \left(\sum_{i=1}^{n} \gamma^{i-1} R_{t+i} + \gamma^n V(S_{t+n})\right) - V(S_t)

Substitute δt+i=Rt+i+1+γV(St+i+1)V(St+i)\delta_{t+i} = R_{t+i+1} + \gamma V(S_{t+i+1}) - V(S_{t+i}) into the right-hand side i=0n1γiδt+i\sum_{i=0}^{n-1} \gamma^i \delta_{t+i}:

i=0n1γiδt+i=i=0n1γi[Rt+i+1+γV(St+i+1)V(St+i)]\sum_{i=0}^{n-1} \gamma^i \delta_{t+i} = \sum_{i=0}^{n-1} \gamma^i \left[R_{t+i+1} + \gamma V(S_{t+i+1}) - V(S_{t+i})\right]

=i=0n1γiRt+i+1=i=1nγi1Rt+i+i=0n1γi+1V(St+i+1)i=0n1γiV(St+i)telescoping= \underbrace{\sum_{i=0}^{n-1} \gamma^i R_{t+i+1}}_{= \sum_{i=1}^{n} \gamma^{i-1} R_{t+i}} + \underbrace{\sum_{i=0}^{n-1} \gamma^{i+1} V(S_{t+i+1}) - \sum_{i=0}^{n-1} \gamma^i V(S_{t+i})}_{\text{telescoping}}

Writing out the telescoping of the last two terms makes it clear:

i=0n1γi+1V(St+i+1)=γV(St+1)+γ2V(St+2)++γnV(St+n)\sum_{i=0}^{n-1} \gamma^{i+1} V(S_{t+i+1}) = \gamma V(S_{t+1}) + \gamma^2 V(S_{t+2}) + \cdots + \gamma^n V(S_{t+n})

i=0n1γiV(St+i)=V(St)+γV(St+1)++γn1V(St+n1)\sum_{i=0}^{n-1} \gamma^i V(S_{t+i}) = V(S_t) + \gamma V(S_{t+1}) + \cdots + \gamma^{n-1} V(S_{t+n-1})

Subtracting, the middle terms γV(St+1)γn1V(St+n1)\gamma V(S_{t+1}) \cdots \gamma^{n-1} V(S_{t+n-1}) all cancel, leaving:

γnV(St+n)V(St)\gamma^n V(S_{t+n}) - V(S_t)

Therefore i=0n1γiδt+i=i=1nγi1Rt+i+γnV(St+n)V(St)=Gt:t+nV(St)\sum_{i=0}^{n-1} \gamma^i \delta_{t+i} = \sum_{i=1}^{n} \gamma^{i-1} R_{t+i} + \gamma^n V(S_{t+n}) - V(S_t) = G_{t:t+n} - V(S_t). \square

3.3 Forward View as (γλ)krt+k\sum (\gamma\lambda)^k r_{t+k}#

The forward view definition:

Gtλ=(1λ)n=1λn1Gt(n)G_t^\lambda = (1-\lambda)\sum_{n=1}^{\infty} \lambda^{n-1} G_t^{(n)}

Substituting the expansion of Gt(n)G_t^{(n)}:

Gtλ=(1λ)n=1λn1[k=0n1γkrt+k+γnV(st+n)]G_t^\lambda = (1-\lambda)\sum_{n=1}^{\infty} \lambda^{n-1} \left[\sum_{k=0}^{n-1} \gamma^k r_{t+k} + \gamma^n V(s_{t+n})\right]

For a finite episode, once nn exceeds the trajectory endpoint, V(st+n)V(s_{t+n}) lands on a terminal state (V=0V=0), and the bootstrap term vanishes naturally. For the infinite case, γ<1|\gamma| < 1 guarantees γnV(st+n)0\gamma^n V(s_{t+n}) \to 0 (since VV is bounded). In both cases, only the reward portion remains in the lambda-return:

Gtλ=(1λ)n=1λn1k=0n1γkrt+kG_t^\lambda = (1-\lambda)\sum_{n=1}^{\infty} \lambda^{n-1} \sum_{k=0}^{n-1} \gamma^k r_{t+k}

Swap the order of the double sum. The outer nn runs from 11 to \infty, the inner kk from 00 to n1n-1. Equivalently, kk runs from 00 to \infty and nn runs from k+1k+1 to \infty:

Gtλ=(1λ)k=0γkrt+kn=k+1λn1G_t^\lambda = (1-\lambda)\sum_{k=0}^{\infty} \gamma^k r_{t+k} \sum_{n=k+1}^{\infty} \lambda^{n-1}

Change variables in the inner sum: let m=nk1m = n-k-1, so n=m+k+1n = m+k+1:

n=k+1λn1=m=0λm+k=λkm=0λm=λk1λ\sum_{n=k+1}^{\infty} \lambda^{n-1} = \sum_{m=0}^{\infty} \lambda^{m+k} = \lambda^k \sum_{m=0}^{\infty} \lambda^m = \frac{\lambda^k}{1-\lambda}

Substituting back:

Gtλ=(1λ)k=0γkrt+kλk1λ=k=0(λγ)krt+kG_t^\lambda = (1-\lambda)\sum_{k=0}^{\infty} \gamma^k r_{t+k} \cdot \frac{\lambda^k}{1-\lambda} = \sum_{k=0}^{\infty} (\lambda\gamma)^k r_{t+k}

This is the forward view in reward form — “the sum of future rewards decaying by (λγ)k(\lambda\gamma)^k.“


3.4 Forward View to Backward View: Straight from the Definition#

There is no need to first derive the reward form and then substitute rδr \to \delta back in — that route introduces an extra S2S3S_2 - S_3 cancellation step with unnecessary technical detail. The shortest path uses the lemma from section 3.2 directly.

Start from the forward view definition:

Gtλ=(1λ)n=1λn1Gt(n)G_t^\lambda = (1-\lambda)\sum_{n=1}^{\infty} \lambda^{n-1} G_t^{(n)}

Subtract V(st)V(s_t) from both sides and apply section 3.2’s result Gt(n)V(st)=i=0n1γiδt+iG_t^{(n)} - V(s_t) = \sum_{i=0}^{n-1} \gamma^i \delta_{t+i}:

GtλV(st)=(1λ)n=1λn1i=0n1γiδt+iG_t^\lambda - V(s_t) = (1-\lambda)\sum_{n=1}^{\infty} \lambda^{n-1} \sum_{i=0}^{n-1} \gamma^i \delta_{t+i}

Swap the summation order — the exact same trick as section 3.3, with ii from 00 to \infty and nn from i+1i+1 to \infty:

GtλV(st)=(1λ)i=0γiδt+in=i+1λn1=(1λ)i=0γiδt+iλi1λG_t^\lambda - V(s_t) = (1-\lambda)\sum_{i=0}^{\infty} \gamma^i \delta_{t+i} \sum_{n=i+1}^{\infty} \lambda^{n-1} = (1-\lambda)\sum_{i=0}^{\infty} \gamma^i \delta_{t+i} \cdot \frac{\lambda^i}{1-\lambda}

Gtλ=V(st)+k=0(γλ)kδt+k\boxed{G_t^\lambda = V(s_t) + \sum_{k=0}^{\infty} (\gamma\lambda)^k \delta_{t+k}}

This is the equivalent backward view — expressing lambda-return as V(st)V(s_t) plus a decaying sum of TD errors. Note that δt=rt+γV(st+1)V(st)\delta_t = r_t + \gamma V(s_{t+1}) - V(s_t) only depends on two adjacent states, so it can be computed online at each step, broadcast backward along the eligibility trace, with no need to wait for the episode to end.

The derivation never uses the S2S3S_2 - S_3 cancellation — the lemma in section 3.2 already took care of the V(st)V(s_t) cancellation upfront. All we did here was reorganize the weighted sum of δt\delta_t.


3.5 A Rigorous Proof of Forward-Backward Equivalence (Offline Case)#

Under offline updates, VV stays fixed throughout the entire episode, so all δt\delta_t are constant. We now prove that the total update from the forward view equals the total update from the backward view.

Forward view: at each time tt, update VV toward the target GtλG_t^\lambda:

ΔVForward(s)=αt=0T1(GtλV(St))I{St=s}\Delta V_{\text{Forward}}(s) = \alpha \sum_{t=0}^{T-1} \left(G_t^\lambda - V(S_t)\right) \mathbb{I}_{\{S_t = s\}}

Substitute GtλV(St)=k=0T1t(γλ)kδt+kG_t^\lambda - V(S_t) = \sum_{k=0}^{T-1-t} (\gamma\lambda)^k \delta_{t+k}:

ΔVForward(s)=αt=0T1[k=0T1t(γλ)kδt+k]I{St=s}\Delta V_{\text{Forward}}(s) = \alpha \sum_{t=0}^{T-1} \left[\sum_{k=0}^{T-1-t} (\gamma\lambda)^k \delta_{t+k}\right] \mathbb{I}_{\{S_t = s\}}

Backward view: at each time tt, use δt\delta_t and the eligibility trace Et(s)E_t(s) to update all states:

ΔVBackward(s)=αt=0T1δtEt(s)\Delta V_{\text{Backward}}(s) = \alpha \sum_{t=0}^{T-1} \delta_t E_t(s)

Expand the eligibility trace: Et(s)=j=0t(γλ)tjI{Sj=s}E_t(s) = \sum_{j=0}^{t} (\gamma\lambda)^{t-j} \mathbb{I}_{\{S_j = s\}}. Substituting:

ΔVBackward(s)=αt=0T1δt[j=0t(γλ)tjI{Sj=s}]\Delta V_{\text{Backward}}(s) = \alpha \sum_{t=0}^{T-1} \delta_t \left[\sum_{j=0}^{t} (\gamma\lambda)^{t-j} \mathbb{I}_{\{S_j = s\}}\right]

Swap the sums: let τ=t\tau = t and t=jt' = j. In the forward view, set τ=t+k\tau = t+k (so k=τtk = \tau - t, with tτt \le \tau):

ΔVForward(s)=ατ=0T1δτ[t=0τ(γλ)τtI{St=s}]\Delta V_{\text{Forward}}(s) = \alpha \sum_{\tau=0}^{T-1} \delta_\tau \left[\sum_{t=0}^{\tau} (\gamma\lambda)^{\tau-t} \mathbb{I}_{\{S_t = s\}}\right]

In the backward view (with t=τt = \tau, j=tj = t'):

ΔVBackward(s)=ατ=0T1δτ[t=0τ(γλ)τtI{St=s}]\Delta V_{\text{Backward}}(s) = \alpha \sum_{\tau=0}^{T-1} \delta_\tau \left[\sum_{t'=0}^{\tau} (\gamma\lambda)^{\tau-t'} \mathbb{I}_{\{S_{t'} = s\}}\right]

The expressions inside the brackets are identical, therefore:

ΔVForward(s)=ΔVBackward(s)\boxed{\Delta V_{\text{Forward}}(s) = \Delta V_{\text{Backward}}(s)}

The forward and backward views are strictly equivalent in the offline sense. Through eligibility traces Et(s)E_t(s), the backward view achieves — with O(S)O(|S|) extra memory — the same credit assignment that the forward view would need to buffer the entire trajectory to compute.

3.6 Three Types of Eligibility Traces#

Sections 3.2 through 3.4 all used the accumulating trace:

Et(s)=γλEt1(s)+I{St=s}E_t(s) = \gamma\lambda E_{t-1}(s) + \mathbb{I}_{\{S_t = s\}}

When a state is visited repeatedly, the trace has no upper bound (it can grow past 11), which may cause gradient explosion under function approximation. In practice, there are two variants.

Replacing trace:

Et(s)={1if St=sγλEt1(s)otherwiseE_t(s) = \begin{cases} 1 & \text{if } S_t = s \\ \gamma\lambda E_{t-1}(s) & \text{otherwise} \end{cases}

On each revisit, the trace is reset to 1 rather than accumulated. Bounded above by 11, numerically more stable. PPO and GAE implementations typically use a replacing trace or compute offline (in which case the trace type is irrelevant, since GAE bypasses explicit traces via backward scanning).

Dutch trace (interpolating between the two, α[0,1]\alpha \in [0,1]):

Et(s)={αγλEt1(s)+1if St=sγλEt1(s)otherwiseE_t(s) = \begin{cases} \alpha \cdot \gamma\lambda E_{t-1}(s) + 1 & \text{if } S_t = s \\ \gamma\lambda E_{t-1}(s) & \text{otherwise} \end{cases}

α=0\alpha = 0 degenerates to replacing (reset to 11 on revisit), α=1\alpha = 1 degenerates to accumulating (decay then +1+1 on revisit). Intermediate α\alpha controls how much of the old trace is retained.

3.7 Offline Equivalence to Online Approximation#

The proof in section 3.5 relies on a critical assumption: VV remains fixed throughout the episode. In an online setting, VV changes after every update, and subsequent δt\delta_t shift accordingly — the forward and backward views are no longer strictly equivalent.

Seijen & Sutton (2014) proposed true online TD(lambda), which applies an extra correction to the trace at each update to restore equivalence, at the cost of increasing per-step computation from O(S)O(|S|) to O(d)O(d) (where dd is the parameter dimension of VV). This correction is rarely used in practice, because the online approximation error is negligible on most tasks, especially in algorithms like PPO that already perform offline batch updates after episodes finish.


4. GAE: From lambda-Return to Advantage#

4.1 Definition#

The original definition of advantage:

At=GtV(st)A_t = G_t - V(s_t)

“How much better the actual return is compared to what V(st)V(s_t) predicted.”

GAE’s approach: replace GtG_t with GtλG_t^\lambda:

AtGAE(γ,λ)=GtλV(st)A_t^{\text{GAE}(\gamma,\lambda)} = G_t^\lambda - V(s_t)

Substituting Gtλ=V(st)+(γλ)kδt+kG_t^\lambda = V(s_t) + \sum (\gamma\lambda)^k \delta_{t+k}:

AtGAE(γ,λ)=k=0(γλ)kδt+kA_t^{\text{GAE}(\gamma,\lambda)} = \sum_{k=0}^{\infty} (\gamma\lambda)^k \delta_{t+k}

V(st)V(s_t) cancels out. The GAE advantage estimate does not directly depend on the absolute value of V(st)V(s_t) — it only depends on TD errors (the differences between VV at adjacent states). Part of the bias cancels in the subtraction, which is why GAE is more stable than directly using GtV(st)G_t - V(s_t).

4.2 Finite-Length Truncation#

In practice, trajectory length is TT, and the sum is truncated:

AtGAE(γ,λ)=l=0Tt1(γλ)lδt+lA_t^{\text{GAE}(\gamma,\lambda)} = \sum_{l=0}^{T-t-1} (\gamma\lambda)^l \delta_{t+l}

δt+l=rt+l+γV(st+l+1)V(st+l)\delta_{t+l} = r_{t+l} + \gamma V(s_{t+l+1}) - V(s_{t+l})

4.3 Two Extremes#

λ\lambdaAtA_tMeaning
00δt\delta_tTD(0) — look one step ahead, fully trust VV
11l=0Tt1γlδt+l=GtV(st)\sum_{l=0}^{T-t-1} \gamma^l \delta_{t+l} = G_t - V(s_t)Monte Carlo — trust VV not at all, only real rewards

4.4 Computation: O(T)O(T) Backward Scan#

The recurrence:

AT1=δT1,At=δt+γλAt+1for t=T2,,0A_{T-1} = \delta_{T-1}, \qquad A_t = \delta_t + \gamma\lambda \cdot A_{t+1} \quad \text{for } t = T-2, \dots, 0

A single backward pass — no need to explicitly sum over each tt.

4.5 Implementation: Under 10 Lines of PyTorch#

def compute_gae(rewards, values, gamma, lam):
    """
    rewards: [T]   per-step immediate rewards
    values:  [T+1] per-step V estimates (includes terminal V(s_{T+1}))
    returns: advantages [T]
    """
    advantages = torch.zeros_like(rewards)
    gae = 0
    for t in reversed(range(len(rewards))):
        delta = rewards[t] + gamma * values[t+1] - values[t]
        gae = delta + gamma * lam * gae
        advantages[t] = gae
    return advantages
python

The line delta + gamma * lam * gae is a direct translation of At=δt+γλAt+1A_t = \delta_t + \gamma\lambda \cdot A_{t+1}. The entire function is just this one recurrence; everything else is index alignment.


5. Derivation Chain Overview#

Gt(n)=k=0n1γkrt+k+γnV(st+n)geometric mixtureGtλ=k=0(γλ)krt+klemmaGtλ=V(st)+k=0(γλ)kδt+kV(st)At=l=0(γλ)lδt+ltruncateAt=δt+γλAt+1\begin{aligned} G_t^{(n)} &= \sum_{k=0}^{n-1} \gamma^k r_{t+k} + \gamma^n V(s_{t+n}) \\ &\xrightarrow{\text{geometric mixture}} \quad G_t^\lambda = \sum_{k=0}^{\infty} (\gamma\lambda)^k r_{t+k} \\ &\xrightarrow{\text{lemma}} \quad G_t^\lambda = V(s_t) + \sum_{k=0}^{\infty} (\gamma\lambda)^k \delta_{t+k} \\ &\xrightarrow{-V(s_t)} \quad A_t = \sum_{l=0}^{\infty} (\gamma\lambda)^l \delta_{t+l} \\ &\xrightarrow{\text{truncate}} \quad A_t = \delta_t + \gamma\lambda \cdot A_{t+1} \end{aligned}

One line, five steps, from n-step return to the PPO implementation.


6. Application in RLHF#

Taking [[Fine-Tuning GPT-2 from Human Preferences (2019)]] as an example, GAE’s usage in RLHF training differs from standard RL in a few key ways.

6.1 RLHF as an MDP#

Text generation is modeled as a token-level MDP:

  • State sts_t: the prompt xx plus the first t1t-1 generated tokens
  • Action ata_t: generating the tt-th token (choosing from the vocabulary)
  • Reward: the reward model rϕ(x,y)r_\phi(x, y) scores the entire text — this means sparse rewards: only the final token receives a non-zero reward; all intermediate tokens get zero immediate reward

So in a sequence of length TT, only rT1r_{T-1} (or rTr_T, depending on indexing convention) is non-zero. Every r0,r1,,rT2r_0, r_1, \dots, r_{T-2} is exactly zero.

6.2 Why gamma = 1?#

Text generation tasks typically set γ=1\gamma = 1. The reason isn’t “text has no discounting” — it is more specific:

  • Text generation is a finite-horizon task (the episode naturally terminates at the EOS token), so there is no need for γ<1\gamma < 1 to keep the return bounded
  • γ<1\gamma < 1 introduces positional bias — earlier tokens get inherently less credit than later ones, but this makes no sense for text (the first sentence matters just as much as the last paragraph for overall quality)
  • With γ=1\gamma = 1, the TD errors for all intermediate tokens simplify to:

δt=0rt+1γV(st+1)V(st)=V(st+1)V(st)\delta_t = \underbrace{0}_{r_t} + \underbrace{1}_{\gamma} \cdot V(s_{t+1}) - V(s_t) = V(s_{t+1}) - V(s_t)

Only the final step differs: δT1=rT1+V(sT)V(sT1)\delta_{T-1} = r_{T-1} + V(s_T) - V(s_{T-1}), where V(sT)=0V(s_T) = 0 (terminal state).

6.3 GAE’s Credit Assignment Mechanism#

With γ=1\gamma = 1, GAE reduces to:

AtGAE=l=0Tt1λlδt+lA_t^{\text{GAE}} = \sum_{l=0}^{T-t-1} \lambda^l \, \delta_{t+l}

For intermediate tokens, δt=V(st+1)V(st)\delta_t = V(s_{t+1}) - V(s_t). For the final token, δT1=rT1V(sT1)\delta_{T-1} = r_{T-1} - V(s_{T-1}). Working backward from the last token:

AT1=rT1V(sT1)AT2=V(sT1)V(sT2)δT2  +  λ(rT1V(sT1))AT1AT3=δT3+λAT2\begin{aligned} A_{T-1} &= r_{T-1} - V(s_{T-1}) \\ A_{T-2} &= \underbrace{V(s_{T-1}) - V(s_{T-2})}_{\delta_{T-2}} \;+\; \lambda \cdot \underbrace{(r_{T-1} - V(s_{T-1}))}_{A_{T-1}} \\ A_{T-3} &= \delta_{T-3} + \lambda \cdot A_{T-2} \end{aligned}

Intuition: the final reward rT1r_{T-1} “seeps” into earlier δt\delta_t through the differences in V(sT1)V(s_{T-1}), then propagates to even earlier tokens with λl\lambda^l decay. Lambda controls the propagation distance:

  • λ1\lambda \approx 1: rT1r_{T-1} is shared almost equally; every token gets credit
  • λ0\lambda \approx 0: only the token immediately before the reward gets non-zero advantage
  • λ0.95\lambda \approx 0.95 (a common default): 0.95200.360.95^{20} \approx 0.36 — contribution drops to about 1/3 at 20 tokens away

6.4 Coupling with PPO Clipping#

GAE’s output AtA_t feeds directly into PPO’s clipped surrogate objective:

LCLIP(θ)=Et[min(rt(θ)At,  clip(rt(θ),1ϵ,1+ϵ)At)]\mathcal{L}^{\text{CLIP}}(\theta) = \mathbb{E}_t \left[\min\left(r_t(\theta) A_t,\; \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) A_t\right)\right]

Here is an easily overlooked detail: GAE’s lambda and PPO’s clip epsilon are complementary. If lambda is set too high (high variance), you can compensate with a tighter epsilon (more conservative policy updates). If lambda is set too low (high bias), the policy learns something that is fundamentally biased, and no amount of epsilon tuning will fix it. In practice, you typically tune lambda first (to control credit assignment quality), then tune epsilon (to control update stability).


  • [[Fine-Tuning GPT-2 from Human Preferences (2019)]] — section 2.4.3 on GAE’s concrete use in RLHF
  • Sutton & Barto, Chapter 12 — the full theory and convergence proofs for TD(lambda) and eligibility traces
  • Schulman et al. (2015) — the original GAE paper
From TD(lambda) to GAE: The Forward-Backward View
https://ru00ys-lab.com/blog/td-lambda-to-gae
Author Ru00y
Published at July 3, 2026

Enjoyed this post? Never miss out on future posts

Loading comments...

Best in the dark?

This site looks its best in dark mode. Give it a try!