← All tutorials

Training DDPG: Target Networks, Replay and Noise

Three stabilizers keep DDPG's two updates from diverging, and one full update shows them working together.

This page builds on Deep Deterministic Policy Gradient (DDPG): Actor and Critic, which teaches the actor, the critic and their two updates.

Run alone, those two updates diverge. The critic chases its own guesses, it learns from runs of nearly identical steps, and the deterministic actor never tries anything new. Three stabilizers each stop one failure (Figure 1): slow target copies hold the critic's target still, a replay buffer mixes old and new steps, and smooth noise makes the actor explore. One training update then runs all five of its parts, and the arm trains.

The running example is the Reacher arm of the RF-DDPG repo, which reads 33 numbers and outputs 4 torques in [−1, 1] every step and earns +0.1 while the hand is on the target. Twenty arms train in parallel, and the task counts as solved when their mean score, averaged over 100 episodes, reaches 30.

Slow target networks live critic moves fast 0.1% per update target critic barely moves prevents the critic chasing its own guesses Replay buffer steps in order step 99 ≈ step 100 store, then sample replay buffer state, torque, reward, next state random minibatches prevents overfitting to recent steps Ornstein-Uhlenbeck noise deterministic actor same state, same torques + noise white noise: jitter OU noise: smooth prevents repeating one action forever

Figure 1. Each stabilizer prevents one failure.

The critic update trains the critic toward a target value.

The target copies set a target value for each move, and the live critic is trained to match it.
y = r + γ·Q′(s′, μ′(s′))
From the next state s′, the target actor μ′ picks the next torques and the target critic Q′ scores them. The target y is the reward r plus the discount γ times that score, and the live critic Q(s, a) is pulled toward y for the move a it took in state s. The primes mark the target copies of Section 1.1.

The actor update moves the actor's torques the way the critic scores higher.

The actor changes its weights so its torques move the way that raises the critic's score.
∇θJ ≈ E[∇aQ(s, μ(s)) · ∇θμ(s)]
∇ is the gradient, the direction of steepest increase. ∇aQ says which way the torques should move to raise the critic's score, and ∇θμ says how the actor μ changes its torques when its weights θ change. Their product, averaged by E over a batch of states, is the gradient of J, the critic's average score of the actor's torques.

On this page

1 Target networks, replay buffer and noise 2 One DDPG training update 3 The Reacher training run 4 DDPG in practice 5 DDPG failure modes 6 TD3, SAC and multi-agent DDPG 7 References

1 Target networks, replay buffer and noise

1.1 Target networks

The critic's target is built from its own predictions, so if the critic changes fast, its target changes fast too. Slow target copies of both networks follow the live ones instead.

After each update, the target weights move a tiny fraction of the way toward the live weights.
θ′ ← τθ + (1−τ)θ′
The arrow means "is replaced by": the target weights θ′ become a blend of a share τ of the live weights θ and the rest, 1−τ, of their own. With τ a tenth of a percent, each target weight moves only a hair per update, so the target value in the critic card barely moves between steps. A larger τ tracks the live networks faster and brings back the moving target; τ = 1 copies them outright.

soft_update applies the card's blend to every weight: t.lerp_(p, TAU) sets t to t + TAU * (p - t), which is the card's line. It runs once for the critic pair and once for the actor pair.

TAU = 1e-3

@torch.no_grad()
def soft_update(tgt, live):
    dst = list(tgt.parameters())
    src = list(live.parameters())
    for t, p in zip(dst, src):
        t.lerp_(p, TAU)

soft_update(critic_target, critic)
soft_update(actor_target, actor)

Deep Q-Networks (DQN) copied its target network in full every 10,000 updates (Mnih et al., 2015); DDPG makes the copy continuous and small.

1.2 Replay buffer

Each arm's consecutive steps are nearly identical, so learning from them in order overfits the latest moment; random minibatches mix old and new.

Every transition from every arm, with its episode-end flag done, goes into one memory, and training samples random minibatches from it. Random sampling breaks the link between consecutive steps, each transition is reused many times, and twenty arms fill the buffer twenty times faster than one. Deep Q-Networks (DQN) uses the same buffer.

import random
from collections import deque

BUFFER_SIZE, BATCH = 100_000, 256
buf = deque(maxlen=BUFFER_SIZE)
step = (s, a, r, s_next, done)
buf.append(step)
batch = random.sample(buf, BATCH)

1.3 Ornstein-Uhlenbeck noise

A deterministic actor left alone repeats its first guess forever, so during training DDPG adds Ornstein-Uhlenbeck (OU) noise to the torques. Gaussian (white) noise is independent every step, so torques stutter; OU noise remembers its last value and is pulled back toward zero, so it wanders smoothly (Figure 2).

