當前位置:
首頁 > 科技 > 教程 | 深度Q學習:一步步實現能玩《毀滅戰士》的智能體

教程 | 深度Q學習:一步步實現能玩《毀滅戰士》的智能體


選自Medium


作者:

Thomas Simonini


機器之心編譯


參與:Panda




近年來,深度強化學習已經取得了有目共睹的成功。機器之心也曾發布過很多介紹強化學習基本理論和前沿進展的文章,比如《專題 | 深度強化學習綜述:從 AlphaGo 背後的力量到學習資源分享(附論文)》。近日,深度學習工程師 Thomas Simonini 在 freeCodeCamp 上發表了介紹深度強化學習的系列文章,已發布的三篇分別介紹了強化學習基本概念、Q 學習以及在《毀滅戰士》遊戲上開發智能體的過程。機器之心已經編譯介紹了其中第二篇,本文為第三篇,前兩篇可參閱:






  • https://medium.freecodecamp.org/an-introduction-to-reinforcement-learning-4339519de419 



  • 通過 Q-learning 深入理解強化學習




上一次,我們介紹了 Q 學習:這種演算法可以得到 Q-table,並且智能體可將其用於尋找給定狀態的最佳動作。但正如我們所見,當狀態空間很大時,求取和更新 Q-table 的效果會很差。




本文是深度強化學習系列博客文章的第三篇。我們將在本文中介紹創造一個深度 Q 網路的過程。我們不會使用 Q-table,我們會實現一個神經網路,其以狀態為輸入,然後基於該狀態為每個動作逼近 Q 值。在這種模型的幫助下,我們將創造一個能玩《毀滅戰士》(Doom)的智能體!







我們的 DQN 智能體




在這篇文章中,你將學習到:






  • 什麼是深度 Q 學習(DQL)?



  • 使用 DQL 的最佳策略是什麼?



  • 如何處理有時間限制的問題?



  • 為什麼要使用經歷重放(experience replay)?



  • DQL 背後的數學



  • 如何用 TensorFlow 實現它?



讓 Q 學習變「深度」




在上一篇文章中,我們使用 Q 學習演算法創造了一個能玩《Frozen Lake》的智能體。



我們實現了用於創建和更新 Q-table 的 Q 學習函數。你可以將其看作是一個參考表,能幫助我們找到一個給定狀態下一個動作的最大預期未來獎勵。這個策略很不錯——但卻難以擴大規模。




比如我們今天要完成的目標。我們將創造一個能玩《毀滅戰士》的智能體。《毀滅戰士》是一個有很大的狀態空間的環境(有數百萬個不同狀態)。為這樣的環境創建和更新 Q-table 根本不行。




針對這種情況的最好想法是創建一個神經網路,使之能在給定狀態下逼近每個動作的不同 Q 值。








深度 Q 學習的工作方式




這是我們的深度 Q 學習的架構:








看起來很複雜,但我會一步步地解釋這個架構。




我們的深度 Q 神經網路以 4 幀一組為輸入。這些幀會通過該網路,然後為給定狀態的每個可能動作輸出一個 Q 值的向量。我們需要取這個向量的最大 Q 值來找到我們最好的動作。




一開始的時候,這個智能體的表現真的很差。但隨著時間的推移,它能越來越好地將幀(狀態)與最佳的動作關聯起來。




預處理部分








預處理是很重要的步驟。我們希望降低狀態的複雜度,從而減少訓練所需的計算時間。




首先,我們可以將每個狀態灰度化。顏色並不能提供重要的信息(在我們的情況中,我們只需要找到敵人並殺死敵人,而我們不需要顏色就能找到它們)。這能節省很多資源,因為我們將 3 個顏色通道(RGB)變成了 1 個通道(灰度)。




然後我們對幀進行裁剪。在我們的情況下,可以看到屋頂實際沒什麼用。




然後我們降低幀的尺寸,再將 4 個子幀堆疊到一起。




時間有限的問題




