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

Deep Q-Networks (DQN)

Hook

Q-learning's table had exactly one number for every state-action pair — completely fine for a 4-state corridor, hopeless for a state space too large to enumerate (a screen of pixels, say). What if Q(s,a)Q(s,a) were computed by a tiny function instead of looked up in a table?

Intuition
S0
S1
S2
S3
step 1/6: at S0, took "right" → S1, reward -1

Same 4-state gridworld, same 6-move script Q-learning used — but instead of a table entry, Q(s,a)Q(s,a) now comes from a network with exactly 6 numbers: one hidden unit feeding two output values, one per action. Step through the same moves and watch those 6 numbers get nudged by gradient descent, using the exact same TD-error signal Q-learning used.

Formalize

A Deep Q-Network replaces the table with a function Q(s,a;θ)Q(s,a;\theta), trained by gradient descent on the squared TD error:

L(θ)=(r+γmaxaQ(s,a;θ)Q(s,a;θ))2\mathcal{L}(\theta) = \Big(r + \gamma \max_{a'} Q(s',a';\theta^-) - Q(s,a;\theta)\Big)^2
  • θ\theta — the online network's parameters, the ones being trained right now.
  • θ\theta^- — the target network's parameters: a frozen, periodically-refreshed copy of θ\theta.
  • Q(s,a;θ)Q(s,a;\theta) — the online network's current prediction for state-action pair (s,a)(s,a).
  1. This is Q-learning's TD error, squared into a loss

    The parenthesized term is exactly the same TD error from the Q-learning chapter. DQN just treats it as a regression target and takes a gradient step against it, instead of nudging a table entry directly by α×\alpha \times error.

  2. Why a separate target network at all?

    If θ=θ\theta^-=\theta, the target moves every time θ\theta does — the network would be chasing a target it just changed, one gradient step ago. Freezing θ\theta^- for a stretch of steps (only periodically copying θ\theta into it) gives the online network a stable target to regress toward, instead of an ever-shifting one.

  3. Experience replay, in one sentence

    Real DQN also stores past transitions in a buffer and samples random past experience for each update, instead of training only on the transition just seen — this breaks the strong correlation between consecutive steps that plain online updates would otherwise have. The toy script here is too short to need it, but every update it runs has the exact same shape as one replay-buffer sample.

Play

A table needs one slot for every state times every action — double the state count, and it doubles in size. The network's parameter count never moves: the same 6 numbers that handled 4 states could, in principle, be asked to handle 1000. Whether they'd generalize well is a separate question — but they don't run out of room the way a table eventually would.

Worked example

Starting from Qθ(0,right)=2Q_\theta(0,\text{right})=-2 (computed from the network's initial 6 numbers), with learning rate 0.050.05:

  1. Step 1 — a clean TD error of exactly 1

    Taking "right" from state 0 lands on state 1 with reward 1-1. Since θ=θ\theta^-=\theta still at this point, the target network's best action-value at state 1 happens to be exactly 00 (max(Q(1,left),Q(1,right))=max(0,1)=0\max(Q(1,\text{left}), Q(1,\text{right})) = \max(0,-1) = 0), so the target is 1+0.9(0)=1-1 + 0.9(0) = -1. TD error =1(2)=1= -1 - (-2) = 1, loss =1=1. The hidden unit is inactive at state 0 (h=max(0,1×0+0)=0h=\max(0, 1\times0+0)=0), so Qθ(0,right)=wright×0+brightQ_\theta(0,\text{right})=w_{\text{right}}\times0+b_{\text{right}} depends only on the output bias — the weight's gradient is 2×1×h=0-2\times1\times h=0, but the bias's gradient is 2×1×1=2-2\times1\times1=-2. Gradient descent: bright20.05×(2)=1.9b_{\text{right}} \leftarrow -2 - 0.05\times(-2) = -1.9 — a small step toward the target, the same shape as a Q-table update but landing on a shared parameter instead of an isolated cell.

  2. Step 3 — a 'left' move with zero TD error

    Taking "left" from state 2 happens to produce a target that already exactly matches the current prediction (both 1-1) — TD error 00, loss 00, and the left-branch weights don't move at all this step. Zero error means zero gradient, exactly like a reward of 00 left the softmax policy untouched in the REINFORCE chapter.

  3. Step 4 — the target network has just re-synced

    After step 3, the target network copies the online network's weights. Step 4's target computation now uses those freshly-updated numbers instead of the original initialization — the "moving target" problem is kept in check by only letting it move in these periodic jumps, not on every single step.

Checkpoint

Step forward until the training loss drops below 0.05 — the network's prediction is nearly matching its bootstrapped target.

S0
S1
S2
S3
step 1/6 — loss = 1.0000
Step forward to try it
Summary
L(θ)=(r+γmaxaQ(s,a;θ)Q(s,a;θ))2\mathcal{L}(\theta) = \Big(r + \gamma \max_{a'} Q(s',a';\theta^-) - Q(s,a;\theta)\Big)^2

DQN keeps Q-learning's exact update signal — a TD error bootstrapped off the best next action — but hands it to a network trained by gradient descent instead of a table updated in place. A target network keeps the bootstrap target from chasing itself, and (in practice) experience replay keeps updates from over-fitting to whatever just happened. The next chapter moves away from value-based learning entirely, going back to a directly-learned policy — but this time paired with a value function that helps it learn faster.