iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
AI Engineering

從零訓練到瀏覽器部署:30 天打造 Atari Breakout 強化學習 AI系列 第 10

Day 10|探索與利用:讓 Agent 不只相信目前最大的 Q-value

  • 分享至 

  • xImage
  •  

Day 8 的 DQN 已經能把一個 Breakout state 轉成每個 action 的 Q-values,Day 9 也把遊戲互動產生的 transition 存進 Replay Buffer。

現在還差一個很重要的問題:拿到 Q-values 之後,Agent 到底要選哪個 action?

直覺上,好像直接選 Q-value 最大的 action 就行了。但訓練剛開始時,這些 Q-values 還只是很不成熟的估計。如果 Agent 太早相信目前最大的值,它可能從此只重複同一類行為,根本沒有機會發現其他 action 其實更好。

反過來,如果每一步都隨機選 action,雖然什麼都會試到,卻又完全沒有利用模型已經學到的資訊。

這就是強化學習裡很重要的 Exploration vs. Exploitation(探索與利用)

  • Exploration(探索):故意去試目前還不確定的 action;
  • Exploitation(利用):使用目前已知資訊,選 Q-value 最大的 action。

Day 10 要做的事情,就是用 epsilon-greedy 在兩者之間取得一個簡單、可控制的平衡。

只做 argmax,Agent 可能永遠看不到其他選擇

利用的做法很直接:從所有 Q-values 中選最大值。這個操作叫 argmax

假設目前四個 action 的 Q-values 是:

[1.0, 2.0, 5.0, 3.0]

那麼 action index 2 的 Q-value 最大,所以 greedy action 就是 2

問題是:Q-value 是目前模型的估計,不是真正答案。

如果訓練剛開始時,模型碰巧高估某個 action,而 Agent 又永遠只執行 argmax,那麼其他 action 就很少有機會被執行。沒有新的互動,就沒有新的 transition;沒有那些 transition,模型也很難知道自己原本的判斷可能是錯的。

所以 argmax 沒有算錯,它只是只回答:

以目前的估計來看,哪個 action 最大?

它不會主動去回答:

我是不是還漏掉了更好的選擇?

另一個極端是每一步都 random。這樣確實能探索不同 action,但當 Agent 已經慢慢學到一些有用資訊後,仍然完全不使用它,互動效率會很差。

Epsilon-greedy:有時探索,有時相信目前的 Q-value

Epsilon-greedy 的想法很簡單:每次要選 action 時,先做一次隨機判斷。

  • epsilon 的機率走 random branch,隨機選一個 action;
  • 1 - epsilon 的機率走 greedy branch,選 Q-value 最大的 action。

epsilon 是一個 01 之間的數字。

例如:

epsilon 行為
0 完全不探索,每次都 greedy
0.1 約 10% 的決策走 random branch
0.5 約一半 random、一半 greedy
1 每次都走 random branch

所以 epsilon 不是拿來和 Q-value 比大小的門檻。它只是在控制:這一次到底要走 random 還是 greedy。

一次 action selection 的資料流如下:

Epsilon-greedy 從 Q-values、epsilon schedule 到 random 或 greedy action 的決策分支

圖中的重點不是某一局 Breakout 發生了什麼,而是每一次決策都會先經過同一個分岔:要嘛探索,要嘛利用,最後才把選出的 action 交給 environment。

如果兩個 action 剛好有一樣大的最高 Q-value,這個版本固定選索引比較前面的 action。這樣同樣的 Q-values 每次都會得到同一個 greedy action,不會因為 tie 而出現額外的隨機性。

用真實抽樣結果看懂 epsilon

現在再回頭看實際程式跑出來的結果會比較有意義。

固定 Q-values:

[1.0, 2.0, 5.0, 3.0]

其中 action 2 是 greedy action。使用 seed 42 後:

epsilon = 0, samples = 20
greedy action index : 2
random decisions    : 0
greedy decisions    : 20
action 2            : 20

epsilon = 1, samples = 20
greedy action index : 2
random decisions    : 20
greedy decisions    : 0
action counts       : [6, 4, 6, 4]

epsilon = 0.1, samples = 1000
random decisions    : 96
greedy decisions    : 904
action counts       : [29, 31, 925, 15]

前兩組很好理解:

  • epsilon = 0 時,20 次全部走 greedy;
  • epsilon = 1 時,20 次全部走 random。

比較有意思的是 epsilon = 0.1

理論上每一次有 10% 機率走 random branch,所以 1,000 次裡大約會有 100 次 random。實際得到 96 次,這只是有限次隨機抽樣下很正常的波動。

但還有一個更重要的細節:random branch 不代表一定會選到「非 greedy action」。

這裡一共有四個 action。即使這次決定要 random,仍然有 1/4 的機率剛好又抽到 action 2

所以當 epsilon = 0.1 時,action 2 最後被執行的理論機率不是 90%,而是:

greedy branch 選到 action 2
= 90%

random branch 又剛好抽到 action 2
= 10% × 1/4
= 2.5%

合計
= 92.5%

而這次實際結果剛好是:

action 2 = 925 / 1000 = 92.5%

這能幫我們分清楚兩件常被混在一起的事:

  • epsilon 控制的是 random branch 的機率
  • 最後某個 action 被執行的機率,還要把 random branch 可能抽到同一個 action 算進去。

Epsilon 不會永遠維持同一個值

固定 epsilon = 0.1 當然可以運作,但訓練早期和訓練後期其實不需要同樣程度的探索。

