1. 程式人生 > >【轉】強化學習(一)Deep Q-Network

【轉】強化學習(一)Deep Q-Network

原文地址:https://www.hhyz.me/2018/08/05/2018-08-05-RL/

1. 前言

雖然將深度學習和增強學習結合的想法在幾年前就有人嘗試,但真正成功的開端就是DeepMind在NIPS 2013上發表的 Playing Atari with Deep Reinforcement Learning 一文,在該文中第一次提出Deep Reinforcement Learning 這個名稱,並且提出DQN(Deep Q-Network)演算法,實現從純影象輸入完全通過學習來玩Atari遊戲的成果。之後DeepMind在Nature上發表了改進版的DQN文章Human-level Control through Deep Reinforcement Learning

,引起了廣泛的關注,Deep Reinfocement Learning 從此成為深度學習領域的前沿研究方向。

智慧體 Agent 來表示一個具備行為能力的物體,比如機器人,無人車,人等等。

那麼增強學習考慮的問題就是智慧體Agent和 環境 Environment 之間互動的任務。

比如一個機械臂要拿起一個手機,那麼機械臂周圍的物體包括手機就是環境,機械臂通過外部的比如攝像頭來感知環境,然後機械臂需要輸出動作來實現拿起手機這個任務。再舉玩遊戲的例子,比如我們玩極品飛車遊戲,我們只看到螢幕,這就是環境,然後我們輸出動作(鍵盤操作)來控制車的運動。

那麼,不管是什麼樣的任務,
都包含了一系列的:

  • 動作 Action
  • 觀察 Observation
  • 反饋值 Reward

所謂的Reward就是Agent執行了動作與環境進行互動後,環境會發生變化,變化的好與壞就用Reward來表示。

接下來這裡用了Observation觀察一詞而不是環境那是因為Agent不一定能得到環境的所有資訊,比如機械臂上的攝像頭就只能得到某個特定角度的畫面。因此,只能用Observation來表示Agent獲取的感知資訊。

只能用 Observation 來表示 Agent 獲取的感知資訊

每個時間片,Agent 都是根據當前的觀察來確定下一步的動作。觀察 Observation 的集合就作為Agent的所處的 狀態 State

,因此,狀態 State動作 Action 存在對映關係,也就是一個 state 可以對應一個 action,或者對應不同動作的概率(常常用概率來表示,概率最高的就是最值得執行的動作)。狀態與動作的關係其實就是輸入與輸出的關係,而狀態 State 到動作 Action 的過程就稱之為一個策略 Policy,一般用 \(\pi\) 表示,也就是需要找到以下關係:

$$a=\pi(s)$$

或者

$$\pi(a|s)$$

其中 a 是 action,s 是 state
第一種是一一對應的表示,第二種是概率的表示。

增強學習的任務就是找到一個最優的策略Policy從而使Reward最多

我們一開始並不知道最優的策略是什麼,因此往往從隨機的策略開始,使用隨機的策略進行試驗,就可以得到一系列的狀態,動作和反饋:

$$\{s_1,a_1,r_1,s_2,a_2,r_2,…s_t,a_t,r_t\}$$

這就是一系列的 樣本 Sample。增強學習的演算法就是需要根據這些樣本來改進 Policy,從而使得得到的樣本中的 Reward 更好。由於這種讓 Reward 越來越好的特性,所以這種演算法就叫做增強學習Reinforcement Learning。

 

2. 馬爾科夫決策過程

MDP只需要用一句話就可以說明白,就是 “未來只取決於當前”,專業點說就是下一步的狀態只取決於當前的狀態,與過去的狀態沒有關係。

一個狀態 \(S_t\) 是Markov當且僅當:

$$P(s_{t+1}|s_t)=P(s_{t+1}|s_t,s_{t-1},…s_1,s_0)$$

P為概率。簡單的說就是下一個狀態僅取決於當前的狀態和當前的動作。
增強學習的問題都可以模型化為MDP的問題

