強化學習-Zee知根知底系列
搞科研、學習強化學習,重要在於知其然,然後知其所以然。
能夠搞清楚,怎麼實現強化學習,看源碼 看論文其實就可以做到。
但是要真正的抓住核心部分的知識,還是要多做自己的仿真實驗,然後認認真真的多看論文。
本系列文章,主要是針對當前主流深度強化學習的各種算法和Trick,分析其背後的原理,從而幫助你改進算法,更適應自己的環境。希望對大家有多幫助。
另外,我會將所有的文章及所做的一些簡單項目,放在我的個人網頁 上。
水平有限,可能有理解不到位的地方,希望大家主動溝通交流。
郵箱:[email protected]
強化學習-知根知底-深度理解值函數方法(一)
整個強化學習的學習過程是一個通過與環境交互中進行學習,尋優的過程。隨着環境給出的reward 不斷調整自身的從而得到最大的reward。值函數方法是強化學習算法中的一大門類。
一、值函數與Bellman方程
首先還是強調一下強化學習基礎知識, 任何強化學習算法都需要去估算一個agent所處的狀態和動作有多好,即估計值函數 動作值函數。值函數評估當前狀態的好壞,動作值函數評估當前狀態下做出該動作之後的好壞:
v π ( s ) ≐ E π [ G t ∣ S t = s ] = E π [ ∑ k = 0 ∞ γ k R t + k + 1 ∣ S t = s ] , for all s ∈ S
v_{\pi}(s) \doteq \mathbb{E}_{\pi}\left[G_{t} | S_{t}=s\right]=\mathbb{E}_{\pi}\left[\sum_{k=0}^{\infty} \gamma^{k} R_{t+k+1} | S_{t}=s\right], \text { for all } s \in \mathcal{S}
v π ( s ) ≐ E π [ G t ∣ S t = s ] = E π [ k = 0 ∑ ∞ γ k R t + k + 1 ∣ S t = s ] , for all s ∈ S
q π ( s , a ) ≐ E π [ G t ∣ S t = s , A t = a ] = E π [ ∑ k = 0 ∞ γ k R t + k + 1 ∣ S t = s , A t = a ]
q_{\pi}(s, a) \doteq \mathbb{E}_{\pi}\left[G_{t} | S_{t}=s, A_{t}=a\right]=\mathbb{E}_{\pi}\left[\sum_{k=0}^{\infty} \gamma^{k} R_{t+k+1} | S_{t}=s, A_{t}=a\right]
q π ( s , a ) ≐ E π [ G t ∣ S t = s , A t = a ] = E π [ k = 0 ∑ ∞ γ k R t + k + 1 ∣ S t = s , A t = a ]
根據bellman方程:
v π ( s ) ≐ E π [ G t ∣ S t = s ] = E π [ R t + 1 + γ G t + 1 ∣ S t = s ] = ∑ a π ( a ∣ s ) ∑ s ′ ∑ r p ( s ′ , r ∣ s , a ) [ r s , a + γ E π [ G t + 1 ∣ S t + 1 = s ′ ] ] = ∑ a π ( a ∣ s ) ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r s , a + γ v π ( s ′ ) ] , for all s ∈ S
\begin{aligned} v_{\pi}(s) & \doteq \mathbb{E}_{\pi}\left[G_{t} | S_{t}=s\right] \\ &=\mathbb{E}_{\pi}\left[R_{t+1}+\gamma G_{t+1} | S_{t}=s\right] \\ &=\sum_{a} \pi(a | s) \sum_{s^{\prime}} \sum_{r} p\left(s^{\prime}, r | s, a\right)\left[r_{s,a}+\gamma \mathbb{E}_{\pi}\left[G_{t+1} | S_{t+1}=s^{\prime}\right]\right] \\ &=\sum_{a} \pi(a | s) \sum_{s^{\prime}, r} p\left(s^{\prime}, r | s, a\right)\left[r_{s,a}+\gamma v_{\pi}\left(s^{\prime}\right)\right], \quad \text { for all } s \in \mathcal{S} \end{aligned}
v π ( s ) ≐ E π [ G t ∣ S t = s ] = E π [ R t + 1 + γ G t + 1 ∣ S t = s ] = a ∑ π ( a ∣ s ) s ′ ∑ r ∑ p ( s ′ , r ∣ s , a ) [ r s , a + γ E π [ G t + 1 ∣ S t + 1 = s ′ ] ] = a ∑ π ( a ∣ s ) s ′ , r ∑ p ( s ′ , r ∣ s , a ) [ r s , a + γ v π ( s ′ ) ] , for all s ∈ S
公式解讀 :
從這個狀態到下一個狀態,首先根據策略π \pi π 來選擇動作 ,然後以一定的概率到達下一個狀態,
所以對應第二步 到 第三步 爲 策略π \pi π 每一個動作的概率 乘以該動作之後的所有可能到達狀態概率 再乘 $R_{t+1}+\gamma G_{t+1} $ 。
然而 此時 r s , a r_{s,a} r s , a 是確定的,但是G t + 1 G_{t+1} G t + 1 是不確定的 ,所以 還需要對G t + 1 G_{t+1} G t + 1 繼續求期望,也就是下一步的值函數。
q π ( s , a ) ≐ E π [ G t ∣ S t = s , A t = a ] = E π [ R t + 1 + γ G t + 1 ∣ S t = s , A t = a ] = ∑ s ′ p ( s ′ , r ∣ s , a ) [ r + γ v π ( s ′ ) ] = ∑ s ′ p ( s ′ , r ∣ s , a ) [ r + γ ∑ a ′ π ( a ′ ∣ s ′ ) q π ( s ′ , a ′ ) ]
\begin{aligned} q_{\pi}(s,a) & \doteq \mathbb{E}_{\pi}\left[G_{t} | S_{t}=s, A_{t}=a\right] \\ &=\mathbb{E}_{\pi}\left[R_{t+1}+\gamma G_{t+1} | S_{t}=s,A_{t}=a\right]\\ &=\sum_{s^{\prime}} p\left(s^{\prime}, r | s, a\right)\left[r+\gamma v_{\pi}\left(s^{\prime}\right)\right] \\ &=\sum_{s^{\prime}} p\left(s^{\prime}, r | s, a\right)\left[r+\gamma \sum_{a'}\pi(a'| s') q_{\pi}\left(s^{\prime},a'\right)\right] \end{aligned}
q π ( s , a ) ≐ E π [ G t ∣ S t = s , A t = a ] = E π [ R t + 1 + γ G t + 1 ∣ S t = s , A t = a ] = s ′ ∑ p ( s ′ , r ∣ s , a ) [ r + γ v π ( s ′ ) ] = s ′ ∑ p ( s ′ , r ∣ s , a ) [ r + γ a ′ ∑ π ( a ′ ∣ s ′ ) q π ( s ′ , a ′ ) ]
公式解讀 :
與上一個類似,但是此時已經選擇好了動作a a a ,所以直接省去策略π \pi π 的概率。這裏用到了V V V 和Q Q Q 的關係
V ( s ) = ∑ π ( a ∣ s ) ∗ Q ( s , a )
V(s)=\sum \pi(a | s) * Q(s, a)
V ( s ) = ∑ π ( a ∣ s ) ∗ Q ( s , a )
Q ( s , a ) = ∑ P ( s ′ , r ∣ s , a ) ∗ ( r + γ V ( s ′ ) )
{Q(s, a)=\sum P\left(s^{\prime}, r | s, a\right) *\left(r+\gamma V\left(s^{\prime}\right)\right)}
Q ( s , a ) = ∑ P ( s ′ , r ∣ s , a ) ∗ ( r + γ V ( s ′ ) )
bellman方程說明當前狀態的值函數可以用下一個時刻所有的值函數來表示。然後進行迭代求解。可以看出值函數與策略息息相關,其實值函數就是去描述策略的好壞的。所以最優的策略的目的就是使得值函數能夠達到最大。
針對公式3,一個最優的策略一定是將當前狀態下的最優動作選擇出來,也就是
V ( s ) = max a Q π ∗ ( s , a ) = max a ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ v ∗ ( s ′ ) ]
V(s)=\mathop {\max }\limits_a Q_{\pi*}(s, a)=\max _{a} \sum_{s^{\prime}, r} p\left(s^{\prime}, r | s, a\right)\left[r+\gamma v_{*}\left(s^{\prime}\right)\right]
V ( s ) = a max Q π ∗ ( s , a ) = a max s ′ , r ∑ p ( s ′ , r ∣ s , a ) [ r + γ v ∗ ( s ′ ) ]
同理
q ∗ ( s , a ) = ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ max a ′ q ∗ ( s ′ , a ′ ) ]
q_{*}(s, a) =\sum_{s^{\prime}, r} p\left(s^{\prime}, r | s, a\right)\left[r+\gamma \max _{a^{\prime}} q_{*}\left(s^{\prime}, a^{\prime}\right)\right]
q ∗ ( s , a ) = s ′ , r ∑ p ( s ′ , r ∣ s , a ) [ r + γ a ′ max q ∗ ( s ′ , a ′ ) ]
其實對比5、6式與bellman 方程之間的差距就是一個 π \pi π , π \pi π 總可以使得下一步的最大的q q q 選擇出來。
然而最優策略的主要原因在於沒有辦法知道最優的值函數 和 動作值函數。
目前,解決該問題主要有三種算法動態規劃、蒙特卡洛、TD差分方法。
二 動態規劃
動態規劃方法中,假設我們已經知道了所有的轉移概率p p p 和每個情況下的r,那麼根據值函數的bellman等式,我們把一個固定的策略代入之後,通過迭代的方式就可以求出該策略下的值函數。這個過程叫做策略估計。
算法如下:
隨機初始化V ( s ) V(s) V ( s )
循環:
令Δ \Delta Δ =0
循環:
v ← V ( s ) V ( s ) ← ∑ a π ( a ∣ s ) ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ V ( s ′ ) ] Δ ← max ( Δ , ∣ v − V ( s ) ∣ ) \begin{array}{l}{v \leftarrow V(s)} \\ {V(s) \leftarrow \sum_{a} \pi(a | s) \sum_{s^{\prime}, r} p\left(s^{\prime}, r | s, a\right)\left[r+\gamma V\left(s^{\prime}\right)\right]} \\ {\Delta \leftarrow \max (\Delta,|v-V(s)|)}\end{array} v ← V ( s ) V ( s ) ← ∑ a π ( a ∣ s ) ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ V ( s ′ ) ] Δ ← max ( Δ , ∣ v − V ( s ) ∣ )
結束循環 當 Δ < θ \Delta<\theta Δ < θ
這樣我們已經知道該策略下準確的值函數,根據公式(4)自然可以根據當前值函數 計算出 動作狀態值函數 q q q 。此時如果我們發現存在動作a使得 q π ( s , a ) ≥ v π ( s ) q_{\pi}\left(s, a\right) \geq v_{\pi}(s) q π ( s , a ) ≥ v π ( s ) 那麼就說明 該動作至少比原來用策略π \pi π 時選擇的動作的期望要好。所以可以改變策略π \pi π 使得其更好。這個過程叫做策略提升。
結合整個過程 ,就是動態規劃方法。
然而實際上,上述方法必須已經得到所有狀態下,所有動作的獎勵值 才能計算更新的值函數,然而往往這是做不到的。因爲複雜度太高 要完成很多次纔可以採到,所以將原來迭代求解值函數的公式改變爲:
V ( s ) ← ∑ s ′ , r p ( s ′ , r ∣ s , π ( s ) ) [ r + γ V ( s ′ ) ]
V(s) \leftarrow \sum_{s^{\prime}, r} p\left(s^{\prime}, r | s, \pi(s)\right)\left[r+\gamma V\left(s^{\prime}\right)\right]
V ( s ) ← s ′ , r ∑ p ( s ′ , r ∣ s , π ( s ) ) [ r + γ V ( s ′ ) ]
總結之後 就可以得到:
可以看出的是 該算法是一個確定性的策略,也就是說 每個狀態下,只能選擇固定的動作,同樣在更新的時候依舊是選擇最好的動作進行更新。
三 蒙特卡洛算法
動態規劃算法,可以非常有效的進行求解馬爾科夫決策過程,但是往往我們需要所有的狀態轉移概率。這個實際上是不滿足的,比如說兩個人下圍棋,我下一個子之後,我並不知道對手下在哪裏。同樣,如果在控制機器人手臂抓握東西的時候,我們雖然知道了控制哪個關節轉動了30度,但是我們要建模手臂動了之後所抓握的東西變成什麼樣是一件非常困難的事情。
這樣我們就需要model-free的算法。也就是,如果我們不知道系統的模型是什麼樣的時候,我們怎麼求解這個問題。
首先,直接觀察強化學習的目標,如果 我們已經可以估計得到公式(1)、(2)的期望的G t G_t G t ,那麼直接用這個期望的G t G_t G t 來計算值函數就可以了。蒙特卡洛算法的思路是直接根據採用了平均採樣彙報來估算值函數、動作值函數的方法。直接上算法:
初始化策略π \pi π 和值函數V V V ;
循環:
利用策略π \pi π 與環境交互,這樣可以得到 K個軌跡 ,每個軌跡都可以表示爲:S 0 , A 0 , S 1 , A 1 , S 2 , A 2 , S 3 , A 3 , … , S T , A T S_0,A_0,S_1,A_1,S_2,A_2,S_3,A_3,…,S_T,A_T S 0 , A 0 , S 1 , A 1 , S 2 , A 2 , S 3 , A 3 , … , S T , A T ;
令G=0;
循環每一個軌跡,從T ->T-1 ->……>1:
直接計算G = γ G + R t + 1 G=\gamma G+R_{t+1} G = γ G + R t + 1
算法一(first-visit Monte Carlo estimating V V V ):如果S t S_t S t 第一次出現,那麼令V ( S t ) = G V(S_t)=G V ( S t ) = G
算法二(every-visit Monte Carlo estimating V V V ):每當S t S_t S t 出現,則記錄G G G 。 當所有循環結束 令V ( S t ) = m e a n ( G ) V(S_t)=mean(G) V ( S t ) = m e a n ( G ) 。
算法三(every-visit Monte Carlo estimating G G G ):每當S t , A t S_t,A_t S t , A t 出現,則記錄G G G 。 當所有循環結束 令G ( S t , A t ) = m e a n ( G ) G(S_t,A_t)=mean(G) G ( S t , A t ) = m e a n ( G ) 。
更新策略:
π ( s ) ≐ arg max a q ( s , a ) \pi(s) \doteq \arg \max _{a} q(s, a) π ( s ) ≐ arg max a q ( s , a ) (貪婪策略)
上述算法中,算法一、算法二已經漸漸被算法三替代。
主要原因是首先從本質上來講,如果不知道轉移概率,單純估計狀態值函數是一件誤差很大的事兒。
這個道理很簡單,對比V V V 函數和Q Q Q 函數的bellman方程,可以看出的V V V 函數估計受到了策略估計影響要大於Q Q Q 函數的,在所有的reward都是沒有誤差的狀態下,從狀態S t S_t S t 到下一步S t + 1 S_{t+1} S t + 1 , 這個S t + 1 S_{t+1} S t + 1 可能有很多種,因爲不確定動作,也不確定轉移概率,所以就是經過了2次隨機。但是在有限次的採樣中,很難反應出來。但是我們都對其平均了,也就是讓其轉移概率都近似於一致。但是如果確定了動作狀態對,那麼就相當於取消了一次不確定的動作。但是如果採用了確定性策略,也就是每當達到狀態S t S_t S t 的時候,一定做出動作A t A_t A t ,那麼這個時候V V V 和Q Q Q 其實是一樣的,也就沒什麼區別了。
Temporal-Difference (時序差分)方法
其實TD算法其實與蒙特卡洛類似,面對的是沒有辦法拿到轉移概率的時候的強化學習問題。 那麼在這個問題下,假如環境沒有終點,可以一直無限的運行下去,那麼蒙特卡洛算法就顯出了局限性。其次,蒙特卡洛算法採樣效率更低,具體對比請看第二篇博文。所以我們想找到一個樣本利用率更高的算法。
假如說,在與環境交互的時候,每次到達狀態S t S_{t} S t 之後,已知了該狀態下的損失獎勵值估計值G t G_t G t ,那麼更新其值函數V ( S t ) V\left(S_{t}\right) V ( S t ) 可以用下式來表示:
V ( S t ) ← V ( S t ) + α [ G t − V ( S t ) ]
V\left(S_{t}\right) \leftarrow V\left(S_{t}\right)+\alpha\left[G_{t}-V\left(S_{t}\right)\right]
V ( S t ) ← V ( S t ) + α [ G t − V ( S t ) ]
根據上式,即使損失獎勵值估計值G t G_t G t 每次都不是那麼準確的時候或者存在噪聲的時候,始終可以使得該值函數收斂。但是上式中,始終存在一些問題,因爲損失獎勵值估計值G t G_t G t 是比較難估計的。所以更近一步,如果我們利用bellman方程的第二步,即已有的值函數去代替原來的損失獎勵值估計值G t G_t G t 。這樣就可以進行循環的迭代,從而得到下式:
V ( S t ) ← V ( S t ) + α [ R t + 1 + γ V ( S t + 1 ) − V ( S t ) ]
V\left(S_{t}\right) \leftarrow V\left(S_{t}\right)+\alpha\left[R_{t+1}+\gamma V\left(S_{t+1}\right)-V\left(S_{t}\right)\right]
V ( S t ) ← V ( S t ) + α [ R t + 1 + γ V ( S t + 1 ) − V ( S t ) ]
根據上式來更新的算法叫做TD(0)算法。
初始化策略π \pi π 和值函數V V V ;
循環:
根據策略π \pi π 選擇狀態S S S 下的動作A A A ,並執行該動作A A A 。
從環境得到獎勵R R R , S ′ S' S ′ 。
根據該樣本更新值函數V ( S t ) ← V ( S t ) + α [ R t + 1 + γ V ( S t + 1 ) − V ( S t ) ] V\left(S_{t}\right) \leftarrow V\left(S_{t}\right)+\alpha\left[R_{t+1}+\gamma V\left(S_{t+1}\right)-V\left(S_{t}\right)\right] V ( S t ) ← V ( S t ) + α [ R t + 1 + γ V ( S t + 1 ) − V ( S t ) ]
更新策略:
π ( s ) ≐ arg max a q ( s , a ) \pi(s) \doteq \arg \max _{a} q(s, a) π ( s ) ≐ arg max a q ( s , a ) (貪婪策略)
結束循環直到V ( S t ) V\left(S_{t}\right) V ( S t ) 不在變化。
在這個算法的基礎上,又演化出了一系列的算法,包括著名的Q-learning算法。