Deep Reinforcement Learning: Pong from Pixels
這是一篇遲來很久的關于增強學習(Reinforcement Learning, RL)博文。增強學習最近非常火!你一定有所了解,現在的計算機能不但能夠被全自動地訓練去玩兒ATARI(譯注:一種游戲機)游戲(直接輸入游戲的原生的像素數據),還能擊敗圍棋的世界冠軍、模擬四足動物上躥下跳。機器人還能學習如何進行復雜的控制任務,甚至比直接編寫的程序效果還要好。這些在各個方面的領先都應該被歸功于增強學習遍地開花般的研究。我本人在過去幾年中也對增強學習非常感興趣:我完成了Richard Sutton的書,看完了David Silver的課程,看了John Schulmann的講義,寫了一個基于Javascript的增強學習的庫,并且在DeepMind公司的DeepRL組實習了一個夏天,而最近的工作有些涉及到一個全新的增強學習評測工具箱OpenAI Gym的設計和開發。所以我實際上已經在這條賊船上帶了一整年,但是直到現在我還沒抽出時間去寫一篇簡短的博客來闡述增強學習是什么、為什么增強學習這么重要、如何開發一個增強學習的程序,以及它的應用背景會是什么。
幾個增強學習的例子。從左到右:深度Q學習網絡玩兒ATARI,AlphaGo,伯克利堆積木機器人Legos,物理模擬的四足動物在地面奔跑。
回憶一下增強學習近期進展的本質是一件很有趣的事情。我比較直白地認為人工智能受到了以下一個因素的掣肘(此處原文為hold back AI,總覺得有些怪怪的):
與計算機視覺界所經歷的一樣,增強學習的發展進程不像想你想的那樣起源于什么驚世駭俗的靈感。在計算機視覺界,2012年的AlexNet幾乎就是1990年代卷積神經網絡(ConvNets)的高規格版本。與之相似的是,2013年ATARI的深度Q學習(Deep Q Learning)的論文實際上在功能上近似于一個標準的算法(Q學習,Q Learning,函數逼近,你可以在Sutton1998年編寫的標準的增強學習書籍上找到),函數逼近實際上使用了一個卷積網絡。AlphaGo使用了帶有蒙特卡洛樹搜索的策略梯度(Policy Gradients),其實這些也是慣用的組件。當然,也還需要用到大量的技巧和一點兒耐心讓它能夠正確地運轉起來,同時也需要在那些之前被提出的傳統算法中應用上一些聰明的小技巧,但是對于一階近似來說,能產生如此巨大的成就并不是取決于算法,而是(與計算機視覺類似)據取決計算能力、數據和基礎設施。
話題回到增強學習。我很喜歡去寫博客來說明一件看上去很夢幻的東西和其背后的簡單的原理。【譯注:這句話的原話語法結構太復雜了,駕馭不住啊】。我見過很多人不敢相信我們能夠全自動地讓機器像人類一樣學會去玩兒大部分ATARI游戲,甚至只需要一個算法、直接輸入像素、從零做起,效果非常震驚,我自己嘗試過。但是我們所用的核心方法其實非常的簡單粗暴(盡管我知道現在回想起來好像這么說會引發一些爭議)。無論如何,我將會帶你了解Policy Gradients算法(PG),即在這個時候了解增強學習的最佳切入點。如果還是個怎強學習的門外漢,你一定會好奇為什么我不去介紹DQN算法呢?它可是一個更廣為人知的增強學習算法,并且在玩兒ATARI游戲的論文中經常出鏡。這是由于Q學習并不是一個非常強大的算法(你可以說DQN在2013年很強大(好吧我是在半開玩笑地說~))。事實上,大多數人更傾向于使用策略梯度算法,甚至包括最早DQN論文的作者,他發現如果參數調的好,則它比Q學習效果還要好。我們首選PG算法是因為它是端到端(End to end)的:有一個顯式的策略,和一個能夠直接優化期望回報(expected reward)的規范的方法。好的,作為例子,我們將會從零開始,在像素級別,使用一個深度神經網絡,并用PG來學習去玩兒ATARI的游戲(Pong!)。所有這些事情只需要130行的Python就能搞定,并且只用到了numpy庫。讓我們試試吧!
Pong from pixels
Pong這個游戲。
Pong是馬爾可夫決策過程(Markov Descision Process, MDP)的一個例子:圖中的每一個結點都是游戲過程中的一個特定狀態,每一條邊都是一個(通常是概率意義上的)可能的變換。每一條邊帶有一個“回報”(reward),而任務的目標是在任意狀態計算出一條最優的路徑來最大化回報。
Pong這個游戲非常適合用來解釋一個簡單的增強學習的任務。在ATARI2600版本的這個游戲中,你需要控制一側的擋板(另一側由一個還算靠譜的AI控制)然后你需要通過撞擊擋板將球反彈給對方(我貌似不用解釋的太詳細了對吧?)。我們可以用更加底層角度看待這個任務:我們接收到了一幀圖像(一個210x160x3的字節數組(從0到255的整數值表示像素值)),然后我們來決定是要讓擋板向上還是向下(這是一個二進制的選擇)。在每一次選擇之后,游戲模擬器執行動作然后給我們一個回報:一個+1回報表示我們成功將球擊向對手,一個-1回報表示丟了球,或者一個0回報表示其他情況。當然,我們的目標是通過移動擋板來得到很多很多的回報。
在我們解決這個問題的時候,我們要做幾個假設,因為我們的關注點并不是Pong這個游戲,而是在于研究一個復雜的高維問題,比如說操縱機器人,裝配和導航。Pong只是一個有趣的測試例子,而總有一天我們會寫出一個非常通用并且能做很多有用的任務的AI系統。
策略網絡(Policy Network)
首先,我們要去定義“策略網絡”這個概念。它能作為我們的“玩家”(或者“代理”,即agent)。這個網絡能夠以當前的游戲狀態為輸入,并且能夠決定我們應該采取什么動作(向上或者向下)。為了計算方便,我們使用了一個兩層神經網絡,接受原生的圖像像素作為輸入(一共100,800個數(210*160*3)),然后產生一個數字來表示“向上移動擋板”的概率。通常情況下我們會用“stochastic”策略,就是說我們只產生一個向上移動的概率值。每一次迭代我們都會從這個概率分布去采樣(就好像投擲一枚不均勻的硬幣)來決定到底是向上還是向下(譯注:這個產生出來的值只是一個向上的概率,而不是說當這個值大于某個閾值就向上,小于閾值就向下。真正使用的時候就是以這個概率值去拋硬幣。也就是說幾遍這個概率告訴你百分之90要向上,你也是有可能采樣獲得“向下”這個決策的)。這么做的原因我們會在講解訓練算法部分仔細說明。
我們的策略網絡(Policy Network)是一個兩層的全連接網絡。
為了更加詳實地闡述,這里我們用Python/Numpy來實現這個策略網絡。假設我們有一個變量x,里面有(經過預處理之后的)像素信息。這時候我們可以計算:
h = np.dot(W1, x) # 計算隱層單元激活值 h[h<0] = 0 # 使用Relu非線性變換:閾值是0 logp = np.dot(W2, h) # 第二層 p = 1.0 / (1.0 + np.exp(-logp)) # sigmoid 函數(輸出一個概率值)在代碼中,W1和W2是兩個隨機初始化的矩陣。這里沒有用到偏置因為不是很重要。要注意我們在最后一層使用了sigmoid非線性變換,它能將輸出值修整到[0,1]區間(譯注:這樣才是概率嘛!)。從直覺上來說,隱藏單元的神經元(在W1上的每一行權重)應該能探測到不同的游戲場景(比如說球在頂部,擋板在中間),而在W2中的權值應該能在各種情況下決定我們是要向上移動還是向下移動。我們現在講W1和W2隨機初始化之后,將會導致這個AI抽風式地運動。所以我們需要做的就是找到一個合適的W1和W2讓這個AI稱為Pong的專家!
額外說一下preprocessing。我們其實需要至少將兩幀輸入到策略網絡中,否則網絡將沒法探測到運動(譯注:一張照片并不能表示球的運動方向等)。為了讓這件事更簡單一些(我在我的Macbook上測試過),我將會做一個微小的預處理。比如說我們實際輸入的是兩幀的“區別”(比如說將當前幀減上一幀得到的結果)。
聽起來不太可能
現在我需要讓你明白一個增強學習任務到底有多難。我們有100,800個數(210*160*3)在我們的策略網絡中(這個網絡的W1和W2很容易就會包含上百萬個參數)。假設我們決定向上移動擋板。在當前時間幀,游戲認為獲得0回報(譯注:因為球還沒撞到擋板,所以并不是成功反擊的+1回報,也不是丟球的-1回報,而是0回報),而在下一個時間幀,又將會有100,800個數字。我們需要重復這個步驟高達上百次,直到出現一次非0的回報(譯注:成功反彈或者丟球)。假設我們最終得到了+1回報。這很棒,但是我們如何知道究竟是什么導致了這個回報的發生?我們在剛剛那幀做了些什么?或者說在第76幀做了什么?或者是不是我們在第10幀時的操作和第90幀時做了某個至關重要的動作?那么我們該如何知道這上百萬的參數該調整那些、該如何調整才能后續的測試中達到更好的效果?我們將這個問題稱為“credit assignment”問題(credit assignment problem)。以Pong為例我們知道,一個+1回報表示球成功地傳給了對手。真實情況是我們將球反擊出了一個正確的軌跡,但實際上這是因為我們很久以前某一幀做出了正確的決定,比如說,有可能是20幀之前的某個操作就決定了最后能將球擊中。而在這之后的操作可能對是否能得到回報并不起作用(譯注:如果能預測球的落點,在地20幀的時候把擋板放對就ok了,后面不論擋板怎么調整,只要擊球時還在這個位置,就能得到回報了)。說了這么多就是為了告訴你,我們面臨的這個問題非常之復雜,并且看起來是很難解決的。
有監督學習 (Supervised Learning)
在深入了解用到Policy Gradients的解決方案之前,我還想帶你回憶一下有監督學習的基本知識,因為它跟增強學習非常相似。參考下圖。在傳統的有監督學習中,我們將一張圖片輸入到網絡中,然后獲取一些概率值。比如說“向上”、“向下”的二類分類問題。我所展示的是log概率(-1.2, -0.36)而不是概率(30%和70%),因為我們經常去優化正確類別的log概率,這在數學上要更好一些,而且這對于優化問題來說是等價的,因為log是單調的?,F在,在有監督學習中,我們必須要用到label。例如,我們被告知了現在應該讓擋板向上(label 0)。此時我們需要將UP對應的log概率設為1,然后運行梯度下降算法去計算?Wlogp(y=UP|x)。這個梯度將會告訴我們這上百萬個參數中的每一個都應該如何調整,來讓網絡稍微傾向于輸出“向上”。例如。網絡中上百萬個參數中的一個有可能具有梯度-2.1,這就意味著如果我們在這個參數上增加一個很小的正值(比如0.001),那么log概率將會增加2.1*0.001(如果是負值則就會減小)。如果我們這樣更新參數,那么網絡在下次看到一張非常相似的圖片的時候,就會更加傾向于去輸出“向上”。
策略梯度 (Policy Gradients)
但是,在增強學習的過程中,我們沒有正確的label那該怎么辦?所以我要介紹一種被稱作是Policy Gradients的方法(如下圖所示)。當我們的策略網絡計算出向上的概率是30%(log概率是-1.2),向下的概率是70%(log概率是-0.36).我們現在從這個分布中去采樣;比如說,假設我們采樣得到的結果是“向下”(譯注:采樣方法比如說,產生一個0~1的均勻分布的隨機數,判斷這個數>=0.7還是<0.7,對應決定輸出是“向上”還是“向下”)
,然后我們在游戲中執行這個操作。這時候我們會注意到一個有趣的現象:我們可以像有監督學習中那樣,立刻在“向下”的梯度上賦值1.0,然后去找到能讓網絡以后略微傾向做出“向下”動作的梯度向量。但是問題是,直到目前為止,我們也不知道“向下”這個操作是好是壞。但這不是個大問題,我們可以等一陣然后看看結果。比如對Pong這個游戲來說,我們能夠一直等到游戲結束,然后獲得收益(如果贏了就是+1,如果輸了就是-1),然后認為相對應的值就是我們所做的操作的梯度(本例中是“向下”)。在下面的例子里,“向下”最終會導致游戲失敗。所以如果我們用-1表示“向下”對應的log概率然后進行反向傳播我們將會讓網絡對這個輸入在以后不鼓勵做出“向下”的操作(顯然是這樣,因為這個動作將會導致最后輸掉游戲)。
也就是說:我們用一個隨機的策略來產生動作,如果這個動作在未來最終帶來好的結果那么將會被鼓勵,如果這個動作在未來最終帶來壞的結果那么將會被壓制。除此之外,甚至在我們贏得或輸掉游戲時,回報不一定要求是+1或者-1。它可以是任何表示最終效果的度量手段。例如我們可以認為如果任務做的好,那么回報就是10.0,如果最終結果還不錯,那我們就把它作為梯度而不用-1,然后進行反向傳播算法。這就是神經網絡美妙的地方;使用它們就好像在作弊一樣:你能夠將一百萬個參數綁定在一個運算速度高達1 teraflop的機器上然后用上SGD(隨機梯度下降)。它看起來并不靠譜,但神奇的是我們正生活在一個讓他能靠譜運轉的世界。
Training Protocol (譯注:實在不知道怎么翻譯了)
下面詳細介紹一下訓練過程。首先我們初始化策略網絡的W1,W2然后進行100次Pong的游戲(我們稱這些策略叫做“rollouts”)。假設每一次游戲由200幀組成,所以我們一共要進行20,000次“向上”或者“向下”的決定,而且對于每個決定,我們都能夠知道梯度,這個梯度則告訴了我們想要在未來做出更好的決策應該做出怎樣的調整?,F在只剩下去對我們做的每個決策標記上是“好”還是“壞”了。例如我們贏了12場游戲,輸了88場游戲。我們將會用在贏的游戲過程中做出的200*12=2400個決策做出“正”的更新(對采樣得到的動作賦值+1的梯度,然后進行BP算法,參數更新將會鼓勵我們所采取的這些動作)。然后我們會將其他在輸掉的游戲中所做的200*88=17600個決策標記為“負”的更新(不鼓勵采取這些動作)。然后網絡將會逐漸偏向做出有用的動作,而減少做出無用的動作。然后我們再用我們輕微修正過的新的策略網絡進行100場游戲,然后再去輕微地更新策略網絡。
策略梯度:讓動作執行一會兒,看看什么動作將會產生高回報,那么就提高這部分動作在當前情況下出現的概率。
圖中展示了4場游戲。每一個黑色的圓圈就是一個游戲的狀態(圖的下部有三個例子),每一個箭頭代表一次狀態轉換,上面標注的是采樣得到的動作。在這個例子中,我們贏了兩場游戲,輸了兩場游戲。通過策略梯度算法,我們用兩場贏了的游戲的數據來稍微鼓勵網絡做出這兩個episode(譯注一場游戲的一系列決策稱為一個episode)中的每一步。相反的,我們用輸掉的兩場游戲的數據來稍微抵制網絡做出這兩個episode中的每一步。
如果你仔細想想這個過程,你會發現一些有趣的事情。比如說如果我們在第50幀時做了一個“正確”的動作(比如將球正確地反擊回去),但是在第150幀的時候卻丟了球該怎么辦?如果此時每一個動作都被標記成“不好”的動作(因為我們丟了球),那么會不會在第50幀的動作也會被壓制?是的,它會被抵制。然而其實你可以考慮一下當游戲進行了成千次甚至上百萬次時,雖然你第一次正確的反擊本應讓你偏向贏得游戲,但平均來說,正確更新的數量還是要大于錯誤更新的數量的,所以最終你的策略將會學習到做出正確的動作。
2016年12月9日更新:從另一個視角解釋
在上面解釋中,我用到了諸如“將梯度設置成xx然后用反向傳播算法”這樣的話,這是基于你們很熟悉如何編寫你自己的反向傳播的算法,或者經常使用Torch之類的需要自己顯示地寫出梯度的框架。然而,如果你經常用的是Theano或者TensorFlow,你有可能會對這句話有些困惑,因為在這些框架中,代碼是圍繞著損失函數組織的,而反向傳播算法是全自動進行的,并且很難去對它做修改。在這種情況下,從另一個角度解釋這件事或許更加直觀。在最簡單的有監督學習任務中,目標函數是最大化∑ilogp(yi|xi),其中xi和yi是訓練樣本(比如說是圖片和它們的標簽)。策略梯度與有監督學習除了這兩點以外是完全一樣的:1)我們沒有正確的標簽yi,所以我們用網絡看到xi時采樣的動作作為“假標簽”來代替。2)我們基于最終的結果(譯注:贏或輸)來調整基于多個樣本相乘的損失函數(譯注:因為最終的損失函數會由多個樣本相乘組成,參見極大似然估計MLE),就是說,我們要對有效的動作提高它的log概率,對無效的動作降低它的log概率。綜上所述,我們的損失函數現在應該是這樣:∑iAilogp(yi|xi),其中yi是我們采樣得到的動作,Ai是一個被稱為“advantage”的數。比如在Pong例子中,當我們經過整個episode最終贏得了勝利Ai就是+1,反之如果我們輸了就是-1.這能保證我們動作的log概率在好結果中會被最大化,壞結果中會被最小化。所以說,增強學習完全就是有監督學習,只不過區別在于數據集是在不斷變化的(每次都會有不同的episode),然后與"advantage"相乘,然后我們每次采樣得到的數據集只會做一次(或者少量的)更新。
(譯注:與有監督學習相比,RL重點在于在整個episode結束前,是不能確定每個標簽的。所以說,產生一個episode->更新策略網絡->再基于最新的策略網絡產生新的episode->循環進行。)
更加通用的“advantage”函數
我之前說過要多講一講“回報”。目前為止,我們去評價一個動作的好壞都是依據最終會不會贏得游戲。一個更加通用的增強學習的設計是我們將會在每一個時間步都獲得一個回報rt。一個常用的選擇就是“discounted reward”。所以上圖的最終回報(eventual reward)就會變成Rt=∑∞k=0γkrt+k。其中,γ是一個0~1之間的數,稱作是discount factor(取值比如說0.99)。這個表達式說明,我們對于一個采樣動作的鼓勵強度,是后續所有回報的加權求和決定的,但是后面回報的重要性是以指數級衰減的。在實踐中,標準化這些回報也非常重要。比如說我們要計算所有100場Pong游戲中的20,000個動作的回報Rt。一個比較好的做法就是在把這些數據送到BP算法之前,對這些回報做一下標準化的操作(比如通過減均值除標準差的方法)。這樣我們總能大約鼓勵一半的動作、壓制一半的動作。從數學上來說,這也可以被認為是一種控制策略梯度的方差的一個技巧。更加相近的解釋可以參考這里
推導策略梯度
下面我會大概說一說策略梯度是怎樣從數學中得到的。策略梯度是一個更加廣義的概念——“score function gradient estimator”的特殊形式。通常的情況下我們需要計算形如Ex~p(x|θ)[f(x)]的表達式,比如說計算一個標量值函數(scalar valued score function) f(x)服從以θ為參數的概率分布p(x;θ)的期望。提示:f(x)可以作為我們的回報函數(或者更通用地說,可以作為advantage函數),而p(x)是策略網絡,也就是給定任意圖象I后對動作a的分布函數p(a|I)。那么,我們感興趣的是我們應該如何通過參數θ來修正這個分布,使得它能對樣本有著更高的得分,而這個得分是由f決定的(即,我們應該如何修改網絡的參數才能讓動作樣本得到更高的分數)。我們有下面的公式:
?θEx[f(x)]=?θ∑xp(x)f(x)=∑x?θp(x)f(x)=∑xp(x)?θp(x)p(x)f(x)=∑xp(x)?θlogp(x)f(x)=Ex[f(x)?θlogp(x)]definition of exceptionswap sum and gradientboth multiply and divide byp(x)use the face that?θlog(z)=1z?θzdefinition of exception譯注:經過上面的公式,我們想要計算 ?θE[f(x)],不再需要真的去計算帶有函數f(x)的梯度了。只需要1)按照某個概率分布采樣,2)直接計算Ex[f(x)?θlogp(x)]來代替即可。這么做的好處是我們可以定義一個非常復雜的打分函數f(x),甚至這個函數可以不可微,因為我們在后續的求導中,完全沒有這個函數的參與,只要概率分布可微就行了。所以,在實際應用中,f(x)常常是一個復雜的函數,而p(x)則可以是一個由神經網絡組成的策略網絡等模型,因為神經網絡一般是可微的。
說人話就是:我們有某個概率分布p(x;θ)(為了簡便所以寫成p(x)),并且可以從中進行采樣(比如說從一個高斯分布)。對于每一個樣本,我們可以對其用評分函數(score function)f打分,即輸入樣本到函數中,得到一個標量值作為分數。這個等式告訴了我們應該如何調整分布(由參數θ控制)才能得到用f評價的更高的分數。特別地,它像是在說:抽一些樣本x,然后評價一下它們的分數f(x),然后對每個x再計算一下第二項?θlogp(x;θ)。第二項的內容是啥?它是一個向量:也就是能夠知道我們在參數空間應該如何調整才能使x出現的概率盡可能大。換句話說,如果我們有在?θlogp(x;θ)的方向有連續不斷的θ,我們將會看到產生x的概率將會稍稍增加。在回顧一下公式,它還告訴我們我們要把這個方向與那個標量打分函數(scalar-valued score)f(x)相乘。這會使得具有更高得分的樣本對概率密度的“拖拽”力度要比分數低的樣本大一些。所以如果我們基于多個從p中采樣的樣本去更新概率密度函數,我們將會在想得分更高的樣本方向多偏離一些,這能夠讓得分更高的樣本更有可能被采樣出來。
一張關于分數梯度函數的可視化圖。左:一個高斯分布,在其中采樣了幾個樣本(藍色點)。在每一個藍色點上,我們也畫出了對應高斯均值參數的log概率的梯度(譯注:即 ?θlogp(x;θ))。箭頭指向了想要使分布更容易采樣到樣本的調整方向的均值。中:一些打分函數對樣本給出了-1分,而在一些小區域中給出了+1分(注意此處不必須是一個可微的標量值函數)?,F在箭頭被染色了,因為在更新中包含了乘法,我們會將所有綠色和紅色的箭頭分別取平均。右:經過參數更新之后,綠色的箭頭和相反的紅色箭頭(譯注:與-1相乘表示取向量的反方向)會將分布向左下角輕輕推動。正如我們所希望的一樣,現在再從這個分布中取值,將會更容易得到更高的分數。
希望我講明白了這與增強學習之間的連接。我們的策略網絡就是讓我么能夠采樣出一系列比其他動作更好的動作(通過advantage函數判斷好壞)。這些數學公式的片段告訴我們了一種能夠修正策略參數的方法就是先讓動作執行一會兒,然后計算采樣的動作的梯度,乘上它們的得分,然后將他們加起來,這就是上面做的事情。想要了解更詳盡的來龍去脈,我推薦你去閱讀John Schulman's lecture.
學習
好了,我們已經介紹了策略梯度的直觀想法并且簡單了解了它的起源。我實現了一個總共130行的Python腳本,它使用了OpenAI Gym的ATARI2600 Pong游戲。我訓練了一個包括了200個隱層單元的兩層策略梯度網絡,并且用RMSProp算法在batch大小為10的episodes上訓練(每一個episode都包含了幾場游戲,因為比賽最高成績就是21分)。我并沒有調整太多的代碼,然后在我的Macbook(非常慢)上運行了3個晚上,最終得到的策略網絡能比AI玩家稍微好一點。Episode的數量共計8,000左右,算法大約玩兒了200,000場Pone的游戲(非常多!對不?),大約做了800次梯度的更新。我朋友告訴我說如果你在GPU上用卷積神經網絡訓練幾天,你能更加頻繁地打敗AI玩家,如果你要是能把參數調的好一些,你就能永遠處于支配地位(就是說,贏得每一場游戲)。然而,我沒有話太多的時間去計算或者調優,在用Pong AI成功驗證了主要的思想并且效果還不錯我就停掉了程序。
學習到的權重
我們可以看一看學習到的權重的內容。經過預處理,我們輸入的都是80x80大小的圖片(當前幀減去上一幀。譯注:保留一部分運動信息)。我們現在取W1的每一行,把他們展開成80x80的大小然后畫出來(譯注:此處可能跟之前提到的210x160x3的結構不太一樣。這里的輸入圖片單張只存為80x80=6400,然后傳輸到200個神經元中,所以矩陣W1的維度是6400x200)。下圖表示了40個(共計200個)神經元的可視化結果。白色的像素表示正值,黑色的像素表示負值。我們會發現有幾個神經元被調整出了特定的球的運動路徑,并被編碼成了“黑白相間”的線段。由于球只能在一點處被擊中,所以這些神經元能處理多個任務并且會在球沿著線的多個位置“激發”(譯注:此處的激發應該不是指擊球。而是說當球沿著這些路徑的時候,這些神經元將會活躍起來,處于激發的狀態)?!昂诎紫嚅g”很有趣,因為在球運動的過程中,神經元像sin函數一樣波動是由于使用了ReLU作為激活函數,它會在軌跡的不同位置上離散式地激活(譯注:ReLU在x大于0的時候是線性,小于0時就是0,所以不是隨時激活)。圖片看起來有一些噪聲,我覺得或許用上L2正則效果會好一些(譯注:加上L2正則項能一定程度上避免過擬合,即避免了圖像“記住”一些特例,更容易分辨一些“普遍的特征”。這些特例可能就會產生圖像上的噪聲)。
哪些事情沒發生
所以說,到目前為止,我們從原始像素點去學習到了如何利用策略梯度去進行Pong游戲,并且效果也非常好。這個方法時“guess-and-check”的一種理想形式?!癵uess”表示從我們當前的策略出發產生一個動作序列,而“check”表示我們要估計能產生正回報的動作。講的更詳細一些,這代表了我們目前這個增強學習問題所能達到的最好的效果。能夠學習到這樣的行為令人印象深刻,但是如果你能直觀地了解到這個算法并且知道它如何工作的,你會有一點兒遺憾。尤其是,什么情況下它會不好使?
與人類如何學習進行Pong游戲相對比。你向人們展示這個游戲,然后告訴他們規則“你要控制這個擋板,它能向上向下運動,你的任務就是將球傳給其他由AI控制的玩家”,然后就準備就緒可以開始了。注意其中由這么幾個區別:
- 在實踐種,我們通常會用某種方式來交流溝通這個任務,但是對于標準的增強學習來說,你只能假設一個回報函數然后從與環境的交互中進行探索。而當人類參與到Pong中時,如果沒有明確的關于回報函數的知識(尤其是回報函數是靜態但是隨機的)時,人類在學習的過程中將會面臨很多困難。但是策略梯度就則不關心這些,并且可能比人類做的還優秀。相似地,如果我們把各幀的像素隨機地置換,對于人類來說很有可能玩兒不好,但是對于策略梯度來說甚至可能都感覺不出什么區別(如果它們用的都是全連接網絡的話)
- 人類是帶有大量先驗知識的,比如基本的物理學(球會反彈而不會瞬間移動,也不太可能會突然停住,因為它帶有一些速度)。和一些基本的心理學(AI對手“渴望”去贏,那就有可能用某種顯而易見的策略去移動球等等)。而且你心中有“控制”擋板的這個概念,并且會反映在向上向下的按鍵上。與此相反,我們的算法從零開始但很快就讓人印象深刻(因為它確實有效)和沮喪(因為我們并不知道它什么時候就失效了)
- 策略梯度是一種暴力搜索的方法,正確的動作最終會被發現并且固化到策略中。人類會構建一個強大又抽象的模型,然后用它做規劃。在Pong中,我們能推理出對手比較慢,所以“將球高速反擊”將會是一個比較好的策略,這可能會導致對手無法在足夠的時間內碰到球。然而,我們也會最終將這策略以肌肉記憶的形式固化在身體里。例如,當我們想要學習一種新的需要移動的任務(比如說學習駕駛一輛手動變速的車)你在剛開始會需要經常思考,但是最終會變得不需要思考,自動就能進行了。
- 策略梯度必須直接輸入正回報,并且需要經常體驗到正匯報,以便于它能慢慢地推動策略參數偏向能重復產生高回報動作的狀態。而人類能在不需要直接體驗的回報(譯注:知道最終結果前)就能知道那些動作更容易獲得高回報。我不用將我的汽車撞毀幾百次才能緩慢地學會如何避免碰撞。
蒙特祖瑪的復仇(Montezuma's Revenge):一個對我們的增強學習算法來說非常復雜的游戲。玩家必須跳躍、攀爬、拿到鑰匙然后打開門。計算機隨機采樣了幾十億次的移動,但是99%都是會掉下去摔死或者被怪物殺死。換句話說,它非常難以進入到獎勵狀態(譯注:絕大部分的采樣最終都是負回報,幾乎沒有正回報,所以沒法訓練)。
另一個非常難的游戲Frostbite,人類能理解運動,一些東西可以接觸,另外一些東西不能接觸,游戲的目標是一塊一塊搭建一個冰屋。Building Machines That Learn and Think Like People是一個不錯的關于這個游戲的分析和關于人與機器之間區別的討論。
我想要強調一點,相反地,有很多游戲策略梯度能輕易打敗人類。特別是任何會經常有回報信號,并且需要精準操控、快速反應的游戲。那些不需要做長期規劃的游戲很合適。這些短期的游戲的動作與回報之間的關系能夠被算法輕易地“發掘”到,然后悄悄地被策略驅使著完善自己。這在我們開發的Pong的智能體中已經出現:它能學習到一種策略,等待球靠近然后在邊緣將它接到,因為這樣能以很高的速度將球傳回去。我們的智能體多次用到了這個策略。深度Q學習在很多ATARI游戲上都用這樣的方式打敗了人類,比如說Pinball, Breakout等等。
總結一下,一旦你理解這些算法工作的“技巧”,你就能推理出它們的強項和弱項?,F在人類距離構建一個抽象、并且具有豐富的游戲表示來幫助我們進行規劃并且能快速學習的系統還差得遠??傆幸惶?#xff0c;一臺計算機將會意識到一個像素數組是一把鑰匙、一扇門,并且能意識到要撿起鑰匙去開門。但是現在我們里這個還是非常遙遠的,而這個領域是一個熱門的研究領域。
神經網絡中的不可導運算
我想提一個跟策略梯度玩兒游戲無關的應用:它能夠讓我們去設計并訓練一個由不可導單元組成的神經網絡。這個概念第一次由Williams于1992年介紹,并且最近在《Recurrent Models of Visual Attention》中用“hard attention”這個名字重新發展起來。這個模型用一系列低解析度的“foveal glances”來處理圖像。特別是在每一次迭代中,RNN都會收到圖像的一個小片段,然后隨機采樣一個下一次會看到的位置。比如說,RNN有可能正在看(5, 30)這個位置,然后看到了圖像的一個小片段,然后決定去看(24, 50)這個未知,以此類推。這個想法有個問題就是這將會產生一個“下一次看哪里”的分布,然后從這個分布采樣一個位置。但不幸的是,這個操作是一個不可導的操作,因為我們不知道如果采樣得到其他的位置將會有什么變化。具體一些地說,考慮一個神經網絡,接受一些輸入產生一些輸出:
我們會發現大部分的箭頭(藍色的)像往常一樣都是可導的,但是一些變換形式有可能包含一些不可導的采樣操作(紅色的)。我們能正確地對藍色箭頭用BP算法,但是紅色箭頭所表示的依賴關系我們是沒法用BP算法的。
而策略梯度則則解決了這個問題!我們可以將網絡的一部分看作是嵌入在一個大網絡中的隨機策略。因此,在訓練過程中我們將會產生幾個樣本(就是下圖中的分支),然后我們會去鼓勵產生那些最終能帶來正回報的樣本(比如說需要在整個過程結束后才能評價損失函數值的時候)。換句話說,我們將會像平時一樣去用BP算法來訓練藍色箭頭表示的參數,而對于紅色箭頭中的參數,我們現在會用策略梯度的方法來向前傳遞,然后鼓勵能采樣出使最終損失降低的樣本。這個想法有一個很好的形式化說明:《Gradient Estimation Using Stochastic Computation Graphs》
可訓練的存儲I/O
你可能會在很多其他的論文中見到這個想法。比如說,神經圖靈機(Neural Turing Machine)有一個“磁帶存儲器”,并且能從上面讀取數據,向上面寫入數據。執行寫操作一般會執行形如m[i] = x的操作,其中的i和x是通過一個RNN控制器網絡(RNN controller network)來產生的。然而,這個操作是一個不可導操作,因為并沒有一個信號告訴我們如果我們向一個不同的位置j != i寫入,損失函數會有什么變化。因此,神經圖靈機必須去做“soft”讀和寫操作。它要預測產生一個分布a(每一個元素都是0~1之間,而且和為1,然后在我們要寫入的索引附近的位置應該有很多峰值。譯注:表示這個位置更容易被采樣得到),然后執行for all i: m[i] = a[i]\*x。雖然現在可導了,但是我們不得不付出很大的計算代價,因為必須訪問每一個內存單元去寫入。想象一下,當每一次賦值操作都會訪問整個內存!
(譯注:這一段是說,神經圖靈機不能像真的計算機一樣,直接就能向某個內存單元寫入。因為這樣的操作是不可導的。解決方法就是通過產生一個分布,然后從這個分布中采樣得到每一個“每一個內存單元內是否寫入數據”的樣本,然后通過遍歷每一個內存單元與這個樣本共同控制是否寫入內容。這樣雖然讓這個問題變得可導、能用BP算法運算,但是每一次操作都會伴隨著對所有內存單元的訪問。)
然而,我們能用策略梯度(在理論上)來解決這個問題,而RL-NTM也就是這么做的。我們現在還是預測一個attention分布a,但是現在我們不再做soft寫入,而是采樣得到一個寫入的位置:i=sample(a); m[i]=x。在訓練過程中,我們將會對一個小批i進行這個操作,而最終要看哪一個分支工作的最好。而且在測試階段,我們只需要對一個位置進行寫入/讀取就可以了,這回打來巨大的計算力的解放。然而,就像這篇論文中指出的一樣,這個策略非常難以發揮作用,因為采樣總會導致意外的錯誤?,F在,大家一致認為策略網絡只有在只包含了幾個離散的選擇時才有效,當需要從巨大的搜索空間中搜索時,這個方法就變得毫無希望了。
然而,我們擁有策略梯度算法和大量的數據和計算能力,我們現在能想的長遠一些,比如說我們能夠設計一個神經網絡,去學習如何與一個巨大的、不可導的模塊進行交互,例如LaTeX的編譯器(比如說你可以做一個字符級的RNN然后產生LaTeX代碼然后編譯),或者一個SLAM(Simultaneous Localization and Mapping)系統、一個LQR(Linear Quadratic Regulator)求解器,或者其他的什么東西。再比如說,一個超級智能的東西能夠學習如何用TCP/IP協議與互聯網進行交互(這顯然是一個沒法求導的問題)去了解如何接管這個世界的致命信息。
結語
我們看到了策略梯度這個功能強大,適用范圍廣泛的算法,并且作為例子我們從零開始用130行Python代碼實現并訓練了一個ATARI Pong的像素級智能體。同樣的算法還可以被用來訓練很多其他的游戲,總有一天它會為很多現實世界中復雜控制問題的解決帶來希望。我想要在這篇文章的結尾處再寫幾句:
關于推動AI
我們已經了解到這些算法使用了包里搜索的方法,也就是剛開始隨機地游走,然后一定會跌跌撞撞地得到至少一次回報,然后再理想情況下,這個過程要重復很多次,直到策略分布通過調整它的參數能夠做出合理的動作。我們也了解到這些問題對人類來說也是非常困難的。這就好像快速構建一個抽象模型——我們僅僅在研究中觸及冰山一角(盡管很多然都在嘗試)。這些抽象模型非常難(如果不是不可能的話)以明確地被評注,這也就是為什么我們最近在(無監督)生成模型和程序歸納(Program Induction)領域表現出極大興趣的原因。
關于復雜機器人的應用
算法并不能簡單地推廣到需要大量探索的場景中。比如說,一個機器人應用中有可能包含了一個(或幾個)機器與現實世界中的實時交流。我們上面提到的算法在這個場景中可能沒法使用。一個試圖解決這個問題的相關工作是deterministic policy gradients。這個方法不是通過從隨機策略中采樣然后鼓勵這個采樣能獲得更高的分數,而是通過確定的策略直接從第二個網絡(稱為critic)中獲得梯度信息并對打分函數建模。這個方法能夠在高維動作場景中取得更好的效果,而動作采樣的方法收斂性不強。但是目前從經驗上看來想要讓它有效果還是需要很多繁瑣的工作需要做的。另一個相關的方法是規模化機器人(scale up robotics),就像谷歌的機械臂農場,或許還包括Tesla的Model S和自動駕駛技術
還有另一種方法能使得搜索過程更加容易,那就是加上額外的監督信息。在一些特定的情況,機器能獲取到人類專家的指導。比如說AlphaGo就首度利用了監督學習的方法去預測人類圍棋專家的落子,然后去再通過策略梯度針對贏得游戲的“真實的”目標函數微調之后,模仿人類的落子策略。在一些情況下只需要不多的專家指導(比如遠程操作機器人),話有一些其他技術通過apprenticeship learning利用這些數據。最后如果沒有任何人類提供的監督數據,仍然有些代價很高的優化算法可以用。比如說trajectory optimization就是一個廣為人知的動力模型(比如說物理引擎中的F=ma),或者其他可以通過學習局部近似的動態模型(常見于非常靠譜的框架Guided Policy Search)
關于使用策略梯度的最佳實踐
在上面我提到過,我想做一些在RNN那篇博文中做過的事情。我在那篇文章中展示了RNN的魔力,并且展示了一個自動序列生成問題。但事實上,想要讓這些模型正確工作起來是需要很多小技巧的,它需要小心而又專業地調參,并且在很多時候,用這么復雜的模型就像大炮轟蚊子??赡芤粋€更簡單的方法在90%的情況下都是有效的。同樣,對于策略梯度來說,它也不是全自動就能用的:你需要大量的樣本,然后永遠訓練下去,當它不好使的時候也很難去debug。你應該在決定使用火箭筒之前先試試玩具槍。在增強學習的例子中,有一個很厲害的基準方法你應該先試試,那就是交叉熵方法(Cross-entropy Method, CEM)。它是一個由進化算法啟發而成的簡單的隨機向上的“猜測、驗證”方法。如果你一定要在你的問題中嘗試使用策略梯度,那就一定要多花些經歷在很多論文tricks的章節。從最簡單的開始,使用一種PG的變種TRPO。它在實踐中幾乎總是比最普通的策略梯度算法有效。它的核心思想是避免因參數更新導致策略變化的太頻繁,強制增加了一個子一組數據上得到的新老兩個分布KL距離的約束(而不是結合上所有的梯度,關于這個想法最簡單的例子就是線搜索(line search)然后一直檢查KL距離)。
好的!我希望我已經大致給你講明白了什么是增強學習,以及其中的難點是什么。如果你非??释椭鰪妼W習的發展,那我邀請你在OpenAI Gym中嘗試一下:)下次見。
原文: http://karpathy.github.io/2016/05/31/rl/?_utm_source=1-2-2
總結
以上是生活随笔為你收集整理的Deep Reinforcement Learning: Pong from Pixels的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sqlyog安装包_sqlyog社区版和
- 下一篇: nodejs 调用win32 api