在強化學習(十三) 策略梯度(Policy Gradient)中,咱們講到了基於策略(Policy Based)的強化學習方法的基本思路,並討論了蒙特卡羅策略梯度reinforce算法。可是因爲該算法須要完整的狀態序列,同時單獨對策略函數進行迭代更新,不太容易收斂。html
在本篇咱們討論策略(Policy Based)和價值(Value Based)相結合的方法:Actor-Critic算法。git
本文主要參考了Sutton的強化學習書第13章和UCL強化學習講義的第7講。github
Actor-Critic從名字上看包括兩部分,演員(Actor)和評價者(Critic)。其中Actor使用咱們上一節講到的策略函數,負責生成動做(Action)並和環境交互。而Critic使用咱們以前講到了的價值函數,負責評估Actor的表現,並指導Actor下一階段的動做。算法
回想咱們上一篇的策略梯度,策略函數就是咱們的Actor,可是那裏是沒有Critic的,咱們當時使用了蒙特卡羅法來計算每一步的價值部分替代了Critic的功能,可是場景比較受限。所以如今咱們使用相似DQN中用的價值函數來替代蒙特卡羅法,做爲一個比較通用的Critic。網絡
也就是說在Actor-Critic算法中,咱們須要作兩組近似,第一組是策略函數的近似:$$\pi_{\theta}(s,a) = P(a|s,\theta)\approx \pi(a|s)$$多線程
第二組是價值函數的近似,對於狀態價值和動做價值函數分別是:$$\hat{v}(s, w) \approx v_{\pi}(s)$$$$\hat{q}(s,a,w) \approx q_{\pi}(s,a)$$app
對於咱們上一節講到的蒙特卡羅策略梯度reinforce算法,咱們須要進行改造才能變成Actor-Critic算法。框架
首先,在蒙特卡羅策略梯度reinforce算法中,咱們的策略的參數更新公式是:$$\theta = \theta + \alpha \nabla_{\theta}log \pi_{\theta}(s_t,a_t) v_t$$ide
梯度更新部分中,$\nabla_{\theta}log \pi_{\theta}(s_t,a_t) $是咱們的分值函數,不用動,要變成Actor的話改動的是$v_t$,這塊不能再使用蒙特卡羅法來獲得,而應該從Critic獲得。函數
而對於Critic來講,這塊是新的,不過咱們徹底能夠參考以前DQN的作法,即用一個Q網絡來作爲Critic, 這個Q網絡的輸入能夠是狀態,而輸出是每一個動做的價值或者最優動做的價值。
如今咱們彙總來講,就是Critic經過Q網絡計算狀態的最優價值$v_t$, 而Actor利用$v_t$這個最優價值迭代更新策略函數的參數$\theta$,進而選擇動做,並獲得反饋和新的狀態,Critic使用反饋和新的狀態更新Q網絡參數$w$, 在後面Critic會使用新的網絡參數$w$來幫Actor計算狀態的最優價值$v_t$。
在上一節咱們已經對Actor-Critic算法的流程作了一個初步的總結,不過有一個能夠注意的點就是,咱們對於Critic評估的點選擇是和上一篇策略梯度同樣的狀態價值$v_t$,實際上,咱們還能夠選擇不少其餘的指標來作爲Critic的評估點。而目前可使用的Actor-Critic評估點主要有:
a) 基於狀態價值:這是咱們上一節使用的評估點,這樣Actor的策略函數參數更新的法公式是:$$\theta = \theta + \alpha \nabla_{\theta}log \pi_{\theta}(s_t,a_t) V(s,w)$$
b) 基於動做價值:在DQN中,咱們通常使用的都是動做價值函數Q來作價值評估,這樣Actor的策略函數參數更新的法公式是:$$\theta = \theta + \alpha \nabla_{\theta}log \pi_{\theta}(s_t,a_t) Q(s,a,w)$$
c) 基於TD偏差:在強化學習(五)用時序差分法(TD)求解中,咱們講到了TD偏差,它的表達式是$\delta(t) = R_{t+1} + \gamma V(S_{t+1}) -V(S_t)$或者$\delta(t) = R_{t+1} + \gamma Q(S_{t+1},A_{t+1} ) -Q(S_t,A_t)$, 這樣Actor的策略函數參數更新的法公式是:$$\theta = \theta + \alpha \nabla_{\theta}log \pi_{\theta}(s_t,a_t)\delta(t)$$
d) 基於優點函數:在強化學習(十二) Dueling DQN中,咱們講到過優點函數A的定義:$A(S,A,w,\beta) = Q(S,A, w, \alpha, \beta) - V(S,w,\alpha) $,即動做價值函數和狀態價值函數的差值。這樣Actor的策略函數參數更新的法公式是:$$\theta = \theta + \alpha \nabla_{\theta}log \pi_{\theta}(s_t,a_t)A(S,A,w,\beta)$$
e) 基於TD($\lambda$)偏差:通常都是基於後向TD($\lambda$)偏差, 在強化學習(五)用時序差分法(TD)求解中也有講到,是TD偏差和效用跡E的乘積。這樣Actor的策略函數參數更新的法公式是:$$\theta = \theta + \alpha \nabla_{\theta}log \pi_{\theta}(s_t,a_t)\delta(t)E_(t)$$
對於Critic自己的模型參數$w$,通常都是使用均方偏差損失函數來作作迭代更新,相似以前DQN系列中所講的迭代方法. 若是咱們使用的是最簡單的線性Q函數,好比$Q(s,a ,w) = \phi(s,a)^Tw$,則Critic自己的模型參數$w$的更新公式能夠表示爲:$$\delta = R_{t+1} + \gamma Q(S_{t+1},A_{t+1} ) -Q(S_t,A_t)$$$$w = w+ \beta\delta\phi(s,a)$$
經過對均方偏差損失函數求導能夠很容易的獲得上式。固然實際應用中,咱們通常不使用線性Q函數,而使用神經網絡表示狀態和Q值的關係。
這裏給一個Actor-Critic算法的流程總結,評估點基於TD偏差,Critic使用神經網絡來計算TD偏差並更新網絡參數,Actor也使用神經網絡來更新網絡參數
算法輸入:迭代輪數$T$,狀態特徵維度$n$, 動做集$A$, 步長$\alpha,\beta$,衰減因子$\gamma$, 探索率$\epsilon$, Critic網絡結構和Actor網絡結構。
輸出:Actor 網絡參數$\theta$, Critic網絡參數$w$
1. 隨機初始化全部的狀態和動做對應的價值$Q$. 隨機初始化Critic網絡的全部參數$w$。隨機初始化Actor網絡的全部參數$\theta$。
2. for i from 1 to T,進行迭代。
a) 初始化S爲當前狀態序列的第一個狀態, 拿到其特徵向量$\phi(S)$
b) 在Actor網絡中使用$\phi(S)$做爲輸入,輸出動做$A$,基於動做$A$獲得新的狀態$S'$,反饋$R$。
c) 在Critic網絡中分別使用$\phi(S), \phi(S‘’)$做爲輸入,獲得Q值輸出$V(S), V(S’)$
d) 計算TD偏差$\delta = R +\gamma V(S’) -V(S) $
e) 使用均方差損失函數$\sum\limits(R +\gamma V(S’) -V(S,w))^2$做Critic網絡參數$w$的梯度更新
f) 更新Actor網絡參數$\theta$:$$\theta = \theta + \alpha \nabla_{\theta}log \pi_{\theta}(S_t,A)\delta$$
對於Actor的分值函數$\nabla_{\theta}log \pi_{\theta}(S_t,A)$,能夠選擇softmax或者高斯分值函數。
上述Actor-Critic算法已是一個很好的算法框架,可是離實際應用還比較遠。主要緣由是這裏有兩個神經網絡,都須要梯度更新,並且互相依賴。可是瞭解這個算法過程後,其餘基於Actor-Critic的算法就好理解了。
下面咱們用一個具體的例子來演示上面的Actor-Critic算法。仍然使用了OpenAI Gym中的CartPole-v0遊戲來做爲咱們算法應用。CartPole-v0遊戲的介紹參見這裏。它比較簡單,基本要求就是控制下面的cart移動使鏈接在上面的pole保持垂直不倒。這個任務只有兩個離散動做,要麼向左用力,要麼向右用力。而state狀態就是這個cart的位置和速度, pole的角度和角速度,4維的特徵。堅持到200分的獎勵則爲過關。
算法流程能夠參考上面的第三節,這裏的分值函數咱們使用的是softmax函數,和上一片的相似。完整的代碼參見個人Github:https://github.com/ljpzzz/machinelearning/blob/master/reinforcement-learning/actor_critic.py
代碼主要分爲兩部分,第一部分是Actor,第二部分是Critic。對於Actor部分,你們能夠和上一篇策略梯度的代碼對比,改動並不大,主要區別在於梯度更新部分,策略梯度使用是蒙特卡羅法計算出的價值$v(t)$,則咱們的actor使用的是TD偏差。
在策略梯度部分,對應的位置以下:
self.loss = tf.reduce_mean(self.neg_log_prob * self.tf_vt) # reward guided loss
而咱們的Actor對應的位置的代碼是:
self.exp = tf.reduce_mean(self.neg_log_prob * self.td_error)
此處要注意的是,因爲使用的是TD偏差,而不是價值$v(t)$,此處須要最大化self.exp,而不是最小化它,這點和策略梯度不一樣。對應的Actor代碼爲:
#這裏須要最大化當前策略的價值,所以須要最大化self.exp,即最小化-self.exp self.train_op = tf.train.AdamOptimizer(LEARNING_RATE).minimize(-self.exp)
除此以外,Actor部分的代碼和策略梯度的代碼區別並不大。
對於Critic部分,咱們使用了相似於DQN的三層神經網絡。不過咱們簡化了這個網絡的輸出,只有一維輸出值,而不是以前DQN使用的有多少個可選動做,就有多少維輸出值。網絡結構以下:
def create_Q_network(self): # network weights W1q = self.weight_variable([self.state_dim, 20]) b1q = self.bias_variable([20]) W2q = self.weight_variable([20, 1]) b2q = self.bias_variable([1]) self.state_input = tf.placeholder(tf.float32, [1, self.state_dim], "state") # hidden layers h_layerq = tf.nn.relu(tf.matmul(self.state_input, W1q) + b1q) # Q Value layer self.Q_value = tf.matmul(h_layerq, W2q) + b2q
和以前的DQN相比,這裏還有一個區別就是咱們的critic沒有使用DQN的經驗回放,只是使用了反饋和當前網絡在下一個狀態的輸出來擬合當前狀態。
對於算法中Actor和Critic交互的邏輯,在main函數中:
for step in range(STEP): action = actor.choose_action(state) # e-greedy action for train next_state,reward,done,_ = env.step(action) td_error = critic.train_Q_network(state, reward, next_state) # gradient = grad[r + gamma * V(s_) - V(s)] actor.learn(state, action, td_error) # true_gradient = grad[logPi(s,a) * td_error] state = next_state if done: break
你們對照第三節的算法流程和代碼應該能夠比較容易理清這個過程。可是這個程序很難收斂。所以你們跑了後發現分數老是很低的話是能夠理解的。咱們須要優化這個問題。
基本版的Actor-Critic算法雖然思路很好,可是因爲難收斂的緣由,還須要作改進。
目前改進的比較好的有兩個經典算法,一個是DDPG算法,使用了雙Actor神經網絡和雙Critic神經網絡的方法來改善收斂性。這個方法咱們在從DQN到Nature DQN的過程當中已經用過一次了。另外一個是A3C算法,使用了多線程的方式,一個主線程負責更新Actor和Critic的參數,多個輔線程負責分別和環境交互,獲得梯度更新值,彙總更新主線程的參數。而全部的輔線程會按期從主線程更新網絡參數。這些輔線程起到了相似DQN中經驗回放的做用,可是效果更好。
在後面的文章中,咱們會繼續討論DDPG和A3C。
(歡迎轉載,轉載請註明出處。歡迎溝通交流: liujianping-ok@163.com)
原文出處:https://www.cnblogs.com/pinard/p/10272023.html