1. 程式人生 > >強化學習導論 第四章 動態規劃

強化學習導論 第四章 動態規劃


 

這一篇來講一下第四章,動態規劃。

DP這個詞,指的是一系列的演算法,這些演算法主要用來解決:當我有了一個可以完美模擬馬爾可夫過程的模型之後,如何計算最優policies的問題。注意是policies,表明最優的策略可能不止一個。經典的DP演算法在強化學習中的應用受限的原因有兩個:一個是強假設滿足不了,就是無法保證我能先有一個完美的模型來描述整個馬爾可夫過程;另一個就是計算開銷太大。但這仍掩蓋不了其理論上的重要性。DP可以幫助我們更好地理解本書餘下部分討論的方法。事實上,這些方法都可以看成是儘可能的獲得跟DP一樣的效果,只是在強假設條件和計算開銷上進行了優化。

從這章開始,我們假設我們面對的環境是有限MDP過程,也就是它的狀態集合S和動作集合A(s),\;s \in S

,都是有限的。其動態特性由一系列的狀態轉移矩陣給出: P(s',r|s,a)

當前reward的期望由下式給出:

r(s,a,s')=E[R_{t+1}|S_t=s,A_t=a,S_{t+1}=s']

儘管DP思想可以用於連續性的狀態空間和動作空間,精確解只有在特定情形下才能得到。獲得連續空間下的近似解的一種常用方法是把連續空間進行數值化變換,然後使用有限馬爾可夫方法。我們第九章討論的方法可以用於連續空間下的問題。

DP的核心思想,就是使用value function作為依據,指導policies的搜尋過程。這一章我們討論如何使用DP來計算第三章定義的value function。正如我們討論過的,一旦我們找到了滿足bellman 最優方程的最優value functions,我們就能找到最優policies。

回顧一下最優value function的定義:

或者:

正如我們將要看到的那樣,DP演算法做的事情就是把這些bellman functions轉變成優化value functions近似值的更新規則。

4.1 policy evaluation

首先我們來看一下如何計算對應任一policy的value function。這個叫做策略評估。我們也稱之為prediction problem。回憶一下第三章,對於所有s \in S

這裡\pi(a|s)表示在policy為\pi,狀態為s的情況下,action為a的概率。這個value function和上一段描述的並沒有本質不同,只是多了policy的限制。只要滿足\gamma <1

或者在策略\pi的情況下,所有的從狀態s起始的路徑都會有終止狀態,那麼這個valun function就是存在且唯一的。

如果環境的動態轉移特性是完全可知的,那麼上式其實就是|S|個線性方程,帶有|S|個未知數。在這種情況下,暴力解是可行的,也是是確定的。對於我們來說,迭代的計算方式是最適合的。假設我們有一系列的近似value function:v_0,v_1,v_2,每一個都把狀態集合S對映到實數集R。最初的近似value function:v_0,是任意選擇的(注意這裡的0是指初始的value function,不是指狀態的開始。事實上,每個迭代的value function都對所有的狀態有個對應的實數對映。這也是為何後面會收斂於真實的v_{\pi}的原因)。然後後面的每一個近似value function都按照上式迭代求解。事實上,隨著迭代的進行,最終value function會逐漸收斂於v_{\pi}。這個演算法叫做iterative policy evaluation。

為了從v_k得到後續的v_{k+1},iterative policy evaluation針對每個狀態s進行相同的操作如下:把當前狀態s的value更新成一個新的value,這個新的value是由之後一個狀態的舊的value和瞬時期望獎勵,沿著所有可能的狀態轉移概率求和得到(仔細閱讀上述公式)。我們把這個迭代操作叫做full backup。這個演算法中的每一輪迭代操作都反向把所有狀態的value值都推算(更新)一次,最後產生新的下一個v_{k+1}。DP中的反向操作都是full back up,因為每次操作都把所有可能的後續狀態都涉及到了,而不是指取樣某一個後續狀態。

如果你想寫一個描述iterative policy evaluation演算法的程式,那麼你應該由兩個陣列,其中一個儲存v_k(s),另一個儲存v_{k+1}(s)。這樣的話,新的value就可以在不改變舊value值的情況下被一個個計算出來。當然只使用一個數組更容易,可以用“in place”的方式更新value。這種方式下,某個狀態更新後的value就會實時的覆蓋掉舊的value。由於不同狀態的更新順序不一樣,有時候不能保證上述公式右邊部分都用的是同一時刻某狀態舊的value(可以這麼理解:有時候恰好某個狀態A的value更新較頻繁,因為它與其他狀態聯絡比較多,這樣有可能下一次其他狀態用到的A的value就是其更新兩次或多次之後的)。這個稍微有些不同的演算法同樣最後收斂於v_{\pi}。事實上,它收斂的更快,因為每次只用某狀態最新的value。對於這種“in place”的演算法,狀態被涉及到的順序對收斂速度有著很大的影響。當我們考慮DP演算法的時候,通常都考慮“in place”形式。虛擬碼如下:

雖然iterative policy evaluation演算法最終肯定會收斂,但是實際程式中我們需要設定一個終止條件。一個典型的終止條件就是當\max_{s \in S }|v_{k+1}(s)-v_{k}(s)|的值非常小的時候,就讓程式停止。

4.2 policy improvment

我們之所以要在某個policy下計算value function,是因為我們想要評估policy的好壞。假定我們已經確定了某一個policy下的value function v_{\pi}。那麼對於一些狀態s,我們想要進一步知道是不是可以改變一下policy來選擇另外一個和當前policy的決定不一樣的動作a \neq \pi(s)。換句話說,我們已經知道當前的policy有多好了,那麼改變成另一個policy是好一點呢還是壞一點呢?一個方法就是在當前s下選擇你想選的a,然後繼續按照已有的policy v_{\pi}走下去。這時的value迭代公式如下:

這裡的關鍵點就在於上式和v_{\pi}(s)的大小比較。如果上式比v_{\pi}(s)大,那麼就是說當我在狀態為s的時候選擇a,然後繼續按照policy \pi走下去,比我一直按照policy \pi走下去好,那麼當我每次遇到狀態s的時候,最好還是選擇a。這樣的一個policy就是一個好一點的new policy。

這時候一定會有人疑惑,剛才說的狀態s,只是某一個狀態,難道說在某一個狀態下更好,就意味著真的更好?如果在其他的狀態下反而不好怎麼辦?good question。這就是接下來要說的,policy improvment theorem。嚴格的數學的語言我就省略了,反正你只要知道,只要你發現在某個狀態下有更好的選擇a,那麼保證其他選擇都不變的情況下,這個新的policy一定在所有狀態下都比前一個policy好!美妙啊!!我把證明貼上來,以防有人追根問底:

按照上述結論,我們考慮一下greedy policy \pi

greedy policy採取的動作是短期內最優的,但是這個短期指的是多看了一步。通過上式,可以看出greedy policy滿足policy improvment theorem,因此,它一定比已有的policy更好或者至少一樣好。這種通過構建greedy policy來得到更好的一個policy的方式,就叫做策略改進。

假設greedy policy和原有的policy一樣好,也就是滿足下式:

那麼,這個方程看起來和bellman optimality value function是一模一樣的,也就是說,原有的policy一定是最優policy。換句話說,policy improvment一定會給我們一個更好地policy,除非我們當前的policy已經是最優的了。

到目前為止,我們討論的policy都是確定性的。在更廣泛的意義上,policy是隨機概率性的,比如\pi(a|s)。我們不去處理細節,但是這一節的思想可以無縫銜接到概率化的policy。

除此之外,如果有多個動作同時都可以得到相同的max value,那麼在概率化的policy中我們不會去選其中之一,而是其中的每一個動作都會被以一定的概率選到。

4.3 policy iteration

一旦某個策略\pi,經過policy improvement之後變成了一個更好地policy \pi',那麼我們就能在此基礎上進一步優化成更好的policy \pi'',於是我們就能得到下圖所示的更新序列:

其中帶有E的箭頭表示policy evaluation,帶有I的箭頭表示policy improvement。每一個當前的policy,除非它已經是最優的,否則必然有一個better policy。由於有限馬爾可夫過程的policy是有限的,那麼這個過程一定會在有限的迭代次數後收斂於最優的policy。

上述這種找到最優policy的方法叫做policy iteration。下圖給出了一個完整的演算法。需要注意的是,上述序列的每一個policy evaluation 的過程,其本身也是一個iteration過程,以上一個policy的value function開始。這就加快了policy evaluation收斂的速度。

policy iteration經常會在有限的幾個迭代後就收斂了。看一下下圖的情形:左邊的一列是隨機策略下的value function在不同k下的evaluation過程;右邊一列是對應每個k的value function結果的greedy policy。(這裡要多說幾句,以免誤解了這個圖的含義和上面的講解:需要注意的是,如果按照前面policy evaluation的規則,應該是在v_{k}收斂之後,才根據收斂的v_{k}確定一個greedy policy;而這裡在k=1,k=2時都給出了相應的greedy policy,是為了後面的value iteration做鋪墊,為了告訴讀者,有時不需要等到v_{k}徹底收斂才確定greedy policy)

下面給出完整的policy iteration的演算法虛擬碼:

這份虛擬碼裡面有個小bug,就是當最終policy收斂於最優的時候,可能不會停止迭代,而是不斷的在幾個最優的policy之間來回跳躍。

4.4 value iteration

policy iteration演算法的一個缺點是其迭代過程每次都包含一次policy evaluation,而這個policy evalution過程本身就是一遍遍的迭代。當然,等到policy evaluation徹底結束是好的,因為可以保證v_{k}精確地收斂到v_{\pi}。然而我們必須要這個精確的收斂嗎?我們能不能在中間就停止evaluation過程以加快收斂速度呢?上面給出的那個圖就告訴我們,有時候提前終止evaluation過程其實也能得到最優policy。

事實上,上面的猜想是肯定的,的確可以通過某些方式來縮短evaluation的過程,同時又不會損失收斂性。其中一個特別的方式就是當所有狀態都遍歷一遍後,停止evaluation過程。這個演算法就叫做value iteration。公式如下:

另外一個理解value iteration的方式是參考貝爾曼最優方程。我們注意到value iteration本質上是簡單地把貝爾曼最優方程轉化成一個更新規則。同意注意到value iteration的backup過程和之前的policy evaluation的backup過程是一模一樣的,只是在value iteration過程中每次我們都需要所有動作中獲得上式最大值的那個。

最後,我們需要考慮一下value iteration如何終止。和policy evaluation相同,我們理論上需要無限次迭代使v_{k}收斂到v_{*}。在實際應用中,我們在相鄰兩次遍歷狀態的v_{k}的差值非常小時,就停止執行。

我們可以看出,value iteration高效地結合了policy evaluation和policy improvement,這樣就獲得了更快的收斂速度。總體來講,這一大類的policy iteration演算法都可以看作是一系列的遍歷序列,一部分遍歷序列使用了policy evaluation的backup,另一部分使用了value iteration的backup。因為僅有的不同之處只是上式中的max操作,因為我們可以認為是把一些max操作加入了policy evaluation過程。所有這些演算法對於discounted finite MDP來說都會收斂到最優policy。

4.5 Asynchronous Dynamic Programming

到目前為止,我們討論的DP演算法的一個較大的缺陷是我們必須使用整個狀態集。如果狀態集數量非常大,那麼就算是單次遍歷也非常耗時。

非同步DP演算法是這樣一類實時迭代式DP演算法:它不要求規範系統的遍歷順序。它們可以按照任意順序進行反向計算過程,而不管當時計算時遇到的狀態價值是不是同步更新的。為了使得收斂準確性不受影響,非同步DP演算法必須要遍歷過所有的狀態價值:它不能在計算過程中刻意忽略一些狀態。非同步DP演算法帶來了很大的靈活性,使得我們可以去選擇使用哪些狀態做反向計算。

比如:有某個非同步value iteration演算法在每一步只是反向更新一個狀態s_{k}。如果0 \leq \gamma < 1,那麼當且僅當所有的狀態在{s_{k}}序列中出現無窮多次,最終的價值函式才能收斂於v_{*}。儘管這些不太常見的非同步DP演算法的細節討論超出了本書的範圍,我們依然可以很清晰的看出一些特別的backup方式使得很多非遍歷形式的DP演算法變得更加靈活。

誠然,儘可能地避免遍歷過程並非意味著我們可以有很少的計算量。它只是意味著我們可以適當的逃離一些毫無意義的遍歷過程。我們可以利用這種靈活性去選擇那些真正能讓演算法效率更高的狀態價值去遍歷。我們甚至可以直接跳過那些對實際最優行為無關的狀態不去遍歷。第8章討論了這類問題。

非同步DP同時也使得我們可以在實時的互動過程中加入計算過程。為了解決一個MDP問題,我們可以在執行機構與環境互動作用的同時,執行之前討論的那些迭代式DP演算法。agent的經驗可以幫助決定哪些狀態需要反向計算;同時,最新的價值函式和policy資訊也可以幫助agent來做出決策。這樣可以讓DP演算法的反向計算過程集中於那些真正和agent相關的狀態。這種區域性集中的思想在強化學習中被再三強調。

4.6 Generalized Policy Iteration

policy iteration包含兩個即同時發生,又相互影響的過程。其中一個過程使value function和當前的policy保持一致(policy evaluation),而另一個過程依據當前的value function給出greedy policy。在policy iteration中,這兩個子過程交替進行,但是並非真的必要。比如在value iteration中,兩次policy improvement之間只有一次evaluation的迭代過程。在非同步DP方法中,上述兩個子過程的交錯更加精細:在有些情況下,一個過程中僅有一個狀態被更新。其實只要能保證所有狀態都能被持續遍歷,其具體順序是不太重要的,因為最終的結果都是一樣的--收斂於最優value function和最優policy。

我們用一個名詞“generalized policy iteration”(GPI)來表徵廣泛意義上的上述兩個子過程,而不去過分關注細節。幾乎所有的強化學習方法都可以用GPI來很好的表述。也就是說,所有這些方法都有相似的內涵:policy永遠是根據value function來進行improvement過程;而value function一直被驅使成為當前policy下的最優value function。下圖可以很清楚地描述這種相互過程:

很容易看出如果improvement和evaluation過程都基本穩定下來了,也就是不再有很大的變化,那麼當前的value function和policy一定是最優的。這種情況也是貝爾曼最優方程成立的情形,因此value function和policy一定同時是最優的。

GPI中的evaluation和improvement過程可以說是既相互競爭,又在相互協作。說它們相互競爭意思是這個過程在向著相反的方向走:根據當前的value function把policy變成greedy形式,其實就是否定了當前value function相對於改變後的greedy policy的正確性;而對value function進行更新使之和當前policy相一致,也就意味著當前的policy對於更新後的value function來說,不再greedy。在長期互動作用中,這兩個子過程卻可以找到同一個最終答案:最優的policy和最優的value function。

我們也可以如下圖這樣考慮:

儘管真實的情形比這個圖要複雜,但是該圖的確反映了一些抽象的內在含義。每個子過程(指的是improvement和evaluation其中之一)都在驅使value function或者policy向著兩個目標其中之一前進(兩個目標指的是上下兩條成角度的線)。儘管向著其中一個目標前進必然離另一個目標遠一些,但是因為最終兩條線有共同的交點,也就是最終會達到唯一的solution:optimal value function和optimal policy。

4.7 Efficiency of Dynamic Programming

DP演算法對於規模非常大的問題也許不太適用,但是相比其他解決MDP問題的方法,已經高效很多。如果我們忽略一些技術細節,其實DP演算法的worst case時間複雜度是基於狀態集個動作集數量之和的多項式複雜度。就算所有policies的總數是m^n,DP演算法也總能保證在多項式複雜度的時間內找到最優解。在這個層面上,DP比直接對policies集合進行搜尋快指數倍,因為直接搜尋需要詳盡地檢查每一個policy。線性規劃方法也可以用於解決MDP問題,並且在一些情況下其worst-case的收斂速度要好於DP。但是在很多小規模的問題中,線性規劃表現的並不好。對於超大型的問題,只有DP是可行的。

DP有時被認為會受限於“維度災難”的問題而不能得到廣泛運用,也就是隨著狀態變數的增多,狀態數量會成指數倍的飆升。過大的狀態集的確帶來困難,但那是問題內在的困難,並非DP的困難。事實上,DP對於大型問題的效果要比暴力搜尋和線性規劃強的多。

實際應用中,使用現代計算機,DP可以完成百萬級別狀態數的MDP問題的解決。policy iteration和value iteration方法都用的很廣泛,很難說哪一種更好。實際中,這些方法的收斂速度比它們理論上的worst case的收斂速度都要快的多,尤其是當初始value function或者policy的設定很恰當的時候。

對於超大型規模的狀態集,非同步DP演算法更加受到追捧。對於同步DP演算法來說,當連單次狀態集的遍歷也變得不可行的時候,問題依舊可以解決。其實,並非所有的狀態對於最優解都是必須的。這時候非同步DP演算法就可以站出來解決這類問題,往往會得到比同步DP演算法更快更好的結果。

4.8 Summary

這一章我們熟悉了用以解決MDP類問題的動態規劃演算法的基本概念。Policy evaluation指的是按照給定policy進行value function的迭代計算;policy improvement指的是按照當前的value function進行policy的改進。把這兩部分合並在一個過程裡,我們得到了policy iteration和value iteration。它倆之中任何一個都可以高效解決finite MDP問題。

經典DP演算法對整個狀態集進行遍歷,對每一個狀態進行“反向更新”(full backup)計算。每一次backup依據所有可能的後續狀態和轉移概率來更新狀態的value。Full backup過程和貝爾曼方程很像:只不過是把貝爾曼方程轉化成了賦值規則。當backup計算不再變化時,說明這個時候的values已經收斂到可以滿足貝爾曼方程了。為了直觀看出backup過程,我們可以使用backup diagram(上文給出了)。

深入分析DP演算法或者所有的強化學習演算法的本質,我們可以把他們都看作是GPI(generalized policy iteration)。GPI包含兩個互相作用的子過程:其中一個根據給定的policy改變value function,使value function給符合當下的policy;另一個根據value function改變policy,使policy更好。這倆過程看起來是在拆對方的臺,但事實上最終會得到最優的結果。在一些情況下,GPI可被證明收斂,另一些情況下,雖然GPI不一定收斂,但是仍幫助我們理解這類方法的內涵。

有時並不一定非得遍歷所有狀態:非同步DP就是這種以任意順序遍歷狀態的方法,甚至是隨機遍歷或者使用過時的value資訊。

最後,我們注意到DP演算法的最後一個重要性質:它們都在其他estimates的基礎上更新某個estimates。我們把這種思想叫做:bootstrapping(所謂的Bootstrapping法就是利用有限的樣本資料經由多次重複抽樣,重新建立起足以代表母體樣本分佈之新樣本)。下一章我們會討論既不需要model也不需要bootstrapping的演算法。再下一章我們討論不需要model但是需要bootstrapping的方法