Part XVI — Reinforcement Learning: Bandits, MDPs, Policy Gradients & PPO · Chapter 8

Actor-Critic architectures (A2C/A3C)

Hook

REINFORCE scaled every update by the raw return GG — a noisy number that depends on everything that happened for the rest of the episode. What if something else, learned alongside the policy, could tell it "that was better than expected" or "worse than expected," instead of just "here's a number"?

Intuition
S0
S1
S2
S3
step 1/6: at S0, took "right", advantage (TD error) = -1.00

Back to the familiar gridworld, but now two things learn at once: an actor (a softmax policy, one preference per action per state, just like REINFORCE) and a critic (a V(s)V(s) table, updated the same TD way as the value-function chapters). Step through a trace and watch both bar charts move together — every single step, off the exact same number.

Formalize

The critic learns V(s)V(s) by ordinary one-step TD, producing a TD error:

δ=r+γV(s)V(s)\delta = r + \gamma V(s') - V(s)

The actor then uses that same δ\delta as its advantage estimate, in place of REINFORCE's raw return GG:

θiθi+α(1[i=a]πθ(i))δ\theta_i \leftarrow \theta_i + \alpha\big(\mathbb{1}[i{=}a] - \pi_\theta(i)\big)\,\delta
  • δ\delta — the TD error: how much better or worse the actual outcome was than the critic's own expectation.
  • V(s)V(s) — the critic's current value estimate for state ss.
  • πθ(i)\pi_\theta(i) — the actor's current probability of action ii, from the softmax over its preferences.
  1. Same update shape as REINFORCE, different scale

    The (1[i=a]πθ(i))(\mathbb{1}[i{=}a] - \pi_\theta(i)) term is identical to the REINFORCE chapter. The only thing that changed is what multiplies it: a baseline-subtracted advantage instead of a raw return.

  2. Why this reduces variance

    GG can swing wildly step to step, purely from randomness far in the future. δ\delta only measures the gap between one real step and the critic's own prediction — a much smaller, steadier number to scale a gradient step by, even though it points in the same useful direction on average.

  3. Two learners, one shared signal

    The critic isn't "used" and then discarded — it's trained by its own TD update every step, using the exact same δ\delta the actor consumes. Neither one needs to fully converge before the other starts learning from it.

Play

Before any updates, π(S2)\pi(\cdot \mid S_2) is a coin flip between left and right — nothing has been learned yet. After six steps, "right" has pulled ahead, driven entirely by the critic's own value estimates, which shifted right alongside it.

Worked example

With α=0.5\alpha=0.5 for both actor and critic, γ=0.9\gamma=0.9, starting from an all-zero critic and a uniform actor:

  1. Step 1 — no signal yet, so the update is uninformative but harmless

    From S0S_0, "right" lands on S1S_1 with reward 1-1; V(S1)=0V(S_1)=0 still, so δ=1+0.9(0)0=1\delta = -1+0.9(0)-0=-1. V(S0)0.5(1)=0.5V(S_0) \leftarrow 0.5(-1) = -0.5. With the policy still uniform (π=0.5\pi=0.5 each way), the actor update θiθi+0.5(1[i=right]πi)δ\theta_i \leftarrow \theta_i+0.5(\mathbb{1}[i{=}\text{right}]-\pi_i)\delta gives:

    • θ(S0,right)0+0.5(10.5)(1)=0.25\theta(S_0,\text{right}) \leftarrow 0+0.5(1-0.5)(-1) = -0.25
    • θ(S0,left)0+0.5(00.5)(1)=0.25\theta(S_0,\text{left}) \leftarrow 0+0.5(0-0.5)(-1) = 0.25

    Discouraging the very action just taken, purely because the critic (still near-zero everywhere) rated the outcome as worse than expected.

  2. Step 3 — a real mistake, correctly penalized

    From S2S_2, taking "left" moves away from the goal, landing on S1S_1 (whose value, by now, is already 0.5-0.5, from step 2's own critic update). δ=1+0.9(0.5)0=1.45\delta = -1 + 0.9(-0.5) - 0 = -1.45 — a bigger penalty than step 1's, because this time the critic has real (negative) information about where "left" leads. With S2S_2's policy still uniform:

    • θ(S2,left)0+0.5(10.5)(1.45)=0.3625\theta(S_2,\text{left}) \leftarrow 0+0.5(1-0.5)(-1.45) = -0.3625
    • θ(S2,right)0+0.5(00.5)(1.45)=0.3625\theta(S_2,\text{right}) \leftarrow 0+0.5(0-0.5)(-1.45) = 0.3625

    Already favoring "right" with more than half the probability, after a single update.

  3. Step 5 — reaching the goal spikes the advantage

    From S2S_2, "right" reaches the goal directly: reward +10+10, and V(S2)=0.725V(S_2)=-0.725 at that point (from step 3's own critic update), so δ=10+0.9(0)(0.725)=10.725\delta = 10+0.9(0)-(-0.725) = 10.725 — far larger than anything seen so far. The critic updates V(S2)0.725+0.5(10.725)=4.6375V(S_2) \leftarrow -0.725+0.5(10.725) = 4.6375. The actor, starting from step 3's θ(S2,right)=0.3625\theta(S_2,\text{right})=0.3625 (policy πright0.674\pi_{\text{right}}\approx0.674), updates to θ(S2,right)0.3625+0.5(10.674)(10.725)2.11\theta(S_2,\text{right}) \leftarrow 0.3625+0.5(1-0.674)(10.725) \approx 2.11 — the actor and critic correcting course together, in the same step.

Checkpoint

Step forward until you're standing at state 2 and the actor favors "right" with more than half the probability.

S0
S1
S2
S3
step 1/6
Step forward to try it
Summary
δ=r+γV(s)V(s),θiθi+α(1[i=a]πθ(i))δ\delta = r + \gamma V(s') - V(s), \qquad \theta_i \leftarrow \theta_i + \alpha\big(\mathbb{1}[i{=}a] - \pi_\theta(i)\big)\,\delta

Actor-critic keeps REINFORCE's direct policy gradient but replaces its noisiest ingredient — the raw return — with a TD error computed by a value function learned alongside it. Both halves are simple, familiar algorithms from earlier chapters, run in parallel and coupled through one shared number. The next chapter takes this same clipped-nowhere update and adds one more piece of machinery: a hard limit on how far a single gradient step is allowed to move the policy at all.