強化學習簡介(6)--DQN
我們在時序差分那篇討論到,時序差分可以在未知環境變化的情況下,利用窮舉行動、更新Q表的方式,找到各狀態最適合採取的行動組成最佳策略。他解決了動態規劃中,面對無法掌握環境狀態轉移會無法使用的缺點;也解決了蒙地卡羅中,如果回合沒有終止狀態會無法使用的缺點。
然而,時序差分也有問題需要處理。其一就是,必須知道每個狀態會採取的所有動作。我們在時序差分使用的例子,對於每個狀態,都是清楚知道有哪些動作的(a=0, a=1)。如果遇到不知道所有動作的狀況,或者有新加的動作,就無法使用時序差分。
另一個問題,是即使知道全部的動作,要更新Q表,也需要消耗大量的紀錄資源和時間。在使用的例子裡,僅僅是三個狀態、兩個行動,就用了六列表格。隨著狀態和動作增加,窮舉所需要紀錄和更新的量只會更多。所以,我們還需要一種方法,可以更好的處理「多狀態動作、無法列舉所有動作」的狀況。當然,原本時序差分的優勢也要保留才行。
這就是今天的主題:DQN。
原版DQN
DQN全名是deep Q network,基於Q learning的特色,但改用神經網路來逼近Q值。這邊先介紹一個概念:experience replay buffer(經驗暫存區)。這是一個用來應付無法列舉所有動作的方法,主要是建立一個暫存區,裡面放著代理人行動產生的狀態變化、和獲得的獎勵。這個區域空間有限,因此如果超過儲存空間時,會從最早開始記錄的項目刪除,然後補進最新的狀態變化、獎勵,稱為先進先出(first in first out)。
輸入神經網路的,是接觸時間狀態(s)、行動(a)、狀態轉移(s')、獎勵(r)。神經網路輸出Q值,會拿來跟當前的Q值()做比較,計算損失,再反向傳播更新神經網路參數。這邊考慮到連續數值的特性,損失函數我們用MSE(均方差)。可以寫成下式:
不過這裡很快就會遇到一個問題:從哪來?如果是直接用同一個神經網路,把s'代入,輸出Q值來當作,可能是一個方法。不過,老師課堂上有提到,這樣做損失函數的收斂會很不穩定。
解決的方法是複製一個一模一樣的神經網路,把代入這個神經網路得到,回來給訓練的神經網路調整參數用。這個被複製的神經網路不會更動參數,而訓練用的神經網路則持續進入下個狀態、行動,更新參數。一直到訓練一定量的資料之後,再把調整過一段時間的神經網路的參數,直接複製過來更新。這個複製品只定時更新,而且都是複製當前原本的神經網路的參數,通常叫這個複製品為目標網路(target network)。
損失函數MSE則寫成
其中來自目標網路,而則來自主網路。對照時序差分off policy的Q learning:
來看一個實際的例子好了:冰湖遊戲,有四種行動:a=0向左,a=1向下,a=2向右,a=3向上。掉到洞,獎勵為-1,回合結束。I為終止態,沒有獎勵。

- 建立神經網路:一個是主網路(),也是agent。另一個是目標網路()。,設定每訓練三次,就同步一次參數。,
- 收集資料:建立Replay buffer,格式:。batch size=2,每次抽取兩筆資料訓練。
- 第一回合:狀態A,代入主網路,計算四個行動個別Q值輸出。然後用貪婪策略選取行動,抽機率,所以選Q值最大的行動,假設是a=2,往右,狀態轉移至B,掉到洞,獎勵-1,回合結束。紀錄結果於replay buffer
- 第二回合:狀態A,代入主網路,一樣輸出Q值,這時抽機率,因此隨機選取行動得到a=1,往下,狀態轉移至D,得到獎勵1,繼續行動。紀錄結果於replay buffer
- 然後把狀態D代入主網路尋找Q值,重複一樣的動作,這次的行動a=2,往右,狀態轉移至E,得到獎勵1,繼續。記錄結果
- 此時replay buffer資料量已經超過batch size,可以抽樣了。假設抽到和兩筆,計算損失函數
(1) 第一個樣本,則需用目標網路計算。為E,代入目標網路,假設得到為5。則用主網路計算,這邊因為沒有實際模擬神經網路參數,所以只能假設運算值,實際上可以用程式模擬。為D,而,分別帶入主網路,得到。此樣本的損失為。
(2) 第二個樣本用一樣的方法計算,假設,而,則損失為。
(3) 不要忘了還要平方相加取平均之後才是本次抽樣的損失。,將其作為梯度,更新主網路參數。
- 繼續收集資料。剛剛停留在狀態E,所以把E代入更新後的主網路,這次得到行動為a=3向上,狀態轉移到B,獲得獎勵-1,回合結束。記錄在replay buffer
- 進行第二次訓練,再抽兩個樣本。這次抽到和,依照剛剛的方式計算損失為3.36,再更新主網路參數
- 再收集資料,初始狀態A,代入第二次更新的主網路,採取行動a=0往左,但左邊沒有狀態,因此停留在狀態A,獎勵為0。紀錄於replay buffer,但目前容量已滿,所以先進先出,把第一筆資料刪除,最後一筆放到最下面
- 第三次訓練,抽出和兩組,損失計算為2.15,更新主網路參數。這時達到訓練滿三次,將主網路參數同步到目標網路。
- 以此循環直到損失收斂,訓練完成。使用時,將狀態代入網路,每次選Q值最高的行動,串聯起來就是最佳策略。
Double DQN/Dueling DQN
這邊介紹兩個DQN的變體。先從double DQN開始。
Double DQN
和DQN的差異在損失函數。DQN的損失函數是
而double DQN的損失函數為
DQN的損失函數,下個狀態的Q值是以狀態代入目標網路,直接選Q值最大者。Double DQN的損失函數,下個狀態的Q值是以狀態代入主網路,選出Q值最大的那個行動之後,搭配狀態再一起代入目標網路,直接取值。那為什麼要改成這樣?原本DQN在挑選Q值時,是代入目標網路計算。這樣的缺點是,因為目標網路的參數更新比主網路慢,如果直接帶入去找最大Q值,有可能不是最新的結果(即在主網路和目標網路,促成最大Q值的行動並非同一個)。因此,先在主網路找到造成最大Q值的行動,再代到目標網路,會比較貼近一點。
Dueling DQN
優勢函數(advantage function)
一個狀態只有一個價值,但隨著採用不同的行動,會有不同的Q值。因此,把Q值扣除該狀態的價值,可以觀察出因為行動不同,帶來的純粹差異。
若獎勵高,Q值有可能比較高,優勢函數的值比較高。把所有行動的優勢值取平均,稱為平均優勢。
Dueling DQN
和DQN的差異主要在Q函數的計算方式。一直以來,Q函數的計算方式如上,即為優勢函數移項的結果。
在dueling DQN,Q函數的計算方式,在每一個動作的優勢函數要先剪去平均優勢之後,才能和價值相加,得到Q值。
Dueling DQN的神經網路分為兩部分:一部分計算V值(V stream),一部分計算A值(A stream)。A stream會先把每個動作的A值都算出來,進而求得平均優勢。最後有一層聚集層(aggregation layer),用來計算。
至於損失函數,則沒有限制。要使用DQN,或double DQN的損失函數都可以。