因此 MDP 可以表示為一個元組 \((S, A, P_{sa}, R)\) :

  • \(S\) :所有可能狀態的集合, \(s \in S\),\(s\) 表示某個特定狀態
  • \(A\) :針對每個狀態,我們都要做出動作,這些動作的集合就是 \(A\); \(a \in A\),有限動作 action 集合, \(a\) 表示某個特定動作
  • \(P_{sa}\) :狀態轉換分佈(statetransition distribution),如果我們在狀態 \(s\) 中採取了動作 \(a\) ,系統會轉移到一個新的狀態,狀態轉換分佈描述了轉移到哪個狀態的概率分佈。
  • \(R\) :回饋函式(rewardfunction),增強學習的核心概念,描述了動作能夠產生的回報。比如 \(R_π(s,a)\) 描述了在狀態 \(s\) 下采用策略 \(\pi\) 所對應的動作 \(a\) 的回報,也叫做立即回報,回饋函式可以有不同的表達形式。
  • \(\pi(s)\rightarrow a\): 策略 policy,根據當前 state 來產生 action,可表現為 \(a=\pi(s) \) 或 \( \pi(a|s) = P[a|s]\),後者表示某種狀態下執行某個動作的概率

一個基本的 MDP 可以用 \((S,A,P)\) 來表示, \(S \) 表示狀態, \(A\) 表示動作, \(P \) 表示狀態轉移概率,也就是根據當前的狀態 \(s_t\) 和 \(a_t\) 轉移到 \(s_{t+1}\) 的概率。

如果我們知道了轉移概率 P,也就是稱為我們獲得了 模型 Model,有了模型,未來就可以求解,那麼獲取最優的動作也就有可能,這種通過模型來獲取最優動作的方法也就稱為 Model-based 的方法。但是現實情況下,很多問題是很難得到準確的模型的,因此就有 Model-free 的方法來尋找最優的動作。

 

3. 價值函式

既然一個狀態對應一個動作,或者動作的概率,而有了動作,下一個狀態也就確定了。這就意味著每個狀態可以用一個確定的值來進行描述。可以由此判斷一個狀態是好的狀態還是不好的狀態。

但是在選取最優策略的過程中,我們只看立即回報並不能判定哪種策略更優,我們希望的是在採取了策略 \(\pi\) 以後,可以使得整個狀態序列的折扣回饋最大。

狀態的好壞其實等價於對未來回報的期望,回報 Return 來表示某個時刻 t 的狀態將具備的回報:

$$G_t = R_{t+1} + \lambda R_{t+2} + … = \sum_{k=0}^\infty\lambda^kR_{t+k+1}$$
  • R 是 Reward 反饋
  • \(λ\) 是 discount factor 折扣因子,一般小於 1,就是說一般當下的反饋是比較重要的,時間越久,影響越小。

其中 \(λ\) 被稱為折扣因子,在經濟學上的解釋叫做無風險折現率(risk-freeinterest rate),意思是馬上得到的錢(回饋)比未來得到錢更有價值。

以上概念就組成了增強學習的完整描述:找到一種策略,使得我們能夠根據狀態 \(s_0, s_1, s_2, …\) 採取策略中對應的動作 \(a_0, a1, a2…,\) 並使 \(G_t\) 的期望值最大化

引出價值函式,對於獲取最優的策略Policy這個目標,我們就會有兩種方法:

  • 直接優化策略 \(\pi(a|s)\) 或者 \(a = \pi(s)\) 使得回報更高
  • 通過估計 value function 來間接獲得優化的策略。道理很簡單,既然我知道每一種狀態的優劣,那麼我就知道我應該怎麼選擇了,而這種選擇就是我們想要的策略。

但是現在為了理解DQN,我們將只關注第二種做法,就是估計value function的做法,因為DQN就是基於value function的演算法。

  1. 狀態價值函式 \(V\) :從狀態 \(x_0\) 開始, 所有的動作 \(a\) ,都是執行某個策略 \(π\) 的結果,最後求每個動作帶來累積獎賞
  2. 動作價值函式 \(Q\) :從狀態 \(x_0\) 開始,先執行動作 \(a_0\) , 然後再執行某個策略 \(π\) ,再求相應的積累獎賞

 

3.1 State-Value function 狀態價值函式

那麼實際上除非整個過程結束,否則顯然我們無法獲取所有的 reward 來計算出每個狀態的Return,因此,再引入一個 概念價值函式 Value Function,用 value function \(v(s)\) 來表示一個狀態未來的潛在價值。

從定義上看,value function 就是回報的期望:

$$v(s) = \mathbb E[G_t|S_t = s]$$

$$V^{\pi}(s) =\mathbb E_{\pi}[ R(s_0, a_0) + γR(s_1, a_1)+ γ^2R(s_2, a_2) + … | s_0= s ]$$

