Deep Q Learning: Deep Q-Learning

Deep Q Learning : Guide Complet — Q-Learning Profond

Deep Q Learning: Complete Guide — Deep Q-Learning

Summary — The Deep Q-Network (DQN), introduced by DeepMind in 2015, is a reinforcement learning algorithm that replaces the Q-table of classic Q-learning with a deep neural network. This innovation enables handling massive state spaces (images, continuous sensors) that cannot be represented in a discrete table. The DQN achieved superhuman performance on 49 Atari games by learning directly from raw pixels, marking a revolution in the field of reinforcement learning.


Mathematical Principle

1. Q-function Approximation with a Neural Network

In classic Q-learning, a table stores Q(s, a) for each (state, action) pair. But if the state is a 210×160 RGB image, there are 256^(210×160×3) possible states — a table is impossible.

The DQN uses a neural network as an approximator:

Q(s, a; w) ≈ Q*(s, a)

where w are the network weights. The network takes the state s as input and produces a Q-value for each available action at the output.

2. Loss Function

The objective is to minimize the error between the predicted Q-value and the Bellman target:

L(w) = E[(r + γ · max_a’ Q(s’, a’; w-) – Q(s, a; w))²]

Where:
– r: immediate reward
– γ: discount factor (typically 0.99)
– s’: next state
– w-: target network weights (frozen copy)
– Q(s, a; w): Q-value predicted by the main network

3. Target Network

The fundamental problem of Q-learning with nonlinear approximation is instability: the Q target depends on the same weights being updated, creating a negative feedback loop (like training a network on data that changes at every step).

The solution: use a target network — a frozen copy of the weights that is updated periodically (every C iterations):

w- ← w (every C iterations)

This stabilizes the target for C steps, allowing learning to converge.

4. Experience Replay

The second problem is the correlation between successive samples: transitions (s, a, r, s’) are highly correlated because they come from a continuous trajectory.

Experience replay stores transitions in a fixed-size buffer and samples randomly (mini-batch) for training:

  1. At each step, store (s, a, r, s’, done) in the buffer
  2. When the buffer contains enough samples, draw a random mini-batch
  3. Compute the loss and update the weights

This breaks temporal correlations and reuses past experiences (more efficient).

5. Advanced Variants

Double DQN (2016): Reduces overestimation of Q-values by using the main network to select the action and the target network to evaluate it:

Q_target = r + γ · Q(s’, argmax_a’ Q(s’, a’; w); w-)

Dueling DQN (2016): Separates the estimation of the state value V(s) and the action advantage A(s, a):

Q(s, a) = V(s) + A(s, a) – mean(A(s, ·))

This architecture learns more efficiently in states where the choice of action doesn’t matter.

Prioritized Experience Replay: Samples transitions with high TD error more frequently, as they contain more information to learn.


Intuition

Imagine a video game player learning to play Space Invaders without knowing the rules.

The DQN does three things:

  1. It looks at the screen: each frame is preprocessed (resized to 84×84, stacked over 4 frames to capture motion) and passed through a CNN that extracts key features (alien positions, ship, bullets).
  2. It decides what to do: the network produces a Q-value for each possible action (left, right, shoot). It chooses either the action with the best Q, or a random action (exploration).
  3. It learns from its mistakes: each action produces a reward (+1 for killing an alien, -1 for dying, 0 otherwise). The network adjusts its predictions to match the immediate reward plus the best predicted future reward.

Experience replay is its memory: instead of forgetting each game, it stores key moments (first death, dangerous alien pattern, winning strategy) and replays them randomly during training. It’s like the human brain consolidating memories during sleep by replaying the day’s experiences.

The target network is its stable reference: instead of correcting itself against its own constantly-changing predictions, it uses an older version of itself as a reference point. It’s like a student comparing progress to a benchmark exam taken last month rather than to their own fluctuating estimates.


Python Implementation

1. DQN on CartPole with TensorFlow/Keras

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import gymnasium as gym
from collections import deque
import random

# Hyperparameters
GAMMA = 0.99
EPSILON = 1.0
EPSILON_MIN = 0.01
EPSILON_DECAY = 0.995
LEARNING_RATE = 0.001
BUFFER_SIZE = 10000
BATCH_SIZE = 64
TARGET_UPDATE_FREQ = 100
N_EPISODES = 500

# Environment
env = gym.make("CartPole-v1")
state_dim = env.observation_space.shape[0]  # 4
action_dim = env.action_space.n  # 2

# Replay buffer
buffer = deque(maxlen=BUFFER_SIZE)

# Main network
def build_model():
    model = keras.Sequential([
        layers.Dense(64, activation="relu", input_shape=(state_dim,)),
        layers.Dense(64, activation="relu"),
        layers.Dense(action_dim, activation="linear")
    ])
    model.compile(optimizer=keras.optimizers.Adam(learning_rate=LEARNING_RATE),
                  loss="mse")
    return model

q_network = build_model()
target_network = build_model()
target_network.set_weights(q_network.get_weights())

# Function to choose an action (epsilon-greedy)
def choose_action(state, epsilon):
    if random.random() < epsilon:
        return env.action_space.sample()  # exploration
    q_values = q_network.predict(np.array([state]), verbose=0)
    return np.argmax(q_values[0])  # exploitation

# Training
scores = []
step_count = 0