Arthur Juliani 在他的文章中對此給出了很好的解釋,參閱:https://goo.gl/ZU2Z9a。他有個很巧妙的想法:使用 LSTM 神經網路來處理這個問題。




但是,我覺得對初學者來說,使用堆疊的幀更好。




你可能會問的第一個問題是:我們為什麼要把幀堆疊到一起?




我們把幀堆疊到一起的原因是這有助於我們處理時間有限的問題。




比如,在《乒乓球》(Pong)遊戲中,你會看到這樣的幀:








你能告訴我球會往哪邊走嗎?




不能,因為一幀不足以體現運動情況。




但如果我再添加另外 3 幀呢?這裡你就能看到球正往右邊運動:








對於我們的《毀滅戰士》智能體而言,道理也是一樣。如果我們一次只為其提供 1 幀,它就沒有運動的概念。如果它沒法確定目標的移動方向和速度,它又怎能做出正確的決定呢?




使用卷積網路




這些幀會在 3 個卷積層中得到處理。這些層讓你能利用圖像之中的空間關係。另外,因為幀是堆疊在一起的,所以你可以利用這些幀之間的一些空間屬性。




如果你對卷積不熟悉,可以閱讀 Adam Geitgey 這篇出色的直觀介紹:https://goo.gl/6Dl7EA。




這裡的每個卷積層都使用 ELU 作為激活函數。事實證明,ELU 是一種用於卷積層的優良激活函數。




我們使用了一個帶有 ELU 激活函數的萬全連接層和一個輸出層(一個帶有線性激活函數的完全連接層),其可以得到每個動作的 Q 值估計。




經歷重放:更高效地利用已觀察過的經歷




經歷重放(Experience Replay)有助於我們完成兩件事:






  • 避免忘記之前的經歷



  • 降低經歷之間的相關性




我將會解釋這兩個概念。




這部分內容和插圖的靈感來自 Udacity 的「深度學習基礎」納米學位課程中的深度 Q 學習章節。




避免忘記之前的經歷




我們有個大問題:權重的可變性,因為動作和狀態之間有很高的相關性。




回憶一下我們在第一篇文章中介紹的強化學習過程:








在每個時間步驟,我們都會收到一個元組(狀態,動作,獎勵,新狀態)。我們從中學習(將該元組輸入我們的神經網路),然後丟棄這個經歷。




我們的問題是為神經網路提供來自與環境交互的序列樣本。因為在它使用新經歷覆寫時,往往會忘記之前的經歷。




比如,如果我們先在第一關,然後到了第二關(這兩者完全不一樣),那麼我們的智能體就會忘記在第一關的做法。






在學習水中關卡的玩法後,我們的智能體會忘記第一關的玩法。




因此,多次學習之前的經歷會更加有效。




我們的解決方案:創建一個「回放緩衝(replay buffer)」。這能在存儲經曆元組的同時與環境進行交互,然後我們可以採樣少部分元組以輸入我們的神經網路。




你可以將回放緩衝看作是一個文件夾,其中每個表格都是一個經曆元組。你可以通過與環境的交互向其提供信息。然後你可以隨機取某個表格來輸入神經網路。








這能防止網路只學習它剛剛做的事情。




降低經歷之間的相關性




我們還有另一個問題——我們知道每個動作都會影響下一個狀態。這會輸出一個高度相關的經曆元組序列。




如果我們按順序訓練這個網路,我們的智能體就有被這種相關性效應影響的風險。




通過隨機採樣回放緩衝,我們可以打破這種相關性。這能防止動作值發生災難性的震蕩或發散。




舉個例子能讓人更好地理解。比如說我們在玩一個第一人稱的射擊遊戲,其中的怪可能出現在左邊,也可能出現在右邊。我們的智能體的目標是用槍打怪。它有兩把槍和兩個動作:射擊左邊或射擊右邊。






這張表表示 Q 值的近似。





我們學習了有順序的經歷。假如我們知道:如果我們擊中了一個怪,下一個怪出現在同一方向的概率是 70%。在我們的情況中,這就是我們的經曆元組之間的相關性。




