Q-Learning
Q-learning estimates the value of taking each action in each state without needing a model of the environment, converging to the optimal action-value function by bootstrapping off its own past estimates.
Why Does This Exist?
Most real-world problems don't give you the transition model or reward function in closed form — you can only observe the outcomes of actions you actually take. Q-learning is model-free: it learns optimal action values purely from experience, without ever knowing the environment dynamics.
This is the key breakthrough: you don't need to know how the world works. You just need to interact with it.
Think of It Like This
Learning which moves win at chess by playing
You learn to play chess not by memorizing a complete game tree, but by playing thousands of games and remembering which positions tended to lead to wins. After enough games, your estimate of how good each position is becomes accurate. Q-learning does exactly this: maintain a running estimate of how valuable each action is in each state, and update that estimate after every move based on what actually happened.
How It Actually Works
The Q-function
The Q-function estimates the expected discounted return of taking action in state , then following the optimal policy thereafter. The optimal Q-function satisfies the Bellman optimality equation:
If we know , the optimal policy is simply: in state , take .
The Q-update rule
After observing transition :
The TD error is the difference between the bootstrapped target () and the current estimate. A positive TD error means the current estimate is too low — increase it. A negative error means it's too high — decrease it. is the learning rate.
Off-policy learning
Q-learning is off-policy: the target uses (the greedy action) regardless of which action the agent actually took during exploration. This means the agent can explore with -greedy (taking random actions of the time) while still learning the optimal policy — the exploration policy and the target policy are decoupled.
Convergence guarantee
For tabular Q-learning with finite state-action spaces, converges to if:
- Every state-action pair is visited infinitely often.
- Learning rates satisfy (enough total learning) and (learning slows over time).
In practice: use a small constant (e.g., 0.1) and anneal from 1.0 to 0.01.
Code
import gymnasium as gymimport numpy as np
# ── Tabular Q-learning on FrozenLake ─────────────────────────────────────────env = gym.make("FrozenLake-v1", is_slippery=True, render_mode=None)num_states = env.observation_space.n # 16num_actions = env.action_space.n # 4
# Initialize Q-tableQ = np.zeros((num_states, num_actions))
# Hyperparametersalpha = 0.1 # learning rategamma = 0.99 # discount factorepsilon = 1.0 # initial exploration rateeps_min = 0.01 # minimum exploration rateeps_decay = 0.999
rewards_per_episode = []
for episode in range(10_000): state, _ = env.reset() total_reward = 0.0 done = False
while not done: # ε-greedy action selection if np.random.random() < epsilon: action = env.action_space.sample() # explore else: action = np.argmax(Q[state]) # exploit
next_state, reward, terminated, truncated, _ = env.step(action) done = terminated or truncated
# Q-update (Bellman target) td_target = reward + gamma * np.max(Q[next_state]) * (1 - int(terminated)) td_error = td_target - Q[state, action] Q[state, action] += alpha * td_error
state = next_state total_reward += reward
# Anneal exploration epsilon = max(eps_min, epsilon * eps_decay) rewards_per_episode.append(total_reward)
# Evaluation (greedy policy, no exploration)eval_rewards = []for _ in range(100): state, _ = env.reset() total = 0.0 done = False while not done: action = np.argmax(Q[state]) state, reward, terminated, truncated, _ = env.step(action) done = terminated or truncated total += reward eval_rewards.append(total)
print(f"Greedy policy win rate: {np.mean(eval_rewards):.1%}")print("\nLearned Q-values (action with highest Q per state):")print(np.argmax(Q, axis=1).reshape(4, 4)) # 0=L, 1=D, 2=R, 3=UWatch Out For
Overestimation bias in the Q-target
The target uses the maximum of noisy Q-estimates, which is systematically biased upward — the maximum of noisy values overestimates the true maximum. This overestimation accumulates and can cause instability or suboptimal convergence. Double Q-learning addresses this: use one network to select and a second network to evaluate , eliminating the bias.
Not visiting enough state-action pairs
Q-learning converges only when every state-action pair is visited sufficiently. With aggressive annealing, the agent commits to a nearly greedy policy before it has explored enough states. Monitor a visitation heatmap — if many states have near-zero visit counts when is already small, slow the annealing schedule.
The Quick Version
- Q-learning is model-free and off-policy: learns the optimal action-value function directly from experience.
- The Q-update: .
- Off-policy: the target uses the greedy action regardless of the exploration policy used during data collection.
- Tabular convergence guaranteed when all state-action pairs visited sufficiently with decaying learning rates.
- Doesn't scale to large/continuous state spaces → needs neural network approximation (DQN).