Chapter 7 · Deep RL for control: DQN to SAC and PPO
§7.4 Off-policy actor-critic: DDPG, TD3, SAC
Drafted June 19, 2026·~2,000 target words·Prereqs: §7.3 (PPO's on-policy constraint — every batch is discarded after a few epochs — and why that is unaffordable when samples are expensive); §7.2 (the actor-critic split, policy gradients, the deterministic vs. stochastic policy distinction); §7.1 (the argmax-over-continuous-actions obstacle, the replay buffer and target network from DQN); §5.3 (Q-learning, the Bellman target, exploration); §3.4 (loss families)
Section 7.3 ended on a complaint disguised as a fact. PPO is on-policy:
after it sweeps a batch for its handful of epochs, the data is stale and
must be thrown away. On a fast simulator that is fine, because samples
are nearly free. On a real robot it is close to fatal — every transition
is a slow, wear-inducing, possibly destructive physical interaction, and
collecting the millions of them PPO wants is not an option. What we need
is a method that keeps every transition it has ever seen and squeezes
many gradient updates out of each one. That is the promise of off-policy
learning, and the family that delivers it for continuous control is the
off-policy actor-critic: DDPG, its hardened successor TD3, and the
maximum-entropy variant SAC that is now the default reach-for algorithm
when sample efficiency matters.
The idea: marry Q-learning to a policy network
Recall the two obstacles. Q-learning (§5.3, §7.1) is beautifully
off-policy — it learns from a replay buffer of transitions collected by
any policy, because its Bellman target r+γmaxa′Q(s′,a′)
depends only on the transition, not on who chose the action. But that
maxa′ is an optimization over the action space, and in a
continuous space — a seven-joint arm with a six-dimensional torque
vector — you cannot enumerate actions to maximize over them. Policy
gradients (§7.2) sidestep the argmax by parameterizing the policy
directly, but the vanilla version is on-policy and sample-hungry.
Deterministic Policy Gradient (DPG; Silver et al. 2014) and its deep
incarnation DDPG (Lillicrap et al. 2016, arXiv:1509.02971) fuse the two.
The trick is to replace the intractable maxa′Q(s′,a′) with a
learned maximizer: train a deterministic actor network
μϕ(s) whose job is to output the action that maximizes the
critic. Then the Bellman target becomes
y=r+γQθ(s′,μϕ(s′)),
with no maximization to solve — the actor is the approximate argmax.
The critic Qθ is trained by ordinary temporal-difference
regression toward y (the same squared-error Bellman loss as DQN). The
actor is trained to push its output in whatever direction makes the
critic’s estimate larger, which is just gradient ascent on the critic
through the action input:
∇ϕJ=Es∼D[∇aQθ(s,a)a=μϕ(s)∇ϕμϕ(s)].
Read that chain rule carefully, because it is the whole method. The
gradient of the critic with respect to the action, ∇aQ, says
“to raise the Q-value, nudge the action this way”; the actor Jacobian
∇ϕμ then translates that desired action-nudge into a
weight update. Because both terms are computed on states s sampled
from the replay buffer D — states collected by old policies
— the whole scheme is off-policy. DDPG inherits DQN’s two stabilizers
wholesale: a replay buffer that decorrelates samples and lets each
transition be reused many times, and slowly-updated target networksQθ′ and μϕ′ that supply the bootstrap target y so
the regression is not chasing a target that moves in lockstep with the
weights being trained. DDPG’s target networks use a soft update,
θ′←τθ+(1−τ)θ′ with τ≈0.005, rather than DQN’s periodic hard copy.
Exploration needs a separate mechanism, because a deterministic actor
left alone always emits the same action in a given state and never tries
anything new. DDPG handles this by adding noise to the actor’s output at
collection time — a=μϕ(s)+N — and storing the
noisy action in the buffer. The original paper used temporally
correlated Ornstein-Uhlenbeck noise; later work found plain Gaussian
noise works as well or better, which is one less moving part.
TD3: DDPG that does not lie to itself
DDPG works, when it works, but it earned a reputation for being
fragile — wildly sensitive to hyperparameters, prone to a return curve
that climbs promisingly and then collapses. The diagnosis, made precise
by Fujimoto et al. (2018, arXiv:1802.09477), is overestimation bias.
The actor is trained to maximize the critic, so it actively seeks out
whatever actions the critic happens to overvalue; those errors then
feed straight into the next Bellman target through Q(s′,μ(s′)), get
bootstrapped forward, and compound. The critic, in effect, believes its
own most optimistic mistakes, and the actor chases them off a cliff.
TD3 — Twin Delayed DDPG — is DDPG plus three targeted fixes, and it is
worth knowing them individually because each addresses a distinct
failure and each shows up again in SAC.
The first is clipped double-Q learning. Train two independent critics
Qθ1,Qθ2 and form the Bellman target using the
minimum of the two:
y=r+γi=1,2minQθi′(s′,a~).
Taking the min is a deliberate pessimism. Two critics will not
overestimate the same action in the same way, so the smaller of the two
is a conservative estimate that systematically counteracts the upward
bias. It can underestimate instead, but underestimation does not get
chased and amplified the way overestimation does, so the trade is heavily
favorable.
The second is target policy smoothing. The action a~ in the
target above is not μϕ′(s′) exactly but that action plus a
small clipped noise: a~=μϕ′(s′)+clip(ϵ,−c,c). The reasoning is that a good action
should have a similar value to its near neighbors; without smoothing, a
critic can develop a sharp, spurious spike at one action that the
deterministic actor then exploits. Averaging the target over a little
noise around the action regularizes those spikes away. This is a
regularizer on the value target, not on exploration — a subtle but
important distinction.
The third is delayed policy updates. Update the actor (and the target
networks) less often than the critics — typically once every two critic
updates. The point is to let the critic settle toward an accurate
estimate before the actor takes a step that depends on it; chasing a
noisy, half-trained critic is what produces the thrashing. The three
fixes together turn DDPG from a method you coax into working into one
that trains reliably on standard MuJoCo benchmarks, and TD3 remains a
strong, simple baseline.
SAC: reward entropy, not just return
Soft Actor-Critic (Haarnoja et al. 2018, arXiv:1801.01290) keeps the
off-policy, replay-buffer, twin-critic skeleton but changes the
objective itself. Where every method so far maximizes expected return,
SAC maximizes return plus the entropy of the policy:
J(π)=t∑E[rt+αH(π(⋅∣st))].
The temperature α sets the exchange rate between reward and
randomness. The reframing has real consequences. The policy is now
stochastic — it outputs a distribution, typically a squashed Gaussian,
rather than a single action — and it is rewarded for staying as random as
it can while still collecting return. This bakes exploration directly
into the objective instead of bolting it on as injected noise the way
DDPG and TD3 do: the agent explores because spreading probability mass is
literally part of what it is maximizing. It also tends to learn more
robust policies, because a high-entropy policy that still succeeds cannot
be relying on one brittle sequence of actions.
Mechanically, SAC borrows TD3’s clipped double-Q (it had a version of the
idea concurrently) and adds the entropy bonus to the critic’s target:
The actor is trained with the reparameterization trick — sample
a=tanh(μϕ(s)+σϕ(s)⊙ξ) with ξ∼N(0,I) — so the gradient of the expected (Q minus
log-probability) objective flows back through the sampled action into
the network, exactly the pathwise gradient used in §3.2’s discussion of
reparameterization. The single most consequential practical refinement
came shortly after: rather than tune α by hand, make it automatic
by treating it as a dual variable and adjusting it to hold the policy’s
entropy near a target value (a reasonable default target is −dim(a),
the negative of the action dimension). With automatic temperature, SAC
has remarkably few knobs to turn, which is much of why it became the
default.
The following sketch shows the off-policy update loop the three methods
share; the bracketed comments mark where they diverge.
for step in range(total_steps): a = actor.act(s, explore=True) # DDPG/TD3: mu(s)+noise; SAC: sample s2, r, done = env.step(a) buffer.add(s, a, r, s2, done) # off-policy: keep everything s = env.reset() if done else s2 batch = buffer.sample(256) # reuse old transitions with torch.no_grad(): a2 = target_actor(batch.s2) # SAC: sample + entropy term a2 = a2 + clip_noise(a2) # TD3 only: target smoothing q_tgt = torch.min(qt1(batch.s2, a2), qt2(batch.s2, a2)) # twin min y = batch.r + gamma * (1 - batch.done) * q_tgt update_critics(batch, y) # TD-regression for Q1, Q2 if step % policy_delay == 0: # TD3: delayed; SAC/DDPG: every step update_actor(batch) # ascend Q through the action soft_update(targets, tau=0.005)
How to choose, and what comes next
The pattern across the three is a steady accretion of pessimism and
self-regularization on top of one core trick — a learned actor standing
in for the continuous argmax. DDPG is the foundational idea but fragile
in practice. TD3 is DDPG made trustworthy with three small, well-motivated
fixes, and it is a fine choice when you want a deterministic policy and
minimal conceptual overhead. SAC is the one to default to: its
maximum-entropy objective gives principled exploration and robustness,
its automatic temperature removes the most painful hyperparameter, and
on continuous-control benchmarks it is reliably as sample-efficient as
or better than TD3. All three crush PPO on sample efficiency — often by
an order of magnitude in environment steps to reach a given performance
— which is exactly the property you want when those steps are expensive.
That sample efficiency is why off-policy actor-critic, and SAC in
particular, is the workhorse behind much of the learning-on-real-hardware
literature, and why its replay-buffer logic reappears inside the
offline-RL and Q-learning-flavored components of some later
action-generation methods. It also sets up the central tension of robot
RL: even SAC’s “order of magnitude fewer samples” is still tens of
thousands of real interactions, which is tens of thousands too many for
most robots. The usual escape — train in a simulator where samples are
cheap, then transfer to hardware — brings its own problem, the reality
gap, which §7.5 takes up under the heading of domain randomization.
This section has been read
—
times.
References
Lillicrap, Hunt, Pritzel, Heess, Erez, Tassa, Silver & Wierstra (2016). Continuous control with deep reinforcement learning (DDPG). ICLR. arXiv:1509.02971.