在強化學習(十一) Prioritized Replay DQN中,咱們討論了對DQN的經驗回放池按權重採樣來優化DQN算法的方法,本文討論另外一種優化方法,Dueling DQN。本章內容主要參考了ICML 2016的deep RL tutorial和Dueling DQN的論文<Dueling Network Architectures for Deep Reinforcement Learning>(ICML 2016)。html
在前面講到的DDQN中,咱們經過優化目標Q值的計算來優化算法,在Prioritized Replay DQN中,咱們經過優化經驗回放池按權重採樣來優化算法。而在Dueling DQN中,咱們嘗試經過優化神經網絡的結構來優化算法。git
具體如何優化網絡結構呢?Dueling DQN考慮將Q網絡分紅兩部分,第一部分是僅僅與狀態$S$有關,與具體要採用的動做$A$無關,這部分咱們叫作價值函數部分,記作$V(S,w,\alpha)$,第二部分同時與狀態狀態$S$和動做$A$有關,這部分叫作優點函數(Advantage Function)部分,記爲$A(S,A,w,\beta)$,那麼最終咱們的價值函數能夠從新表示爲:$$Q(S,A, w, \alpha, \beta) = V(S,w,\alpha) + A(S,A,w,\beta)$$github
其中,$w$是公共部分的網絡參數,而$\alpha$是價值函數獨有部分的網絡參數,而$\beta$是優點函數獨有部分的網絡參數。算法
因爲Q網絡的價值函數被分爲兩部分,所以Dueling DQN的網絡結構也和以前的DQN不一樣。爲了簡化算法描述,這裏不使用原論文的CNN網絡結構,而是使用前面文中用到的最簡單的三層神經網絡來描述。是否使用CNN對Dueling DQN算法自己無影響。網絡
在前面講到的DDQN等DQN算法中,我使用了一個簡單的三層神經網絡:一個輸入層,一個隱藏層和一個輸出層。以下左圖所示:ide
而在Dueling DQN中,咱們在後面加了兩個子網絡結構,分別對應上面上到價格函數網絡部分和優點函數網絡部分。對應上面右圖所示。最終Q網絡的輸出由價格函數網絡的輸出和優點函數網絡的輸出線性組合獲得。函數
咱們能夠直接使用上一節的價值函數的組合公式獲得咱們的動做價值,可是這個式子沒法辨識最終輸出裏面$V(S,w,\alpha)$和$A(S,A,w,\beta)$各自的做用,爲了能夠體現這種可辨識性(identifiability),實際使用的組合公式以下:$$Q(S,A, w, \alpha, \beta) = V(S,w,\alpha) + (A(S,A,w,\beta) - \frac{1}{\mathcal{A}}\sum\limits_{a' \in \mathcal{A}}A(S,a', w,\beta))$$post
其實就是對優點函數部分作了中心化的處理。以上就是Duel DQN的主要算法思路。因爲它僅僅涉及神經網絡的中間結構的改進,現有的DQN算法能夠在使用Duel DQN網絡結構的基礎上繼續使用現有的算法。因爲算法主流程和其餘算法沒有差別,這裏就不單獨講Duel DQN的算法流程了。學習
下面咱們用一個具體的例子來演示Dueling DQN的應用。仍然使用了OpenAI Gym中的CartPole-v0遊戲來做爲咱們算法應用。CartPole-v0遊戲的介紹參見這裏。它比較簡單,基本要求就是控制下面的cart移動使鏈接在上面的pole保持垂直不倒。這個任務只有兩個離散動做,要麼向左用力,要麼向右用力。而state狀態就是這個cart的位置和速度, pole的角度和角速度,4維的特徵。堅持到200分的獎勵則爲過關。優化
這個實例代基於Nature DQN,並將網絡結構改成上圖中右邊的Dueling DQN網絡結構,完整的代碼參見個人github: https://github.com/ljpzzz/machinelearning/blob/master/reinforcement-learning/duel_dqn.py
這裏咱們重點關注Dueling DQN和Nature DQN的代碼的不一樣之處。也就是網絡結構定義部分,主要的代碼以下,一共有兩個相同結構的Q網絡,每一個Q網絡都有狀態函數和優點函數的定義,以及組合後的Q網絡輸出,如代碼紅色部分:
def create_Q_network(self): # input layer self.state_input = tf.placeholder("float", [None, self.state_dim]) # network weights with tf.variable_scope('current_net'): W1 = self.weight_variable([self.state_dim,20]) b1 = self.bias_variable([20]) # hidden layer 1 h_layer_1 = tf.nn.relu(tf.matmul(self.state_input,W1) + b1) # hidden layer for state value with tf.variable_scope('Value'): W21= self.weight_variable([20,1]) b21 = self.bias_variable([1]) self.V = tf.matmul(h_layer_1, W21) + b21 # hidden layer for action value with tf.variable_scope('Advantage'): W22 = self.weight_variable([20,self.action_dim]) b22 = self.bias_variable([self.action_dim]) self.A = tf.matmul(h_layer_1, W22) + b22 # Q Value layer self.Q_value = self.V + (self.A - tf.reduce_mean(self.A, axis=1, keep_dims=True)) with tf.variable_scope('target_net'): W1t = self.weight_variable([self.state_dim,20]) b1t = self.bias_variable([20]) # hidden layer 1 h_layer_1t = tf.nn.relu(tf.matmul(self.state_input,W1t) + b1t) # hidden layer for state value with tf.variable_scope('Value'): W2v = self.weight_variable([20,1]) b2v = self.bias_variable([1]) self.VT = tf.matmul(h_layer_1t, W2v) + b2v # hidden layer for action value with tf.variable_scope('Advantage'): W2a = self.weight_variable([20,self.action_dim]) b2a = self.bias_variable([self.action_dim]) self.AT = tf.matmul(h_layer_1t, W2a) + b2a # Q Value layer self.target_Q_value = self.VT + (self.AT - tf.reduce_mean(self.AT, axis=1, keep_dims=True))
其他部分代碼和Nature DQN基本相同。固然,咱們能夠也在前面DDQN,Prioritized Replay DQN代碼的基礎上,把網絡結構改爲上面的定義,這樣Dueling DQN也能夠起做用。
DQN系列我花了5篇來說解,一共5個先後有關聯的算法:DQN(NIPS2013), Nature DQN, DDQN, Prioritized Replay DQN和Dueling DQN。目前使用的比較主流的是後面三種算法思路,這三種算法思路也是能夠混着一塊兒使用的,相互並不排斥。
固然DQN家族的算法遠遠不止這些,還有一些其餘的DQN算法我沒有詳細介紹,好比使用一些較複雜的CNN和RNN網絡來提升DQN的表達能力,又好比改進探索狀態空間的方法等,主要是在DQN的基礎上持續優化。
DQN算是深度強化學習的中的主流流派,表明了Value-Based這一大類深度強化學習算法。可是它也有本身的一些問題,就是絕大多數DQN只能處理離散的動做集合,不能處理連續的動做集合。雖然NAF DQN能夠解決這個問題,可是方法過於複雜了。而深度強化學習的另外一個主流流派Policy-Based而能夠較好的解決這個問題,從下一篇咱們開始討論Policy-Based深度強化學習。
(歡迎轉載,轉載請註明出處。歡迎溝通交流: liujianping-ok@163.com)