AI-330 · Lesson 7 of 12 · 27 min

Function approximation and deep RL

The tabular methods of Lessons 3 and 5 store a separate value for every state or state-action pair. That is impossible when states are numerous or continuous: the positions and velocities of a robot's joints, the pixels of a video game screen, the temperatures and flows of a cooling plant. Even if a table could be stored, most states would never be visited, so the agent must generalize from the states it has seen to similar ones it has not. Function approximation replaces the table with a parameterized function, from linear models on hand-designed features to deep neural networks. This lesson covers value function approximation, the gradient-based learning rules, feature construction, the stability problems known as the deadly triad, deep Q-networks and their refinements, and model-based and offline RL.

Value function approximation

The value function is represented as \(\hat v(s, \mathbf w)\) with a weight vector \(\mathbf w\) much smaller than the number of states. Changing one weight changes the estimated values of many states, which is how the approximation generalizes, and also why it cannot be exact everywhere. The natural objective is the mean squared value error, weighted by how often each state is visited under the policy, \(\mu(s)\):

\[\overline{\mathrm{VE}}(\mathbf w) = \sum_s \mu(s)\big[v_\pi(s) - \hat v(s, \mathbf w)\big]^2\]

Stochastic gradient descent on this objective, with the unknown \(v_\pi(S_t)\) replaced by a target \(U_t\), gives the update

\[\mathbf w \leftarrow \mathbf w + \alpha\big[U_t - \hat v(S_t, \mathbf w)\big]\nabla_{\mathbf w}\hat v(S_t, \mathbf w)\]

With the Monte Carlo return as the target, \(U_t = G_t\), this is true stochastic gradient descent and converges to a local minimum of the value error. With the TD target \(U_t = R_{t+1} + \gamma\hat v(S_{t+1}, \mathbf w)\), the target itself depends on \(\mathbf w\), but the update ignores that dependence; it is therefore called semi-gradient TD. Semi-gradient methods are not true gradient methods, but they usually learn faster and work online, and for linear approximation with on-policy data they converge reliably.

Linear methods

In linear function approximation, each state is described by a feature vector \(\mathbf x(s)\) and \(\hat v(s, \mathbf w) = \mathbf w^\top\mathbf x(s)\), so the gradient is simply \(\mathbf x(s)\). Linear semi-gradient TD(0) converges, on-policy, to the TD fixed point, whose value error is at most \(1/(1 - \gamma)\) times the smallest error achievable by any weight vector. The quality of the result therefore depends on the features:

  • State aggregation groups states and gives each group one weight: a one-hot feature for the group.
  • Tile coding overlays several offset grids (tilings) on a continuous state space; each state activates one tile per tiling, giving a sparse binary feature vector that generalizes to nearby states and is very cheap to compute. It was the workhorse of RL for robotics and control before deep learning.
  • Radial basis functions, polynomial and Fourier bases give smooth features.
  • Learned features from neural networks, the subject of deep RL.
Semi-gradient TD(0) with state aggregation on a 1000-state random walk
import numpy as np

# 1000-state random walk: start in the middle, jump uniformly 1 to 100 states left or right;
# leaving on the left gives reward -1, on the right +1. Undiscounted.
N = 1000
P = np.zeros((N, N)); b = np.zeros(N)
for s in range(N):
    for d in list(range(-100, 0)) + list(range(1, 101)):
        s2 = s + d
        if s2 < 0: b[s] += -1 / 200
        elif s2 >= N: b[s] += 1 / 200
        else: P[s, s2] += 1 / 200
true_v = np.linalg.solve(np.eye(N) - P, b)          # exact values for comparison