for episode in range(N_EPISODES):
    state, _ = env.reset()
    done = False
    total_reward = 0

    while not done:
        action = choose_action(state, epsilon)
        next_state, reward, terminated, truncated, _ = env.step(action)
        done = terminated or truncated

        # Store in buffer
        buffer.append((state, action, reward, next_state, done))

        state = next_state
        total_reward += reward
        step_count += 1

        # Train if buffer is full enough
        if len(buffer) >= BATCH_SIZE:
            # Random sample
            batch = random.sample(buffer, BATCH_SIZE)
            states = np.array([b[0] for b in batch])
            actions = np.array([b[1] for b in batch])
            rewards = np.array([b[2] for b in batch])
            next_states = np.array([b[3] for b in batch])
            dones = np.array([b[4] for b in batch])

            # Compute targets
            q_next = target_network.predict(next_states, verbose=0)
            q_values = q_network.predict(states, verbose=0)

            for i in range(BATCH_SIZE):
                target = rewards[i]
                if not dones[i]:
                    target += GAMMA * np.max(q_next[i])
                q_values[i][actions[i]] = target

            q_network.fit(states, q_values, epochs=1, verbose=0)

            # Periodically update target network
            if step_count % TARGET_UPDATE_FREQ == 0:
                target_network.set_weights(q_network.get_weights())

    # Decay epsilon
    epsilon = max(EPSILON_MIN, epsilon * EPSILON_DECAY)
    scores.append(total_reward)

    if episode % 50 == 0:
        print(f"Episode {episode} | Score: {total_reward} | "
              f"Epsilon: {epsilon:.3f}")

print(f"Training complete. Average score last 100: "
      f"{np.mean(scores[-100:]):.1f}")

2. Double DQN (minimal modification)

# Double DQN: separate selection and evaluation
def compute_double_dqn_targets(batch):
    next_states = np.array([b[3] for b in batch])
    rewards = np.array([b[2] for b in batch])
    dones = np.array([b[4] for b in batch])

    # Main network selects the best action
    q_next_main = q_network.predict(next_states, verbose=0)
    best_actions = np.argmax(q_next_main, axis=1)

    # Target network evaluates that action
    q_next_target = target_network.predict(next_states, verbose=0)
    best_q_values = q_next_target[np.arange(len(batch)), best_actions]

    targets = rewards + GAMMA * best_q_values * (1 - dones)
    return targets

Hyperparameters

Hyperparameter Typical Value Description
learning_rate 0.0001-0.001 Learning rate for the Adam optimizer
gamma 0.95-0.99 Discount factor (higher = more long-term vision)
batch_size 32-128 Mini-batch size for experience replay
buffer_size 10,000-1,000,000 Maximum replay buffer size
epsilon_start 1.0 Initial exploration (100% random)
epsilon_min 0.01-0.1 Minimum exploration after decay
epsilon_decay 0.99-0.999 Rate of exploration reduction
target_update_freq 100-10,000 q_network → target_network copy frequency

Advantages of DQN

  1. Handling continuous state spaces: Unlike tabular Q-learning, the DQN handles states of any dimension (images, sensors)
  2. Learning from scratch: No manual features needed; the network learns to extract the right representations
  3. Proven: DeepMind’s DQN surpassed humans on the majority of Atari games in 2015
  4. Foundation of the deep RL ecosystem: All modern advances (A3C, PPO, SAC) build on concepts introduced by the DQN

Limitations of DQN

  1. Q-value overestimation: The max operator tends to overestimate values (partially resolved by Double DQN)
  2. Sensitive to hyperparameters: Tuning requires experience and many trials
  3. Sample inefficient: Requires millions of environment interactions to converge
  4. Discrete only: The classic DQN only handles discrete action spaces. For continuous actions, different algorithms are needed (DDPG, SAC, TD3)

4 Concrete Use Cases

1. Atari Games and Video Games

The historical case: DeepMind trained a single DQN algorithm on 49 different Atari games (Pong, Breakout, Space Invaders) learning from raw pixels and score alone. The same algorithm achieved superhuman performance on the majority of games.

2. Algorithmic Trading

A DQN can learn trading strategies by interacting with a market simulator. States contain technical indicators (RSI, MACD, volumes), actions are buy/sell/hold, and rewards are realized profits. The DQN learns to maximize returns while managing risk.

3. Data Center Optimization

Google used deep reinforcement learning to optimize cooling in its data centers. A DQN learns to adjust air conditioning settings (temperature, airflow) to minimize energy consumption while keeping servers at safe temperatures, reducing the energy bill by 40%.

4. Autonomous Robot Navigation

A mobile robot uses a DQN to learn to navigate in an unknown environment. States come from LiDAR/camera sensors, actions are movement commands, and rewards penalize collisions and reward progress toward the target. Learning in simulation enables millions of trials without material risk.


Conclusion

The Deep Q-Network is the bridge between classical reinforcement learning and modern deep learning. By replacing the Q-table with a neural network and introducing experience replay and the target network, it solved the two main obstacles of deep reinforcement learning: the curse of dimensionality and training instability.

Although more recent algorithms like PPO and SAC have surpassed the DQN on many benchmarks, it remains an essential educational starting point and an effective solution for discrete action environments.


See Also


About Salah YAHIAOUI

Salah YAHIAOUI publie sur The Pingouin des tutoriels Python et des décryptages sur l’intelligence artificielle. Les cas pratiques récents précisent leurs données, leurs tests et leurs limites. À propos, méthode éditoriale et contact.

View all posts by Salah YAHIAOUI →