這個函式也被稱為狀態價值函式(statevalue function),記為 \(V_{\pi}(s)\)。 因為初始狀態 \(s\) 和策略 \(\pi\) 是我們給定的,動作 \(a = \pi(s)\) 。

 

3.2 Action-Value function 動作價值函式

我們更關心在某個狀態下的不同動作的價值。顯然。如果知道了每個動作的價值,那麼就可以選擇價值最大的一個動作去執行了。

這就是 Action-Value function \(Q^\pi(s,a)\) 。那麼同樣的道理,也是使用 reward 來表示,只是這裡的 reward 和之前的 reward 不一樣:

這裡是執行完動作 action 之後得到的 reward,之前 state 對應的 reward 則是多種動作對應的 reward 的期望值。顯然,動作之後的 reward 更容易理解。

那麼,有了上面的定義,動作價值函式就為如下表示:

$$ Q^{\pi}(s,a) = \mathbb E[R_{t+1}+\lambda R_{t+2} + \lambda ^2R_{t+3} + …|S_t = s,A_t=a]$$

$$
\begin{align}
Q^\pi(s,a) & = \mathbb E[r_{t+1} + \lambda r_{t+2} + \lambda^2r_{t+3} + … |s,a] \\
& = \mathbb E_{s^\prime}[r+\lambda Q^\pi(s^\prime,a^\prime)|s,a]
\end{align}
$$

這裡要說明的是動作價值函式的定義,加了 \(\pi\) ,也就是說是在策略下的動作價值。因為對於每一個動作而已,都需要由策略根據當前的狀態生成,因此必須有策略的支撐。而前面的價值函式則不一定依賴於策略。當然,如果定義 \(v^\pi(s)\) 則表示在策略 \(\pi\) 下的價值。

那麼事實上我們會更多的使用動作價值函式而不是價值函式,因為動作價值函式更直觀,更方便應用於演算法當中。

 

4. Bellman 方程

在上文我們介紹了 Value Function 價值函式,所以為了解決增強學習的問題,一個顯而易見的做法就是我們需要估算 Value Function。是的,只要我們能夠計算出價值函式,那麼最優決策也就得到了。因此,問題就變成了如何計算 Value Function?

$$P^a_{ss\prime} = P(S_{t+1}=s\prime|S_t =s, A_t =a)$$

還記得回報 Result 的基本定義嗎?就是所有 Reward 的累加(帶衰減係數 discount factor)

$$G_t = R_{t+1} + \lambda R_{t+2} + … = \sum_{k=0}^\infty\lambda^kR_{t+k+1}$$

那麼 Value Function 該如何定義?也很簡單,就是期望的回報啊!期望的回報越高,價值顯然也就越大,也就越值得去選擇。用數學來定義就是如下:

$$v(s) = \mathbb E[G_t|S_t = s]$$

$$v_{\pi}=\sum_{a\in A}P(a|s)\left(R^a_s+\lambda\sum_{s\prime \in S}P^a_{ss\prime}v_{\pi}(s\prime)\right)$$

接下來,我們把上式展開如下:

$$
\begin{align}
v(s) & = \mathbb E[G_t|S_t = s] \\
& = \mathbb E[R_{t+1}+\lambda R_{t+2} + \lambda ^2R_{t+3} + …|S_t = s] \\
& = \mathbb E[R_{t+1}+\lambda (R_{t+2} + \lambda R_{t+3} + …)|S_t = s] \\
& = \mathbb E[R_{t+1} + \lambda G_{t+1}|S_t = s] \\
& = \mathbb E[R_{t+1} + \lambda v(S_{t+1})|S_t = s]
\end{align}
$$

因此,

$$v(s) = \mathbb E[R_{t+1} + \lambda v(S_{t+1})|S_t = s]$$

上面這個公式就是Bellman方程的基本形態。從公式上看,當前狀態的價值和 下一步的價值以及當前的反饋Reward有關。

它表明Value Function是可以通過迭代來進行計算的!!!

總結一下:

$$v_{\pi}(s) = \mathbb E[R_{t+1} + \lambda v_{\pi}(S_{t+1})|S_t = s]$$

$$ q_{\pi}(s,a) = \mathbb E_{\pi}[R_{t+1} +\lambda q_\pi(S_{t+1},A_{t+1})|S_t =s,A_t = a]$$

 

5. 最優化

動態規劃

