強化學習(十五) A3C

    在強化學習(十四) Actor-Critic中,咱們討論了Actor-Critic的算法流程,可是因爲普通的Actor-Critic算法難以收斂,須要一些其餘的優化。而Asynchronous Advantage Actor-critic(如下簡稱A3C)就是其中比較好的優化算法。本文咱們討論A3C的算法原理和算法流程。html

    本文主要參考了A3C的論文,以及ICML 2016的deep RL tutorialgit

1. A3C的引入

    上一篇Actor-Critic算法的代碼,其實很難收斂,不管怎麼調參,最後的CartPole都很難穩定在200分,這是Actor-Critic算法的問題。可是咱們仍是有辦法去有優化這個難以收斂的問題的。github

    回憶下以前的DQN算法,爲了方便收斂使用了經驗回放的技巧。那麼咱們的Actor-Critic是否是也可使用經驗回放的技巧呢?固然能夠!不過A3C更進一步,還克服了一些經驗回放的問題。經驗回放有什麼問題呢? 回放池經驗數據相關性太強,用於訓練的時候效果極可能不佳。舉個例子,咱們學習下棋,老是和同一我的下,指望能提升棋藝。這固然沒有問題,可是到必定程度就再難提升了,此時最好的方法是另尋高手切磋。算法

    A3C的思路也是如此,它利用多線程的方法,同時在多個線程裏面分別和環境進行交互學習,每一個線程都把學習的成果彙總起來,整理保存在一個公共的地方。而且,按期從公共的地方把你們的齊心學習的成果拿回來,指導本身和環境後面的學習交互。bootstrap

    經過這種方法,A3C避免了經驗回放相關性過強的問題,同時作到了異步併發的學習模型。網絡