讓我們開始訓練。我們的智能體看到了右邊的怪,然後使用右邊的槍射擊了它。這做對了!




然後下一個怪也來自右邊(有 70% 的概率),然後智能體又會射擊右邊的槍。再次成功,很好!




然後一次又一次亦復如是……






紅色的槍是所採取的動作。





問題是,這種方法會增大在整個狀態空間中使用右邊的槍的值。






我們可以看到怪在左邊而射擊右邊的槍是正例(即使這不合理)。





如果我們的智能體沒有看到很多左邊出怪的樣本(因為只有 30% 的可能性在左邊),那麼我們的智能體最後就只會選擇右邊的槍,而不管從那邊出怪。這根本不合理。






即使左邊出怪,我們的智能體也會開右邊的槍。





我們有兩種解決這一問題的策略。




首先,我們必須停止在學習的同時與環境進行交互。我們應該嘗試不同的情況,隨機地玩玩以探索狀態空間。我們可以將這些經歷保存在回放緩衝之中。




然後,我們可以回憶這些經歷並從中學習。在那之後,再回去調整更新過的價值函數。




這樣,我們才會有更好的樣本集。我們才能根據這些樣本生成模式,以任何所需的順序回憶它們。




這有助於避免過於關注狀態空間的一個區域。這能防止不斷強化同一個動作。




這種方法可以被視為一種形式的監督學習。




在未來的文章中,我們還將介紹使用「優先的經歷重放」。這讓我們可以更加頻繁地為神經網路提供罕見或「重要的」元組。




我們的深度 Q 學習演算法




首先來點數學運算。回想一下我們使用貝爾曼方程在給定狀態和動作下更新 Q 值的方法:








在我們的這個案例中,我們希望更新神經網路的權重以減小誤差。




通過求取我們的 Q_target(來自下一個狀態的最大可能值)和 Q_value(我們當前預測的 Q 值)之間的差異,可以計算誤差(TD 誤差)。





Initialize Doom Environment E
Initialize replay Memory M

with

capacity N (= finite capacity)
Initialize the DQN weights w

for

episode

in

max_episode:
   s = Environment state
   

for

steps

in

max_steps:
        Choose action a

from

state s using epsilon greedy.
        Take action a, get r (reward)

and

s

" (next state)
        Store experience tuple <s, a, r, s"

>

in

M
        s = s

" (state = new_state)

        Get random minibatch of exp tuples from M
        Set Q_target = reward(s,a) +  γmaxQ(s"

)
        Update w =  α(Q_target - Q_value) *  ?w Q_value



這個演算法中發生著兩個過程:






  • 我們採樣我們執行動作的環境並將所觀察到的經曆元組存儲在回放記憶(replay memory)中。



  • 隨機選擇小批量的元組,並使用梯度下降更新步驟從中學習。




實現我們的深度 Q 神經網路




現在我們知道其工作方式了,我們可以一步步地實現它了。我們在這個 Jupyter 筆記中介紹了代碼的每個步驟和每一部分:https://github.com/simoninithomas/Deep_reinforcement_learning_Course/blob/master/DQN%20Doom/Deep%20Q%20learning%20with%20Doom.ipynb。




一步步完成之後,你就創造出了一個能學習玩《毀滅戰士》的智能體!




原文鏈接:https://medium.freecodecamp.org/an-introduction-to-deep-q-learning-lets-play-doom-54d02d8017d8






本文為機器之心編譯,

轉載請聯繫本公眾號獲得授權



?------------------------------------------------


加入機器之心(全職記者/實習生):hr@jiqizhixin.com


投稿或尋求報道:editor@jiqizhixin.com


廣告&商務合作:bd@jiqizhixin.com


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 機器之心 的精彩文章:

從結構到性能,概述XGBoost、Light GBM和CatBoost的同與不同
DeepMind提出神經元刪除法:通過理解每個神經元來理解深度學習

TAG:機器之心 |