white noisenew every stepOU noisekeeps most of its last value
Figure 2. Same random kicks, same size: white noise jumps every step, OU noise drifts.
During training a smooth random wander around zero is added to the actor's torques to explore.
x ← x − κ·x + σ·ξ
x is the noise, one value per torque, and it carries over from step to step. The term κ·x pulls it back toward zero, harder the further it has wandered. σ sets the size of each fresh kick, and ξ is a new standard normal random number every step. Because x keeps most of its last value, consecutive steps drift together instead of twitching; a larger κ makes the wander shorter, a larger σ makes it wider. The DDPG paper and the repo use κ = 0.15 (the paper calls it θ) and σ = 0.2.
a = μ(s) + x
The torques sent to the arm are the actor's output μ(s) plus the noise x. Noise is on during training, so the arm tries nearby torques the actor would not choose, and typically off at test time, so the arm gives the same torque every time for the same state.

For an arm with inertia (a moving part keeps moving), smooth noise tries coherent strategies ("push left for a while, see what happens") instead of vibrating in place. The DDPG paper chose OU noise for this reason, and the repo keeps it.

2 One DDPG training update

One training update has five parts: sample, compute the target, update the critic, update the actor, update the targets. This is off-policy learning: the networks learn from experience gathered by older versions of the actor, which is why the replay buffer can be reused.

Figure 3. Live networks learn every update; target copies follow slowly.

In one DDPG training update the target network sets the target value, the critic measures its error, the actor climbs the critic's slope, and the target networks move slowly toward the live networks.
y = r + γ·Q′(s′, μ′(s′))
From the next state, the target actor picks the next move, then the target critic evaluates that pair. The target y is the reward just seen plus the discounted value of that pair. It comes from the target networks so it holds still while the critic learns.
loss = E[(y − Q(s,a))²]
The critic's step pushes down E, the average over the batch of the squared gap between the target value and the live critic's guess for the move actually taken. Averaging limits the effect of one odd transition, and squaring makes big mistakes count more than small ones.
∇θJ ≈ E[∇aQ(s, μ(s)) · ∇θμ(s)]
The actor moves its weights so its torques raise the score: how the score changes with the torques, at the actor's own torques, times how the torques change with the weights, averaged over the batch. The step is approximate because the actor climbs the critic, a learned model, not the real return; the environment has no gradient, and the critic supplies one.
θ′ ← τθ + (1−τ)θ′
The target weights become a blend of a share τ of the live weights and the rest, 1−τ, of their own. Each update moves them a tenth of a percent of the way toward the live values, so the targets stay stable.
y the target valueQ′ the target critic; μ′ the target actorr the rewardγ the discount; s′ the next stateQ(s,a) the live critic's guess for state s and torques aE the average over the batch; loss the critic's error² squared∇θJ the actor's uphill step; μ the live actor∇aQ which way the torques should move∇ gradient: direction of steepest change; ≈ approximately· timesθ the live weightsθ′ the target weightsτ the soft-update share← is replaced by

3 The Reacher training run

A toy two-joint arm shows what training changes (Figure 4); the real run is the RF-DDPG repo on the Unity ML-Agents Reacher task, with the settings in Figure 5.

toy episode score at this stage
0.0 (solved at 30) Reward this step 0.0

Figure 4. A toy 2D arm; as training goes on, the hand settles on the target.

Setting and repo valueRaising itLowering it
Arms, state, torques
20; 33 in, 4 out
fixed by the Reacher task
Layers
actor 256, 128, 64, tanh; critic 256, +4, 128, 64
more capacity, slowercheaper, may underfit
Replay buffer
100,000
more varied, adapts slowerforgets faster, batches alike
Batch
256
steadier, more computecheaper, noisier
Updates
64 per 256 steps
more reuse; critic can overfitcheaper, slower
Adam learning rate
1e-3 for both
faster; the critic can divergesteadier, slower
Discount γ
0.99
far rewards count moreγ = 0 sees only the next reward
Target update τ
1e-3
faster, less stable; τ = 1 copiessteadier; τ = 0 freezes
Critic clip norm
1
larger steps; huge turns it offsteadier, slower
OU pull κ
0.15
tighter wanderlonger drifts
OU kick σ
0.2
wider, noisier torquesnarrower; 0 stops exploring
Figure 5. Reacher settings in the RF-DDPG repo and their effects.
01020304004080120160episodescoresolved at 3012
Figure 6. ① first 30; ② episode 162, where the 100-episode average reaches 30.11 (solved).