2. A3C的算法優化

    如今咱們來看看相比Actor-Critic,A3C到底作了哪些具體的優化。多線程

    相比Actor-Critic,A3C的優化主要有3點,分別是異步訓練框架,網絡結構優化,Critic評估點的優化。其中異步訓練框架是最大的優化。併發

    咱們首先來看這個異步訓練框架,以下圖所示:app

    圖中上面的Global Network就是上一節說的共享的公共部分,主要是一個公共的神經網絡模型,這個神經網絡包括Actor網絡和Critic網絡兩部分的功能。下面有n個worker線程,每一個線程裏有和公共的神經網絡同樣的網絡結構,每一個線程會獨立的和環境進行交互獲得經驗數據,這些線程之間互不干擾,獨立運行。框架

    每一個線程和環境交互到必定量的數據後,就計算在本身線程裏的神經網絡損失函數的梯度,可是這些梯度卻並不更新本身線程裏的神經網絡,而是去更新公共的神經網絡。也就是n個線程會獨立的使用累積的梯度分別更新公共部分的神經網絡模型參數。每隔一段時間,線程會將本身的神經網絡的參數更新爲公共神經網絡的參數,進而指導後面的環境交互。

    可見,公共部分的網絡模型就是咱們要學習的模型,而線程裏的網絡模型主要是用於和環境交互使用的,這些線程裏的模型能夠幫助線程更好的和環境交互,拿到高質量的數據幫助模型更快收斂。

 

    如今咱們來看看第二個優化,網絡結構的優化。以前在強化學習(十四) Actor-Critic中,咱們使用了兩個不一樣的網絡Actor和Critic。在A3C這裏,咱們把兩個網絡放到了一塊兒,即輸入狀態$S$,能夠輸入狀態價值$V$,和對應的策略$\pi$, 固然,咱們仍然能夠把Actor和Critic看作獨立的兩塊,分別處理,以下圖所示:

    第三個優化點是Critic評估點的優化,在強化學習(十四) Actor-Critic第2節中,咱們討論了不一樣的Critic評估點的選擇,其中d部分講到了使用優點函數$A$來作Critic評估點,優點函數$A$在時刻t不考慮參數的默認表達式爲:$$A(S,A,t) = Q(S,A) - V(S)$$

    $Q(S,A)$的值通常能夠經過單步採樣近似估計,即:$$Q(S,A) = R + \gamma V(S')$$

    這樣優點函數去掉動做能夠表達爲:$$A(S,t) = R + \gamma V(S') - V(S)$$

    其中$V(S)$的值須要經過Critic網絡來學習獲得。

    在A3C中,採樣更進一步,使用了N步採樣,以加速收斂。這樣A3C中使用的優點函數表達爲:$$A(S,t) = R_t + +  \gamma R_{t+1} +...\gamma^{n-1} R_{t+n-1} + \gamma^n V(S') - V(S)$$

    對於Actor和Critic的損失函數部分,和Actor-Critic基本相同。有一個小的優化點就是在Actor-Critic策略函數的損失函數中,加入了策略$\pi$的熵項,係數爲c, 即策略參數的梯度更新和Actor-Critic相比變成了這樣:$$\theta = \theta + \alpha \nabla_{\theta}log \pi_{\theta}(s_t,a_t)A(S,t) + c\nabla_{\theta}H(\pi(S_t, \theta))$$

    以上就是A3C和Actor-Critic相比有優化的部分。下面咱們來總價下A3C的算法流程。

3. A3C算法流程

    這裏咱們對A3C算法流程作一個總結,因爲A3C是異步多線程的,咱們這裏給出任意一個線程的算法流程。

    輸入:公共部分的A3C神經網絡結構,對應參數位$\theta, w$,本線程的A3C神經網絡結構,對應參數$\theta ', w'$, 全局共享的迭代輪數$T$,全局最大迭代次數$T_{max}$, 線程內單次迭代時間序列最大長度$T_{local}$,狀態特徵維度$n$, 動做集$A$, 步長$\alpha,\beta$,熵係數c, 衰減因子$\gamma$, 探索率$\epsilon$

    輸入:公共部分的A3C神經網絡參數$\theta, w$

    1. 更新時間序列$t=1$

    2. 重置Actor和Critic的梯度更新量:$d\theta  \gets 0, dw\gets 0$

    3. 從公共部分的A3C神經網絡同步參數到本線程的神經網絡:$\theta ' =\theta,\;\; w'=w$

    4. $t_{start} = t$,初始化狀態$s_t$

    5. 基於策略$\pi(a_t|s_t;\theta)$選擇出動做$a_t$

    6. 執行動做$a_t$獲得獎勵$r_t$和新狀態$s_{t+1}$

    7. $t \gets t+1, T \gets T+1$

    8. 若是$s_t$是終止狀態,或$t-t_{start} == t_{local} $,則進入步驟9,不然回到步驟5

    9. 計算最後一個時間序列位置$s_t$的$Q(s,t)$:$$Q(s,t)= \begin{cases} 0& {terminal\;state}\\ V(s_t,w')& {none\;terminal\;state,bootstrapping} \end{cases}$$

    10. for $i \in (t-1,t-2,...t_{start})$:

      1) 計算每一個時刻的$Q(s,i)$:$Q(s,i) = r_i + \gamma Q(s,i+1)$

      2) 累計Actor的本地梯度更新:$$d\theta \gets d\theta + \nabla_{\theta '}log \pi_{\theta'}(s_i,a_i)(Q(s,i)-V(S_i, w')) + c\nabla_{\theta '}H(\pi(s_i, \theta '))$$

      3) 累計Critic的本地梯度更新:$$dw  \gets dw + \frac{\partial (Q(s,i)-V(S_i, w'))^2}{\partial w'}$$

    11. 更新全局神經網絡的模型參數:$$\theta = \theta -\alpha d\theta,\;w = w -\beta dw$$

    12. 若是$T > T_{max}$,則算法結束,輸出公共部分的A3C神經網絡參數$\theta, w$,不然進入步驟3

    以上就是A3C算法單個線程的算法流程。

4. A3C算法實例

    下面咱們基於上述算法流程給出A3C算法實例。仍然使用了OpenAI Gym中的CartPole-v0遊戲來做爲咱們算法應用。CartPole-v0遊戲的介紹參見這裏。它比較簡單,基本要求就是控制下面的cart移動使鏈接在上面的pole保持垂直不倒。這個任務只有兩個離散動做,要麼向左用力,要麼向右用力。而state狀態就是這個cart的位置和速度, pole的角度和角速度,4維的特徵。堅持到200分的獎勵則爲過關。

    算法代碼大部分參考了莫煩的A3C代碼,增長了模型測試部分的代碼並調整了部分模型參數。完整的代碼參見個人Github:https://github.com/ljpzzz/machinelearning/blob/master/reinforcement-learning/a3c.py

    整個算法的Actor和Critic的網絡結構都定義在這裏, 全部的線程中的網絡結構,公共部分的網絡結構都在這裏定義。

    def _build_net(self, scope):
        w_init = tf.random_normal_initializer(0., .1)
        with tf.variable_scope('actor'):
            l_a = tf.layers.dense(self.s, 200, tf.nn.relu6, kernel_initializer=w_init, name='la')
            a_prob = tf.layers.dense(l_a, N_A, tf.nn.softmax, kernel_initializer=w_init, name='ap')
        with tf.variable_scope('critic'):
            l_c = tf.layers.dense(self.s, 100, tf.nn.relu6, kernel_initializer=w_init, name='lc')
            v = tf.layers.dense(l_c, 1, kernel_initializer=w_init, name='v')  # state value
        a_params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope=scope + '/actor')
        c_params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope=scope + '/critic')
        return a_prob, v, a_params, c_params

    全部線程初始化部分,以及本線程和公共的網絡結構初始化部分以下:

    with tf.device("/cpu:0"):
        OPT_A = tf.train.RMSPropOptimizer(LR_A, name='RMSPropA')
        OPT_C = tf.train.RMSPropOptimizer(LR_C, name='RMSPropC')
        GLOBAL_AC = ACNet(GLOBAL_NET_SCOPE)  # we only need its params
        workers = []
        # Create worker
        for i in range(N_WORKERS):
            i_name = 'W_%i' % i   # worker name
            workers.append(Worker(i_name, GLOBAL_AC))

    本線程神經網絡將本地的梯度更新量用於更新公共網絡參數的邏輯在update_global函數中,而從公共網絡把參數拉回到本線程神經網絡的邏輯在pull_global中。

    def update_global(self, feed_dict):  # run by a local
        SESS.run([self.update_a_op, self.update_c_op], feed_dict)  # local grads applies to global net

    def pull_global(self):  # run by a local
        SESS.run([self.pull_a_params_op, self.pull_c_params_op])

    詳細的內容你們能夠對照代碼和算法流程一塊兒看。在主函數裏我新加了一個測試模型效果的過程,你們能夠試試看看最後的模型效果如何。

5. A3C小結

    A3C解決了Actor-Critic難以收斂的問題,同時更重要的是,提供了一種通用的異步的併發的強化學習框架,也就是說,這個併發框架不光能夠用於A3C,還能夠用於其餘的強化學習算法。這是A3C最大的貢獻。目前,已經有基於GPU的A3C框架,這樣A3C的框架訓練速度就更快了。

    除了A3C, DDPG算法也能夠改善Actor-Critic難收斂的問題。它使用了Nature DQN,DDQN相似的思想,用兩個Actor網絡,兩個Critic網絡,一共4個神經網絡來迭代更新模型參數。在下一篇咱們討論DDPG算法。

 

(歡迎轉載,轉載請註明出處。歡迎溝通交流: liujianping-ok@163.com)      

相關文章
相關標籤/搜索