rng = np.random.default_rng(0)
def run_td(groups, episodes=3000, alpha=0.01):
    w = np.zeros(groups); size = N // groups
    for _ in range(episodes):
        s = 500
        while True:
            d = int(rng.integers(1, 101)) * (1 if rng.random() < 0.5 else -1)
            s2 = s + d
            g = s // size
            if s2 < 0 or s2 >= N:
                r = -1.0 if s2 < 0 else 1.0
                w[g] += alpha * (r - w[g])
                break
            w[g] += alpha * (w[s2 // size] - w[g])      # semi-gradient TD(0) with one-hot group features
            s = s2
    return np.repeat(w, size)

for groups in [5, 10, 50]:
    v = run_td(groups)
    print(f"{groups:3d} groups ({groups} weights): RMS error vs true values = {np.sqrt(np.mean((v - true_v) ** 2)):.3f}")
print(f"true values at states 100, 500, 900: {true_v[100]:.3f}, {true_v[500]:.3f}, {true_v[900]:.3f}")
Output
  5 groups (5 weights): RMS error vs true values = 0.294
 10 groups (10 weights): RMS error vs true values = 0.137
 50 groups (50 weights): RMS error vs true values = 0.089
true values at states 100, 500, 900: -0.752, 0.001, 0.754

With only five groups, each weight covers 200 states whose true values range widely, so the approximation is coarse. Ten and fifty groups reduce the error considerably, at the cost of more weights to learn. Within each group the estimate is a constant, a staircase approximation of the smooth true value function; better features, such as tile coding or polynomials, would fit the curve with few weights.

Plot of state value against state number from 1 to 1000. The true value function is a smooth S-shaped curve from minus 0.8 at the left to plus 0.8 at the right. Two staircase approximations are overlaid: one with 10 steps and one with 50 steps, the latter following the curve more closely.
State aggregation approximates the smooth true value function by a staircase.

Control with function approximation

For control, the action-value function is approximated as \(\hat q(s, a, \mathbf w)\), and semi-gradient SARSA or Q-learning updates \(\mathbf w\) with the corresponding TD errors. For discrete actions, a network often outputs one value per action from the state. For continuous actions, maximizing over actions is itself an optimization problem, which is one reason continuous control uses actor-critic methods (Lesson 9).

The deadly triad

Combining three ingredients can make learning unstable, with values diverging to infinity even in simple problems:

  • Function approximation, which generalizes across states.
  • Bootstrapping, which updates toward targets built from current estimates.
  • Off-policy training, in which the distribution of updates differs from the distribution the target policy would generate.

Any two are safe: tabular methods can bootstrap off-policy, Monte Carlo with function approximation does not bootstrap, and on-policy linear TD converges. All three together can diverge. The classic demonstration is Baird's counterexample, a seven-state MDP with all rewards zero, where the correct answer is trivially zero values, yet off-policy semi-gradient TD drives the weights to infinity.

Baird's counterexample: off-policy semi-gradient TD diverges; on-policy updates remain stable
import numpy as np

# Baird counterexample: 7 states, 8 weights, all rewards zero, so the true values are all 0.
X = np.zeros((7, 8))
for i in range(6):
    X[i, i] = 2; X[i, 7] = 1                  # upper states: v = 2 w_i + w_8
X[6, 6] = 1; X[6, 7] = 2                      # lower state:  v = w_7 + 2 w_8
gamma, alpha = 0.99, 0.01
w0 = np.array([1, 1, 1, 1, 1, 1, 10, 1], float)

def expected_td(off_policy, sweeps=1000):
    w = w0.copy()
    for k in range(1, sweeps + 1):
        v = X @ w
        if off_policy:
            # behaviour: uniform over states; target policy always goes to the lower state (7);
            # importance ratio is 7 for the solid action, 0 for dashed, solid chosen with prob 1/7
            delta = gamma * v[6] - v                 # TD error under the target policy
            w += alpha * (X.T @ delta) / 7           # semi-gradient, states weighted uniformly
        else:
            # on-policy: states visited in proportion to the target policy (all mass on state 7)
            delta = gamma * v[6] - v[6]
            w += alpha * delta * X[6]
        if k in (1, 10, 100, 1000):
            tag = "off" if off_policy else "on "
            print(f"{tag}-policy, sweep {k:4d}: |w| = {np.linalg.norm(w):12.2f}")
expected_td(True)
expected_td(False)
Output
off-policy, sweep    1: |w| =        10.37
off-policy, sweep   10: |w| =        10.61
off-policy, sweep  100: |w| =        16.83
off-policy, sweep 1000: |w| =       436.86
on -policy, sweep    1: |w| =        10.34
on -policy, sweep   10: |w| =        10.33
on -policy, sweep  100: |w| =        10.21
on -policy, sweep 1000: |w| =         9.42

Off-policy, the weight norm grows without bound even though every reward is zero, because updates are made from states the target policy never visits, and the generalization through shared weights then pushes up the value the target policy's own state bootstraps from. On-policy updates remain bounded. Remedies include gradient-TD methods that perform true gradient descent on a projected Bellman error, emphatic TD, and, in deep RL, the practical stabilizers of DQN described next.

Venn diagram of three overlapping circles labelled function approximation, bootstrapping and off-policy training. Each pairwise overlap is labelled stable. The central region where all three overlap is labelled the deadly triad: possible divergence.
The deadly triad: any two are manageable; all three together can diverge.

Deep Q-networks

In 2015, the deep Q-network (DQN) learned to play 49 Atari 2600 games from raw pixels and the score, reaching human-level performance on many, with the same network architecture and hyperparameters for every game. DQN is Q-learning with a convolutional neural network approximating \(Q(s, a)\), and it confronts the deadly triad head-on. Two ideas made it work:

  • Experience replay: transitions \((s, a, r, s')\) are stored in a large buffer (one million in the original), and each update uses a random mini-batch from it. This breaks the strong correlations between consecutive samples, which would otherwise violate the assumptions of stochastic gradient descent, and reuses each experience many times, improving data efficiency.
  • Target network: the TD target is computed with a separate copy of the network whose weights \(\mathbf w^-\) are updated only periodically (every 10,000 steps in the original) or slowly averaged. This stops the target from chasing the network being trained, reducing oscillation and divergence.

The loss minimized for each mini-batch is

\[L(\mathbf w) = \mathbb{E}_{(s,a,r,s') \sim \mathcal D}\Big[\big(r + \gamma\max_{a'} Q(s', a'; \mathbf w^-) - Q(s, a; \mathbf w)\big)^2\Big]\]

often with the Huber loss instead of the square to limit the effect of large errors, and with rewards clipped to a fixed range.

Architecture diagram of a deep Q-network. Stacked recent game frames enter convolutional layers, then fully connected layers, ending in one output per action giving its Q value. Below, the training loop: the agent acts epsilon-greedily in the environment, stores transitions in a replay buffer, samples random mini-batches, and computes targets with a separate target network that is periodically copied from the online network.
DQN: a convolutional Q-network trained from a replay buffer against a slowly updated target network.

Improvements to DQN

  • Double DQN uses the online network to choose the best next action and the target network to evaluate it, removing much of the maximization bias of Lesson 5.
  • Dueling networks split the output into a state value and action advantages, \(Q(s, a) = V(s) + A(s, a) - \bar A(s)\), which helps when many actions have similar values.
  • Prioritized replay samples transitions with large TD errors more often, with importance weights to correct the bias.
  • Multi-step returns, distributional RL (learning the distribution of returns rather than its mean) and noisy networks for exploration.

The Rainbow agent combined these and roughly doubled DQN's median performance on Atari. Later agents reached superhuman scores on all 57 Atari games.

Worked problem

DQN target computation

A transition has reward 1 and is not terminal. The online network gives \(Q(s', \cdot; \mathbf w) = (2.0, 3.5, 3.0)\) and the target network gives \(Q(s', \cdot; \mathbf w^-) = (2.2, 2.8, 3.4)\). With \(\gamma = 0.99\), compute the DQN and double DQN targets.

Show solution
  1. DQN: \(1 + 0.99 \times \max(2.2, 2.8, 3.4) = 1 + 0.99 \times 3.4 = 4.37\).
  2. Double DQN: the online network chooses action 2 (value 3.5); the target network evaluates it at 2.8; target \(1 + 0.99 \times 2.8 = 3.77\).

Answer: DQN 4.37 and double DQN 3.77. Because the two networks disagree about the best action, the double estimate is lower, counteracting the upward bias of maximizing over noisy estimates.

Model-based RL

Model-free methods can need millions of interactions. Model-based methods learn a model of the environment's dynamics and rewards from experience and use it to plan or to generate simulated experience. Dyna interleaves real steps with many simulated updates from the learned model. AlphaZero combines a learned value and policy network with Monte Carlo tree search using the known rules of chess and Go; MuZero extends this by learning the model itself in a latent space, reaching superhuman play in board games and strong Atari performance without knowing the rules. World-model approaches, such as the Dreamer agents, learn compact latent dynamics and train policies inside the model. Model-based methods are far more data-efficient, but model errors can be exploited by the planner, so they must be handled carefully.

Offline RL

In many applications, such as healthcare, industrial control or data centre operations, exploring with a poor policy on the real system is unacceptable, but large logs of past operation exist. Offline (batch) RL learns policies from such fixed datasets without further interaction. It is off-policy learning at its most extreme: naive Q-learning on logged data overestimates the values of actions the data never tried, because nothing corrects the errors. Offline methods therefore constrain the learned policy to stay close to the data (behaviour-regularized methods) or penalize values of unfamiliar actions (conservative Q-learning). Evaluating a new policy from logged data before deploying it, called off-policy evaluation, uses importance sampling (AI-320) and model-based estimates.

Practical deep RL

Deep RL is notoriously sensitive. Results can vary widely between random seeds, small implementation details matter, and rewards that are badly scaled or sparse slow learning drastically. Good practice is to normalize observations and rewards, start from well-tested implementations, report results over many seeds with confidence intervals, monitor value estimates for divergence, and begin with simple baselines. When a good simulator exists, massive parallel simulation makes many problems tractable; when it does not, model-based and offline methods and careful reward design matter most. Real deployments, such as RL-based control of data centre cooling, typically add safety constraints, human oversight and fallback to conventional controllers.

Lesson 8 develops two of the directions listed here, exploration and distributional RL, and Lesson 10 treats model-based and offline RL in depth.

Common mistakes

  • MistakeTreating semi-gradient TD as true gradient descent.

    InsteadIts target depends on the weights; it is stable on-policy with linear features but can diverge in the deadly triad.

  • MistakeTraining a Q-network on consecutive samples with a moving target.

    InsteadUse experience replay and a target network to decorrelate samples and stabilize targets.

  • MistakeReporting deep RL results from a single seed.

    InsteadPerformance varies widely between seeds; report averages and intervals over many runs.

  • MistakeRunning plain Q-learning on logged data.

    InsteadOffline RL must constrain the policy or penalize unseen actions to avoid overestimation.

  • MistakeTrusting a learned model blindly for planning.

    InsteadPlanners exploit model errors; account for model uncertainty.

Summary and key terms

  • Function approximation generalizes values across states with far fewer parameters than states.
  • Gradient MC is true SGD on the value error; semi-gradient TD ignores the target's dependence on weights.
  • Linear on-policy TD converges to the TD fixed point, within 1/(1 − γ) of the best possible error.
  • Features: state aggregation, tile coding, basis functions, learned neural features.
  • The deadly triad of function approximation, bootstrapping and off-policy training can diverge (Baird's counterexample).
  • DQN stabilizes deep Q-learning with experience replay and a target network.
  • Double DQN, dueling networks, prioritized replay and distributional RL improve DQN (Rainbow).
  • Model-based RL (Dyna, MuZero, world models) improves data efficiency; offline RL learns from fixed logs with conservatism.
Function approximation
Representing value functions or policies with parameterized functions.
Mean squared value error
The visit-weighted squared difference between true and estimated values.
Semi-gradient method
A TD update that differentiates the estimate but not the bootstrapped target.
TD fixed point
The weights to which linear on-policy TD converges.
State aggregation
Grouping states to share one estimated value.
Tile coding
Sparse binary features from multiple offset grids over the state space.
Deadly triad
Function approximation, bootstrapping and off-policy training together, which can diverge.
Deep Q-network
Q-learning with a deep neural network, replay and a target network.
Experience replay
Storing transitions and training on random mini-batches from the buffer.
Target network
A slowly updated copy of the network used to compute TD targets.
Dueling network
A Q-network that separates state value and action advantages.
Prioritized replay
Sampling transitions with large TD errors more often.
Model-based RL
RL that learns or uses a model of the environment to plan.
Offline RL
Learning policies from fixed datasets without interaction.

Practice problems

Work each problem on paper first, then reveal the answer to check.

  1. Why can't a table be used for a robot arm with continuous joint angles?

    Show answer

    There are infinitely many states, most never visited; generalization from visited states is required.

  2. Write the linear semi-gradient TD(0) update.

    Show answer

    w ← w + α[R + γ wᵀx(S′) − wᵀx(S)] x(S).

  3. With x(S) = (1, 0, 1), x(S′) = (0, 1, 1), w = (0.5, 0.2, 0.1), R = 1, γ = 0.9 and α = 0.1, compute the updated w.

    Show answer

    v(S) = 0.6, v(S′) = 0.3; δ = 1 + 0.27 − 0.6 = 0.67; w = (0.567, 0.2, 0.167).

  4. Why is gradient MC a true gradient method but semi-gradient TD not?

    Show answer

    The MC target G_t does not depend on w; the TD target does, and the update ignores that dependence.

  5. With γ = 0.9, what bound does theory give on the TD fixed point error relative to the best achievable error?

    Show answer

    At most 1/(1 − 0.9) = 10 times.

  6. Name the three elements of the deadly triad.

    Show answer

    Function approximation, bootstrapping, off-policy training.

  7. What two problems does experience replay address?

    Show answer

    Correlated consecutive samples and poor data efficiency (each transition is reused).

  8. Why does DQN use a target network?

    Show answer

    To keep the TD target fixed for a while, so the network is not chasing a moving target, which reduces oscillation and divergence.

  9. Online Q(s′, ·) = (1, 4, 3), target Q(s′, ·) = (2, 3, 5), r = 0, γ = 0.9. Compute the DQN and double DQN targets.

    Show answer

    DQN 0.9 × 5 = 4.5; double DQN: online chooses action 2, target value 3, giving 2.7.

  10. Why is offline RL harder than ordinary off-policy RL?

    Show answer

    The agent cannot gather new data to correct overestimated values of actions absent from the dataset.

Lesson quiz · 5 questions

Score 60% or more to complete this lesson.

Take the quiz