Q‑Learning 是一種「模型無關」(model‑free)的強化學習演算法,用來在不知道環境轉移機率的情況下,透過反覆試誤學出在每個狀態下應該採取哪個動作可以讓長期累積回報最大化。

核心概念

  • 在強化學習裡,我們有「狀態 ss」、「動作 aa」、「回饋/獎勵 rr」、「折扣因子 γγ」,以及 agent 與環境反覆互動的過程。
  • Q‑Learning 不需要環境模型(例如 P(ss,a)P(s′∣s,a)),而是直接學一個 action‑value 函數 Q(s,a)Q(s,a):代表在狀態 ss 下採取動作 aa,之後按照最優策略行動時的期望累積回報。
  • 通常用一個 Q‑table(或在連續空間時用 NN 近似)來存這些 Q(s,a)Q(s,a) 值,agent 在決策時就查表選擇 Q 值最大的動作(或做 ε‑greedy 探索)。

更新規則(Bellman 方程)

每次互動一步 s,a,r,ss,a,r,s′ 後,Q‑Learning 用 Bellman optimality 的 TD 更新:

  • 直觀版口頭描述:
    • 取目前的 Q(s,a)Q(s,a)。
    • 用「立即獎勵 rr + 折扣後的下一狀態最大 Q 值 γmaxaQ(s,a)γmaxa′​Q(s′,a′)」當成新的目標。
    • 兩者差叫做 TD error,乘上學習率 αα 加回去,更新 Q(s,a)Q(s,a)。
  • 反覆套用這個更新,在合適的探索策略與學習率條件下,Q‑Learning 可以收斂到最優 Q 函數,因此也間接學到最優策略(對每個狀態選 Q 最大的動作)。

特點與應用直覺

  • Off‑policy:更新時是看「下一步可能的最佳動作」的回報,不一定是實際走的動作,因此即使用隨機或 exploratory policy 探索,也能學到最優策略。
  • 優點:實作簡單、不需要環境模型,適用於離散狀態/動作空間的小到中型問題,例如網格世界、簡單遊戲、routing 控制等。
  • 延伸:當狀態空間太大時,就會發展成 Deep Q‑Learning(DQN),用深度網路近似 Q 函數,而不是明確存整張 Q‑table。

如果你想,我可以下一步直接給你一個超短的 Python 實作範例(tabular Q‑learning)當作 template。

由深度研究準備

一個超短的 Python 實作範例(tabular Q‑learning)當作 template。

下面是一個「最小可用」的 tabular Q‑learning Template,用 Gymnasium 的 FrozenLake(離散狀態/動作)示範,你可以直接改成任何離散環境。

import numpy as np
import gymnasium as gym

env = gym.make("FrozenLake-v1", is_slippery=False)  # 離散 state/action 環境
n_states = env.observation_space.n
n_actions = env.action_space.n

Q = np.zeros((n_states, n_actions))  # Q-table

alpha = 0.1      # learning rate
gamma = 0.99     # discount factor
epsilon = 0.1    # ε-greedy
n_episodes = 2000
max_steps = 100

def epsilon_greedy_action(state):
    if np.random.rand() < epsilon:
        return env.action_space.sample()          # explore
    return np.argmax(Q[state])                    # exploit

for ep in range(n_episodes):
    state, _ = env.reset()
    for t in range(max_steps):
        action = epsilon_greedy_action(state)
        next_state, reward, terminated, truncated, _ = env.step(action)
        done = terminated or truncated

        # Q-learning 更新
        best_next = np.max(Q[next_state])
        td_target = reward + gamma * best_next
        td_error = td_target - Q[state, action]
        Q[state, action] += alpha * td_error

        state = next_state
        if done:
            break

# 測試:用學到的 Q-table 玩一回
state, _ = env.reset()
done = False
while not done:
    action = np.argmax(Q[state])
    next_state, reward, terminated, truncated, _ = env.step(action)
    state = next_state
    done = terminated or truncated
    env.render()
print("Episode reward:", reward)

如果你要改成自己的離散環境,只要:

  • 把 env = gym.make(...) 換成你的環境。
  • 確保有 observation_space.n / action_space.n(或自己定義離散編碼),其餘核心 Q‑learning loop 基本可以原樣沿用。