One arm's score varies a lot from episode to episode. Twenty arms, each with its own exploration noise, average that variation out (Figure 6 plots their mean score) and fill the buffer with more varied experience.

4 DDPG in practice

The repo runs one update function 64 times every 256 environment steps, a quarter of an update per step, with the settings in Figure 5; Stable-Baselines3 has a widely used PyTorch DDPG. Each update costs two target forward passes, a critic forward and backward pass, an actor pass through the critic, and two weight blends. Memory is dominated by the buffer: 100,000 transitions of 33 + 4 + 1 + 33 + 1 = 72 numbers each is about 29 MB at 4 bytes per number, while the four networks (two live, two target) hold about 200,000 weights, under 1 MB.

ddpg_update runs one update on a sampled batch, using the actor and critic built in the actor and critic networks section of Deep Deterministic Policy Gradient (DDPG): Actor and Critic, their target copies and their optimizers.

import torch
import torch.nn.functional as F
import torch.nn.utils as U

GAMMA, TAU, CLIP = 0.99, 1e-3, 1.0
pairs = [(actor_target, actor),
         (critic_target, critic)]

@torch.no_grad()
def soft_update(tgt, live):
    dst = list(tgt.parameters())
    src = list(live.parameters())
    for t, p in zip(dst, src):
        t.lerp_(p, TAU)

@torch.no_grad()
def td_target(r, s_next, done):
    a2 = actor_target(s_next)
    q2 = critic_target(s_next, a2)
    keep = 1 - done
    return r + GAMMA * q2 * keep

def ddpg_update(batch):
    s, a, r, s_next, done = batch
    y = td_target(r, s_next, done)
    q = critic(s, a)
    critic_loss = F.mse_loss(q, y)
    critic_opt.zero_grad()
    critic_loss.backward()
    U.clip_grad_norm_(
        critic.parameters(), CLIP)
    critic_opt.step()
    q = critic(s, actor(s))
    actor_loss = -q.mean()
    actor_opt.zero_grad()
    actor_loss.backward()
    actor_opt.step()
    for tgt, live in pairs:
        soft_update(tgt, live)
  1. 1Sets the constants, pairs each target network with its live network, and defines soft_update.
  2. 2Builds the target y from the target networks; keep is 0 at the end of an episode (update card in Section 2, line 1).
  3. 3Critic step on the loss in line 2, with gradient clipping.
  4. 4Actor step up the critic's score (line 3).
  5. 5Soft-updates both target networks (line 4).

Three mistakes break this update.

5 DDPG failure modes

6 TD3, SAC and multi-agent DDPG

TD3 and SAC each change the target from One DDPG training update (Section 2).

TD3 (Twin Delayed DDPG, Fujimoto et al., 2018) changes DDPG's target in two ways and its schedule in one. It adds a little noise, kept within a small range, to the next torques, and it scores them with two slow target critics and keeps the lower score, so one critic's lucky high guess cannot lift the target. It also updates the actor and the slow copies less often than the critics, so the actor climbs a critic that has had time to settle.

The full TD3 update, worked on one Reacher step, is on Continuous-Action Actor-Critic: TD3 and SAC.

SAC (Soft Actor-Critic, Haarnoja et al., 2018) keeps the policy random and rewards it for spreading its choices (high entropy), so exploration lives in the objective instead of in added OU noise, and the critic's target carries that payment. The same page teaches it in SAC pays for spread.

Multi-agent DDPG is taught on Multi-Agent Reinforcement Learning, where one shared actor and critic drive both rackets of a tennis game (self-play). The MADDPG paper (Lowe et al., 2017) instead gives each agent its own actor and its own centralized critic, which sees every agent's observations and actions.

DDPG fits continuous actions, a cheap simulator, and a controller that should act with no noise at test time, the same torque every time for the same state; for a short list of discrete actions, DQN fits better.

7 References

  1. Mnih, V., et al. (2015). Human-level control through deep reinforcement learning. Nature 518, 529 to 533. doi:10.1038/nature14236.
  2. Lillicrap, T. P., et al. (2016). Continuous Control with Deep Reinforcement Learning. ICLR. arXiv:1509.02971.
  3. Fujimoto, S., et al. (2018). Addressing Function Approximation Error in Actor-Critic Methods. ICML. arXiv:1802.09477.
  4. Haarnoja, T., et al. (2018). Soft Actor-Critic: Off-Policy Maximum Entropy Deep Reinforcement Learning with a Stochastic Actor. ICML. arXiv:1801.01290.
  5. Lowe, R., et al. (2017). Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments. NeurIPS. arXiv:1706.02275.