訓練剛開始時,Agent 幾乎還不知道哪些 action 比較好,所以需要多試不同選擇。隨著經驗增加,才逐漸把更多決策交給目前學到的 Q-values。

因此 Day 10 使用 linear epsilon schedule(線性 epsilon 排程),讓 epsilon 隨著 environment step 逐漸下降。

這裡的 environment step 指的是 Agent 執行一次 action,環境回傳一次 transition。使用 step 而不是 episode,是因為每一局 Breakout 的長度可能不同;用互動次數來衡量探索進度會比較一致。

這次圖表使用:

start       = 0.9
end         = 0.05
decay_steps = 1000

也就是從 90% 的 random branch 機率,逐步下降到 5%。

由 LinearEpsilonSchedule 實際產生的 epsilon 與 random/greedy 分支機率

幾個時間點可以直接看出變化:

environment step epsilon random branch greedy branch
0 0.900 90% 10%
500 0.475 47.5% 52.5%
1,000 0.050 5% 95%
1,200 0.050 5% 95%

在 step 0 時,Agent 幾乎都在探索;到了 step 1,000,epsilon 已經降到 0.05,之後就維持在這個最低值,不再繼續下降。

這張圖只能告訴我們「探索比例怎麼變」,不能證明模型已經學會 Breakout。0.9 → 0.05 也是這次示範使用的設定,不是唯一正確答案;真正適合多快下降,還要等完整訓練後再用 evaluation 比較。

Epsilon-greedy 會直接影響 Replay Buffer 裡有什麼

Day 9 的 Replay Buffer 負責保存 transition,但它不會自己創造新的經驗。資料仍然來自 Agent 和 Breakout 的互動:Agent 先選 action,environment 執行後產生 transition,最後才把這筆 transition 放進 Replay Buffer。

因此 epsilon-greedy 決定的不只是「Agent 下一步按哪個按鍵」,它也會間接決定 Replay Buffer 最後收集到什麼資料。

如果 Agent 從來沒有探索某些 action,那些 action 對應的遊戲結果就很少出現在 Replay Buffer 裡。後面的 DQN 即使能反覆抽樣 Replay Buffer,也無法憑空學到一段從來沒有被收集過的互動。

所以 Day 9 和 Day 10 解決的是兩個不同但連在一起的問題:

  • Experience Replay:過去的經驗怎麼保存、重複利用;
  • Epsilon-greedy:新的經驗要怎麼在探索與利用之間被收集出來。

Epsilon schedule 和 Replay warm-up 不是同一件事

還有一個很容易混淆的設定叫 replay warm-up,也常寫成 learning_starts

它和 epsilon schedule 控制的是完全不同的事情:

機制 它回答的問題
epsilon schedule 這一步要用 random 還是 greedy 方式選 action?
replay warm-up Replay Buffer 累積多少資料後,才開始更新模型?

換句話說,epsilon schedule 影響的是資料怎麼收集;replay warm-up 影響的是什麼時候開始拿資料訓練

因此「前 10,000 步先不要訓練」不等於「前 10,000 步一定完全 random」。兩個條件可以分開設定,真正把它們串進完整 training loop 會留到 Day 12。

選 action 的時候不需要計算 gradient

DQN 產生 Q-values 之後,epsilon-greedy 只是根據這些值決定下一個 action。這個過程是在使用目前的模型做決策,不是在更新模型。

PyTorch 訓練時會保存一些中間計算,之後才能根據 loss 反向調整模型參數;這個用來追蹤計算關係的機制,就是 gradient graph。

但 action selection 不需要之後回頭算梯度,所以這裡會使用 torch.no_grad(),避免保留不必要的訓練資訊。

真正需要 gradient 的時候,是之後從 Replay Buffer 抽出一批 transition,計算模型的預測誤差,再用這個誤差更新 network。那會在後面的 training loop 才正式串起來。

固定 seed 是為了分辨「設定改變」和「剛好抽到不同亂數」

Epsilon-greedy 本身有隨機性。如果每次實驗都使用不同亂數序列,就很難判斷結果差異到底來自:

  • epsilon 或程式真的改了;
  • 還是這次只是剛好抽到不同 action。

因此這個專案會明確傳入隨機數產生器(random number generator),並使用固定 seed 做可重現的 inspection。

相同的 Q-values、epsilon、action 數量與 seed,會產生相同的 random / greedy 決策序列。這讓我們比較容易驗證程式行為。

但 seed 只負責讓隨機過程可重現,不會讓錯誤的 Q-value 自動變正確

Day 10 把「怎麼選 action」這一層接起來了

走到這裡,Agent 已經有一條比較完整的互動資料路徑:DQN 先根據目前 state 產生 Q-values,epsilon-greedy 再決定這一步要探索還是利用,選出的 action 交給 Breakout,產生的新 transition 最後再進入 Replay Buffer。

Day 10 解決的是 action selection,還沒有真正開始訓練 DQN。

真正開始更新 network 後,還會遇到另一個問題:模型一邊學,拿來當作「學習答案」的估計值也跟著一直變,這會讓訓練變得不穩定。

Day 11 會用 Target Network 把這個問題拆開。


上一篇
Day 9|Experience Replay:把遊戲經驗存起來,再隨機拿回來學
下一篇
Day 11|Target Network:別讓 DQN 的學習目標每一步都跟著自己跑
系列文
從零訓練到瀏覽器部署:30 天打造 Atari Breakout 強化學習 AI17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言