先簡單介紹一下動態規劃,因為嚴格來說,值迭代與策略迭代是用來解決動態規劃問題的兩種規劃方法。而強化學習又有另外一個暱稱——就是擬動態規劃。說白了強化學習就是模擬動態規劃演算法。

用一句話來總結動態規劃就是,對一個複雜問題給出一個一般性的解決辦法。它主要由兩個性質:

  • 最優子結構:最優解法能被分解到多個子問題中
  • 重疊子問題:子問題能重複多次且解法能被重複利用、

馬爾科夫決策過程(MDP)滿足以上兩個性質,所以任何 MDP 都可以用動態規劃來解。動態規劃與強化學習的區別就是動態規劃假設 MDP 模型是全知的(即引數可知) 而 強化學習可以使 MDP 未知

MDP需要解決的問題有兩種:

  • 第一種是 prediction,它已知MDP的 \(S,A,P,R,γ\) 以及 policy,目標是算出在每個狀態下的 value function(值函式其實就是問題的目標,一般都是跟 reward 有關的函式,例如 Atari 小遊戲,一般值函式就是累計的得分的期望。目標一般就是最大化這個值函式。
  • 而第二種是control,它已知 MDP 的 \(S,A,P,R,γ\) 但是 policy 未知(即動作 \(a_t\) 未知),因此它的目標不僅是計算出最優的 value function 而且要給出最優的 Policy。

5.1 Optimal value function 最優價值函式

能計算動作價值函式是不夠的,因為我們需要的是最優策略,現在求解最優策略等價於求解最優的 value function,找到了最優的 value function,自然而然策略也就是找到。(當然,這只是求解最優策略的一種方法,也就是 value-based approach,由於 DQN 就是 value-based,因此這裡只講這部分,以後我們會看到還有 policy-based 和 model-based 方法。一個就是直接計算策略函式,一個是估計模型,也就是計算出狀態轉移函式,從而整個MDP過程得解)

首先是最優動作價值函式和一般的動作價值函式的關係:

$$V^*(s,a) = \max_\pi V^\pi(s,a)$$

$$Q^*(s,a) = \max_\pi Q^\pi(s,a)$$

也就是最優的動作價值函式就是所有策略下的動作價值函式的最大值。通過這樣的定義就可以使最優的動作價值的唯一性,從而可以求解整個MDP。

那麼套用上一節得到的 value function,可以得到

$$Q^*(s,a) = \mathbb E_{s^\prime}[r+\lambda \max _{a^\prime}Q^*(s^\prime,a^\prime)|s,a]$$

因為最優的Q值必然為最大值,所以,等式右側的Q值必然為使 \(a′\) 取最大的Q值。

下面介紹基於Bellman方程的兩個最基本的演算法,策略迭代和值迭代。




5.2 Policy Iteration 策略迭代

策略迭代就是在policy未知的情況下,根據每次的reward學到最優policy。

對一個具體的 MDP 問題,每次先初始化一個策略,根據這個策略計算值函式 \(v(s)\) , 通過這個re值函式來根據貪心策略更新策略,不斷迭代最終得到最優策略與最優值函式。總結下來就兩個階段。

  • Policy evaluation :根據每一次的給出策略估計 \(v_π\)
  • Policy improvement:根據 Greedy poilcy 和之前得到的 \(v_π\) 獲得當前策略 \(π′\)

Policy Iteration的目的是通過迭代計算value function 價值函式的方式來使policy收斂到最優。














給一個例子:

下圖是一個叫 Small Gridworld 的例子,左上角和右下角是終點, \(γ=1\) ,移動一步 reward 減少1,起始的 random policy 是朝每個能走的方向概率相同,先單獨看左邊一列,它表示在第 \(k\) 次迭代每個 state上value function 的值,這一列始終採用了 random policy,這裡的 value function 就是通過 Bellman Expectation Equation 得到的,考慮 \(k=2\) 的情況, \(-1.7 = -1.0 + 2\times (1/3.0)(-1)\),\(-2.0 = -1.0 + 4(1/4.0)\times (-1)\) 。而右邊一列就是在當前的 value function 情況下通過 greedy 演算法找到當前朝哪個方向走更好。








Policy Iteration 本質上就是直接使用 Bellman 方程而得到的:



5.3 Value Iteration 價值迭代

Value Iteration 則是使用 Bellman 最優方程得到:



然後改變成迭代形式:




值迭代就是在已知 policy 和 MDP 模型的情況下,根據策略獲得最優值函式和最優策略。
只不過這是確定策略,在值函式 \(v_π\) 取得最大值的 \(a_t\) (策略)
通過每次迭代bellman方程獲得 \(v_i\) , 知道值函式收斂。圖解如下:




 

6. Q-Value (Quality-Value)

Q Learning的思想完全根據value iteration得到。但要明確一點是value iteration每次都對所有的Q值更新一遍,也就是所有的狀態和動作。但事實上在實際情況下我們沒辦法遍歷所有的狀態,還有所有的動作,我們只能得到有限的系列樣本。因此,只能使用有限的樣本進行操作。那麼,怎麼處理?Q Learning提出了一種更新Q值的辦法:

$$Q(S_{t},A_{t}) \leftarrow Q(S_{t},A_{t})+\alpha({R_{t+1}+\lambda \max _aQ(S_{t+1},a)} - Q(S_t,A_t))$$

雖然根據value iteration計算出target Q值,但是這裡並沒有直接將這個Q值(是估計值)直接賦予新的Q,而是採用漸進的方式類似梯度下降,朝target邁近一小步,取決於α,這就能夠減少估計誤差造成的影響。類似隨機梯度下降,最後可以收斂到最優的Q值。

具體的演算法如下:



大致程式碼流程如下:

def update():
    # 學習 100 回合
    for episode in range(100):
        # 初始化 state 的觀測值
        observation = env.reset()

        while True:
            # 更新視覺化環境
            env.render()

            # RL 大腦根據 state 的觀測值挑選 action
            action = RL.choose_action(str(observation))

            # 探索者在環境中實施這個 action, 並得到環境返回的下一個 state 觀測值, reward 和 done (是否是掉下地獄或者升上天堂)
            observation_, reward, done = env.step(action)

            # RL 從這個序列 (state, action, reward, state_) 中學習
            RL.learn(str(observation), action, reward, str(observation_))

            # 將下一個 state 的值傳到下一次迴圈
            observation = observation_

            # 如果掉下地獄或者升上天堂, 這回合就結束了
            if done:
                break

    # 結束遊戲並關閉視窗
    print('game over')
    env.destroy()

if __name__ == "__main__":
    # 定義環境 env 和 RL 方式
    env = Maze()
    RL = QLearningTable(actions=list(range(env.n_actions)))

    # 開始視覺化環境 env
    env.after(100, update)
    env.mainloop()
注意:

每一組 (state, action, reward, state_) 為一次序列



以我們回到之前的流程, 根據 Q 表的估計, 因為在 s1 中, a2 的值比較大, 通過之前的決策方法, 我們在 s1 採取了 a2, 併到達 s2, 這時我們開始更新用於決策的 Q 表, 接著我們並沒有在實際中採取任何行為, 而是再想象自己在 s2 上採取了每種行為, 分別看看兩種行為哪一個的 Q 值大, 比如說 Q(s2, a2) 的值比 Q(s2, a1) 的大, 所以我們把大的 Q(s2, a2) 乘上一個衰減值 gamma (比如是0.9) 並加上到達s2時所獲取的獎勵 R (這裡還沒有獲取到我們的棒棒糖, 所以獎勵為 0), 因為會獲取實實在在的獎勵 R , 我們將這個作為我現實中 Q(s1, a2) 的值, 但是我們之前是根據 Q 表估計 Q(s1, a2) 的值. 所以有了現實和估計值, 我們就能更新Q(s1, a2) , 根據 估計與現實的差距, 將這個差距乘以一個學習效率 alpha 累加上老的 Q(s1, a2) 的值 變成新的值.

但時刻記住, 我們雖然用 maxQ(s2) 估算了一下 s2 狀態, 但還沒有在 s2 做出任何的行為, s2 的行為決策要等到更新完了以後再重新另外做. 這就是 off-policy 的 Q learning 是如何決策和學習優化決策的過程.



$$\text{update = learing_rate * (q_target - q_predict)}$$

$$\text{學習率 * (真實值 - 預測值)}$$

我們想象 Qlearning 的機器人天生近視眼, \(\gamma= 1\) 時, 機器人有了一副合適的眼鏡, 在 s1 看到的 Q 是未來沒有任何衰變的獎勵, 也就是機器人能清清楚楚地看到之後所有步的全部價值, 但是當 \(\gamma= 0\) , 近視機器人沒了眼鏡, 只能摸到眼前的 reward, 同樣也就只在乎最近的大獎勵, 如果 \(\gamma\) 從 0 變到 1, 眼鏡的度數由淺變深, 對遠處的價值看得越清楚, 所以機器人漸漸變得有遠見, 不僅僅只看眼前的利益, 也為自己的未來著想.

 

7. Exploration and Exploitation 探索與利用

在上面的演算法中,我們可以看到需要使用某一個policy來生成動作,也就是說這個policy不是優化的那個policy,所以Q-Learning演算法叫做Off-policy的演算法。另一方面,因為Q-Learning完全不考慮model模型也就是環境的具體情況,只考慮看到的環境及reward,因此是model-free的方法。

回到policy的問題,那麼要選擇怎樣的 policy 來生成 action 呢?有兩種做法:

  • 隨機的生成一個動作
  • 根據當前的Q值計算出一個最優的動作,這個 policy \(\pi\) 稱之為 greedy policy 貪婪策略。也就是 \(\pi(S_{t+1}) = arg\max _aQ(S_{t+1},a)\)

使用隨機的動作就是 exploration,也就是探索未知的動作會產生的效果,有利於更新Q值,獲得更好的policy。

而使用 greedy policy 也就是 target policy 則是 exploitation,利用policy,這個相對來說就不好更新出更好的Q值,但可以得到更好的測試效果用於判斷演算法是否有效。

將兩者結合起來就是所謂的 \(\epsilon\ greedy\) 策略, \(\epsilon\) 一般是一個很小的值,作為選取隨機動作的概率值。可以更改 \(\epsilon\) 的值從而得到不同的 exploration 和 exploitation 的比例。例如 \(\epsilon = 0.1\) 表示 90% 的時間是選擇最優策略, 10% 的時間來探索.

要注意一點就是 egreedy 的 \(\epsilon\) 是不斷變小的,也就是隨機性不斷變小。怎麼理解呢?就是一開始需要更多的探索,所以動作偏隨機,慢慢的我們需要動作能夠有效,因此減少隨機。也就是越來越貪婪。
例如:
INITIAL_EPSILON = 0.5 # starting value of epsilon
FINAL_EPSILON = 0.01 # final value of epsilon

這裡需要說明的一點是使用 \(\epsilon-greedy\) 策略是一種極其簡單粗暴的方法,對於一些複雜的任務採用這種方法來探索未知空間是不可取的。因此,最近有越來越多的方法來改進這種探索機制。

 

8. 詳解Q-Learning

8.1 Value Function Approximation 價值函式近似

在簡單分析中,我們使用表格來表示Q(s,a),但是這個在現實的很多問題上是幾乎不可行的,因為狀態實在是太多。使用表格的方式根本存不下。

我們有必要對狀態的維度進行壓縮,解決辦法就是 價值函式近似 Value Function Approximation

就是用一個函式來表示Q(s,a),即:

$$Q(s,a) = f(s,a)$$

f可以是任意型別的函式,比如線性函式:

$$Q(s,a) = w_1s + w_2a + b$$
其中 \(w_1,w_2,b\) 是函式 \(f\) 的引數。

通過函式表示,我們就可以無所謂 \(s\) 到底是多大的維度,反正最後都通過矩陣運算降維輸出為單值的 \(Q\) 。這就是價值函式近似的基本思路。

如果我們就用 \(w\) 來統一表示函式f的引數,那麼就有

$$Q(s,a) = f(s,a,w)$$

為什麼叫近似,因為我們並不知道 \(Q\) 值的實際分佈情況,本質上就是用一個函式來近似 \(Q\) 值的分佈,所以,也可以說是

$$Q(s,a)\approx f(s,a,w)$$

 

8.2 Q值神經網路化!

用一個深度神經網路來表示這個函式 \(f\),即我們可以將狀態和動作當成神經網路的輸入, 然後經過神經網路分析後得到動作的 Q 值, 這樣我們就沒必要在表格中記錄 Q 值, 而是直接使用神經網路生成 Q 值.還有一種形式的是這樣, 我們也能只輸入狀態值, 輸出所有的動作值, 然後按照 Q learning 的原則, 直接選擇擁有最大值的動作當做下一步要做的動作。一般使用第二種形式。

以DQN為例,輸入是經過處理的4個連續的84x84影象,然後經過兩個卷積層,兩個全連線層,最後輸出包含每一個動作Q值的向量。

用神經網路來表示Q值非常簡單,Q值也就是變成用Q網路(Q-Network)來表示。接下來就到了很多人都會困惑的問題,那就是怎麼訓練Q網路???

我們知道,神經網路的訓練是一個最優化問題,最優化一個損失函式loss function,也就是標籤和網路輸出的偏差,目標是讓損失函式最小化。為此,我們需要有樣本,巨量的有標籤資料,然後通過反向傳播使用梯度下降的方法來更新神經網路的引數。

所以,要訓練Q網路,我們要能夠為Q網路提供有標籤的樣本。

所以,問題變成:

如何為 Q 網路提供有標籤的樣本?
答案就是利用 Q-Learning 演算法。

回想一下 Q-Learning 演算法,
$$Q(S_{t},A_{t}) \leftarrow Q(S_{t},A_{t})+\alpha({R_{t+1}+\lambda \max _aQ(S_{t+1},a)} - Q(S_t,A_t))$$

Q值的更新依靠什麼?依靠的是利用 Reward 和 Q 計算出來的目標Q值:

$$\text{Target-Q : }\ \ R_{t+1}+\lambda \max _aQ(S_{t+1},a)$$

因此,我們把目標Q值作為標籤不就完了?我們的目標不就是讓Q值趨近於目標Q值嗎?
因此,Q網路訓練的損失函式就是:



\(s^`,a^`\) 即下一個狀態和動作

既然確定了損失函式,也就是cost,確定了獲取樣本的方式。那麼DQN的整個演算法也就成型了!接下來就是具體如何訓練的問題了!



前邊提到,每一組 (state, action, reward, state_) 為一次序列:

  • state (observation) 為目前狀態,傳遞給 q-eval net 得到預計值 (即輸入狀態值, 輸出所有的動作值);
  • state_ 為下一步狀態,傳遞給 q-target net 得到目標值,之後可以得到 \(\max _aQ(S_{t+1},a)\) ,在之後得到 \(R_{t+1}+\lambda \max _aQ(S_{t+1},a)\)

最終的 \(loss\) 為:

self.loss = tf.reduce_mean(tf.squared_difference(self.q_target, self.q_eval))

再次注意,q-eval net 和 q-target net 網路結構完全一樣,只不過引數更新不同!(即 Fixed Q-targets 方法)








最基本的DQN,也就是NIPS 13版本的DQN:



那麼上面的演算法看起來那麼長,其實就是反覆試驗,然後儲存資料。接下來資料存到一定程度,就每次隨機採用資料,進行梯度下降!

也就是在DQN中增強學習 Q-Learning 演算法和深度學習的 SGD 訓練是同步進行的!
通過 Q-Learning 獲取無限量的訓練樣本,然後對神經網路進行訓練。

整體程式碼結構大致如下:

def run_maze():
    step = 0    # 用來控制什麼時候學習
    for episode in range(300):
        # 初始化環境
        observation = env.reset()

        while True:
            # 重新整理環境
            env.render()

            # DQN 根據觀測值選擇行為
            action = RL.choose_action(observation)

            # 環境根據行為給出下一個 state, reward, 是否終止
            observation_, reward, done = env.step(action)

            # DQN 儲存記憶
            RL.store_transition(observation, action, reward, observation_)

            # 控制學習起始時間和頻率 (先累積一些記憶再開始學習)
            if (step > 200) and (step % 5 == 0):
                RL.learn()

            # 將下一個 state_ 變為 下次迴圈的 state
            observation = observation_

            # 如果終止, 就跳出迴圈
            if done:
                break
            step += 1   # 總步數

    # end of game
    print('game over')
    env.destroy()


if __name__ == "__main__":
    env = Maze()
    RL = DeepQNetwork(env.n_actions, env.n_features,
                      learning_rate=0.01,
                      reward_decay=0.9,
                      e_greedy=0.9,
                      replace_target_iter=200,  # 每 200 步替換一次 target_net 的引數
                      memory_size=2000, # 記憶上限
                      # output_graph=True   # 是否輸出 tensorboard 檔案
                      )
    env.after(100, run_maze)
    env.mainloop()
    RL.plot_cost()  # 觀看神經網路的誤差曲線

 

8.3 Experience Replay 經驗回放

Q learning 是一種 off-policy 離線學習法, 它能學習當前經歷著的, 也能學習過去經歷過的, 甚至是學習別人的經歷. 所以每次 DQN 更新的時候, 我們都可以隨機抽取一些之前的經歷進行學習. 隨機抽取這種做法打亂了經歷之間的相關性, 也使得神經網路更新更有效率。

其將系統探索環境得到的資料儲存起來,然後隨機取樣樣本更新深度神經網路的引數(有了一個記憶庫之後再開始學習)。



Experience Replay 的動機是:

  • 深度神經網路作為有監督學習模型,要求資料滿足獨立同分布,
  • 但 Q Learning 演算法得到的樣本前後是有關係的。為了打破資料之間的關聯性,Experience Replay 方法通過儲存-取樣的方法將這個關聯性打破了。

之所以加入 experience replay 是因為樣本是從遊戲中的連續幀獲得的,這與簡單的 reinforcement learning 問題(比如maze)相比,樣本的關聯性大了很多,如果沒有 experience replay,演算法在連續一段時間內基本朝著同一個方向做 gradient descent,那麼同樣的步長下這樣直接計算 gradient 就有可能不收斂。因此 experience replay 是從一個 memory pool 中隨機選取了一些 experience,然後再求梯度,從而避免了這個問題。

原文的實驗中指出mini batch是32,而replay memory存了最近的1000000幀。

 

8.4 Fixed Q-targets

Fixed Q-targets 也是一種打亂相關性的機理, 如果使用 fixed Q-targets, 我們就會在 DQN 中使用到兩個結構完全相同但引數不同的神經網路 (有時差), 預測 Q 估計 的神經網路 (evaluate net) 具備最新的引數, 而預測 Q 現實 的神經網路 (target net) 使用的引數則是很久以前的

例如一開始有兩個完全一樣的網路,一個進行訓練,另一個不訓練,到了訓練10000次後,把訓練過的網路引數完全複製給凍結的網路,之後仍是一個訓練,持續更新引數,一個凍結,每10000次才更新一次。

target_net 用於預測 q_target 目標值, 他不會及時更新引數.

eval_net 用於預測 q_eval 估計值, 這個神經網路擁有最新的神經網路引數





 

8.5 總結

在 Q-Learning 演算法中,計算經驗得分的公式如下:

$$\text{Q(state, action) = Q(state, action) + }\alpha\text{ (R(state, action) + }\gamma \text{ Max[Q(next state, all actions)] - Q(state, action))}$$

當 \(\alpha\) 的值是 \(1\) 時,公式如下:

$$\text{Q(state, action) = R(state, action) +} \gamma\text{ Max[Q(next state, all actions)]}$$

  • state: 表示 Agent 當前狀態。
  • action: 表示 Agent 在當前狀態下要做的行為。
  • next state: 表示 Agent 在 state 狀態下執行了 action 行為後達到的新的狀態。
  • Q(state, action): 表示 Agent 在 state 狀態下執行了 action 行為後學習到的經驗,也就是經驗分數。
  • R(state, action): 表示 Agent 在 state 狀態下做 action 動作後得到的即時獎勵分數。
  • Max[Q(next state, all actions)]: 表示 Agent 在 next state 狀態下,自我的經驗中,最有價值的行為的經驗分數。
  • Gamma: \(\gamma\) ,表示折損率,也就是未來的經驗對當前狀態執行 action 的重要程度。



演算法流程:

Agent 通過經驗去學習。Agent將會從一個狀態到另一個狀態這樣去探索,直到它到達目標狀態。我們稱每一次這樣的探索為一個場景(episode)。

每個場景就是 Agent 從起始狀態到達目標狀態的過程。每次 Agent 到達了目標狀態,程式就會進入到下一個場景中。

  1. 初始化 Q 矩陣,並將初始值設定成 0
  2. 設定好引數 γ 和得分矩陣 R
  3. 迴圈遍歷場景(episode):

    1. 隨機初始化一個狀態 s
    2. 如果未達到目標狀態,則迴圈執行以下幾步:

      1. 在當前狀態 s 下,隨機選擇一個行為 a
      2. 執行行為 a 得到下一個狀態 s`
      3. 使用 \(\text{Q(state, action) = R(state, action) +} \gamma\text{ Max[Q(next state, all actions)]}\) 公式計算 \(\text{Q(state, action)}\)
      4. 將當前狀態 s 更新為 s`

參考

  1. DQN 從入門到放棄
  2. 經驗回放(Experience replay)
  3. 強化學習系列之九:Deep Q Network (DQN)
  4. 莫煩 PYTHON 強化學習 Reinforcement Learning