用Python和Keras搭建你自己的AlphaZero

景略集智發表於2019-03-04

歡迎訪問集智主站:集智,通向智慧時代的引擎




教會機器通過深度學習和自我博弈學習玩《四子連珠》遊戲(Connect4)。


在本文,我(作者 David Foster——譯者注)會主要講到以下三件事:

  • AlphaZero 邁入人工智慧一大步的兩個原因。
  • 你怎樣可以搭建一個 AlphaZero 一樣的AI玩《四子連珠》遊戲。
  • 你怎樣可以將程式碼適用到其它遊戲中。

AlphaGo → AlphaGo Zero → AlphaZero

2016 年 3 月,在 2 百萬人眼前,DeepMind 的 AlphaGo 以 4-1 擊敗了世界圍棋冠軍李世石。一臺機器學到了人類頂尖的圍棋策略,這在以前是難以想象的事情。


就其自身而言,這已經是了不起的成就了,然而 2017 年 10 月,DeepMind 又往前邁了一大步。

在其釋出的《Mastering the Game of Go without Human Knowledge》(無需人類知識掌握圍棋)中,DeepMind 展示了一種新演算法 AlphaGo Zero,它以 100-0 的戰績擊敗的自己的舊版本 AlphaGo。令人難以置信的是,AlphaGo Zero 完全是通過自我博弈學習,從“白板”開始,逐漸找到了能打敗 AlphaGo 的策略。建立一個這樣的超級人工智慧已經完全不需要任何人類專業知識構成的資料庫進行訓練。

用Python和Keras搭建你自己的AlphaZero

僅僅 48 天后的 2017 年 12 月 5 日,DeepMind 又發表了另一篇論文《Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm》(用通用強化學習演算法自我對弈,掌握國際象棋和將棋),顯示 AlphaGo Zero 也能打敗國際象棋世界冠軍 StockFish 和日本將棋冠軍 Elmo。而整個學習過程,從展示給 AlphaGo Zero 這些棋類開始到它成為這兩種棋的世界頂尖高手,只用了不到 24 小時。


在這種情況下,AlphaZero 誕生了——一種無需預先獲得人類專業知識就能迅速掌握某些領域技能的通用演算法。

用Python和Keras搭建你自己的AlphaZero

對於這項成就,有兩個方面很奇妙:


1.AlphaZero 無需任何人類專業知識作為輸入


這一點的重要性,再強調也不為過。這意味著如果有完善的資訊(如果自始至終雙方都完全知道下棋狀態),AlphaGo Zero 的根本方法可以用到任何棋類遊戲中,因為除了該種棋類的規則之外,AI 無需預先學習任何專業知識。

這就是為何 DeepMind 在釋出初篇 AlphaGo Zero 論文後不到 48 天就能釋出打敗國際象棋和將棋人類冠軍的論文。簡單說,所需的改變就只有描述棋類機制的輸入檔案,以及調整與神經網路和蒙特卡洛樹搜尋相關的高引數。


演算法非常優雅


即便 AlphaZero 使用了超級複雜的演算法,當今世界只有一小部分人能理解,那麼它依然算的上是了不起的成就。然而,它的非凡之處就在於論文中的很多理念實際上遠比之前的版本簡單。其核心思想,就是遵循這些簡單的學習口訣一樣的東西:

  • 從內心先將所有可能會出現的場景過一遍,優先選擇有希望的路徑,同時也思考對手對你的行動最可能做出怎樣的反應,並繼續探索未知情境。
  • 抵達不熟悉的狀態後,評估一下你認為當前情形對自己是否有利,關聯一下前幾步的得分,分析走到當前這一步的心理路徑。
  • 在考慮完將來所有的可能性後,採取探索最多的行動。
  • 在比賽結束時,回溯並評估當時對未來場景出現了哪些誤判,相應地優化對這些場景的理解。

這和你學習下棋的過程是不是很像?當你下了一步壞棋,要麼是因為你誤判了走這步棋的未來情況,要麼你誤判了對手可能會怎麼下,因此沒有考慮到這中可能性。而正是從這兩個方面訓練 AlphaZero 學習下棋。


怎樣搭建你自己的 AlphaZero


本文主要是講解如何搭建AlphaZero,因此假定你已經對AlphaZero的原理有了大致瞭解。如果不太熟悉的,可預先查閱一下相關資料,可以參考我製作的這篇速查表或這篇文章


程式碼


將 Github 上的程式碼庫複製下來

https://github.com/AppliedDataSciencePartners/DeepReinforcementLearning

我後面會引用這裡面的程式碼。


要開始學習過程,首先在 run.ipynb Jupyter notebook 中執行前兩個皮膚。一旦它建立了足夠的博弈情景,神經網路就開始訓練了。

再通過自我博弈和訓練,它會越來越擅長在任何位置預測博弈值和下一步棋的動作,從而做出更好的決策,越來越聰明。

現在我們更詳細地看看程式碼,並展示一些結果,證明 AI 隨著時間推移越來越強。


注意:這是我自己根據 DeepMind 所發論文對 AlphaZero 的理解,如有不當之處,敬請指正。


《四子連珠》

我們的演算法要學習玩的遊戲是《四子連珠》(Connect4)。雖然它不像圍棋那麼複雜,但是仍然總共有 4,531,985,219,092 個遊戲位置。

用Python和Keras搭建你自己的AlphaZero

遊戲的規則很直接:玩家輪流在任何一欄的頂部放置自己的顏色的棋子。誰最先在垂直、水平或對角線上都放置了同一種顏色,則獲勝。如果全部網格都被填滿,仍然沒有出現同一顏色的棋子出現在同一條線上,則平局。


以下是組成程式碼庫的關鍵檔案的總結:

game.py

該檔案包含《四子連珠》的遊戲規則。

每個方格分配一個從0到41的數字,如圖:

用Python和Keras搭建你自己的AlphaZero

此檔案給出了根據給定動作,從一種遊戲狀態轉移至另一種的邏輯。例如,給定空棋盤和 38 號動作,takeAction 方法返回到一個新的遊戲狀態,起始玩家的位置則位於中間列的底部。


你可以用任何符合相同 API 的遊戲檔案替換 game.py 檔案,原則上演算法將根據你給它的規則通過自我博弈學習遊戲策略。


run.ipynb

它包含了開始學習過程的程式碼。它會載入遊戲規則,然後迭代演算法的主迴圈,其中包含三個階段:

  • 自我博弈
  • 再訓練神經網路
  • 評估神經網路

在這一迴圈中有兩個 agent:best_player 和 current_player。

其中 best_player 包含了效能最好的神經網路,用於生成自我博弈記憶。Current_player 然後會根據這些記憶再訓練其神經網路,接著與 best_player 進行對弈。如果它贏了, best_player 中的神經網路就會換成 current_player 中的神經網路,迴圈再次開始。


agent.py

它包含 Agent類(遊戲中的一個玩家)。每個玩家都用自己的神經網路和蒙特卡羅搜尋樹進行初始化。


Simulate 方法執行蒙特卡羅樹搜尋過程。具體說來,agent 移動至樹的一個葉節點,用其神經網路評估該節點,然後通過樹回填(backfill)該節點的值。


Act 方法多次重複 simulate 方法,以理解從當前位置移動至哪個位置是最有利的。然後它將選定的動作返回給遊戲,以執行該遊戲。


replay 方法使用之前的遊戲記憶再訓練神經網路。


Model.py

該檔案包含了 Residual_CNN 類,它定義如何構建神經網路的例項。

用Keras搭建的一個殘留卷積神經網路樣例


其採用 AlphaGo Zero 論文中的神經網路架構的壓縮版本——即一個卷積層,接著是一些殘留層,然後分解成值端(value head)和策略端(policy head)。


卷積過濾器的深度和數量可以在 config 檔案中設定。


Keras 程式庫用於搭建神經網路,使用 TensorFlow 後端。


要在神經網路中檢視單個卷積過濾和密集連線的層,可在 run.ipynb notebook 中執行以下程式碼:

current_player.model.viewLayers()
複製程式碼

神經網路中的卷積過濾器

MCTS.py

它包含節點、邊緣和 MCTS 類,它們構成了一個蒙特卡洛搜尋樹。

MCTS 類包含前面提到的 moveToLeaf 和 backFill 方法,並且邊緣類的例項儲存每個可能的移動的統計資料。


config.py

這是你設定影響演算法的關鍵引數的地方。

用Python和Keras搭建你自己的AlphaZero

調整這些變數將影響演算法的執行時間、神經網路的準確性和演算法的整體成功。上面的引數產生了一個高質量的《四子連珠》玩家,但是要花很長時間才能完成。為了加快演算法的速度,請嘗試以下引數。

用Python和Keras搭建你自己的AlphaZero

funcs.py

它包含了將兩個 agent 進行匹配的 playMatches 和 playMatchesBetweenVersions 函式。

如果要和你建立的玩家對戰,請執行以下程式碼(它也在 run.ipynb notebook 中):

from game import Game
from funcs import playMatchesBetweenVersions
import loggers as lg
env = Game()
playMatchesBetweenVersions(
env
, 1  # the run version number where the computer player is located
, -1 # the version number of the first player (-1 for human)
, 12 # the version number of the second player (-1 for human)
, 10 # how many games to play
, lg.logger_tourney # where to log the game to
, 0  # which player to go first - 0 for random
)
複製程式碼

initialise.py

當你執行該演算法時,所有的模型和記憶體檔案都儲存在 run 資料夾中,在根目錄中。

稍後要從這個檢查點重新啟動演算法,將 run 資料夾轉移到 run_archive 資料夾中,將一個執行編號(run number)附加到資料夾名字上。然後,將執行編號、模型版本號和 memory 版本號輸入到 initialise.py 檔案中,run_archive 資料夾中相關檔案的位置對應。然後從這個檢查點開始,像往常一樣執行該演算法。


memory.py

這是 Memory class 的一個例項,用以儲存之前遊戲的記憶,該演算法會用它們重新訓練 current_player 的神經網路。


loss.py

此檔案包含一個自定義損失函式,用以在傳遞到交叉熵損失函式之前對非法移動的預測進行掩碼處理。


settings.py

run和run_archive 資料夾的位置。


logger.py

這個檔案包含一個自定義的損失函式,它在傳遞到交叉熵損失函式之前,掩蓋了非法移動的預測。


settings.py

run 和 run_archive 資料夾的位置。


loggers.py

日誌檔案被儲存到 run 資料夾中的 log 資料夾。要開啟日誌記錄,可將該檔案中 logger_disabled 變數的值設定為“False”。檢視日誌檔案將幫助你瞭解演算法的工作原理,並瞭解它的“思想”。例如,下面是 logger.mcts 檔案中的一個樣例:

用Python和Keras搭建你自己的AlphaZero

同樣來自 logger.tourney 檔案的一個樣例,你可以在評估階段看到每個與移動相關的概率:

用Python和Keras搭建你自己的AlphaZero

結果

經過幾天的訓練,小批量迭代次數後得出以下損失圖表:

用Python和Keras搭建你自己的AlphaZero

最上面的線是策略端的誤差(MCTS的交叉熵移動概率與神經網路的輸出相對應)。下面的線是值端的誤差(實際博弈值與神經網路值之間的均方差)。中間的線是兩者的平均值。

很明顯,神經網路在預測每個博弈狀態的價值和可能的下一步動作方面做得越來越好。為了展示這一結果如何變得更加強大,我在17個玩家之間進行了一場聯賽,從首次迭代的神經網路到第 49 次迭代,每對搭檔都對戰了兩次,兩名玩家都有機會先玩。

以下是最終排名:

用Python和Keras搭建你自己的AlphaZero

顯然,後期版本的神經網路優於早期版本,贏得了它們之間的大部分比賽。另外,學習似乎並沒有達到飽和,因為隨著訓練時間增加,玩家變得越來越強大,並且學習的策略越來越複雜。

例如,隨著時間的推移,神經網路所偏愛的一個明確策略就是儘早槍戰中心欄。觀察演算法的第 1 個版本和第 30 個版本之間的差別:


神經網路的第一個版本

用Python和Keras搭建你自己的AlphaZero

神經網路的第三十個版本


用Python和Keras搭建你自己的AlphaZero

這是一個很好的策略,因為很多下棋的線路都需要中間欄——要求儘量不要讓對手利用這一點。而神經網路在沒有任何人類知識輸入的情況下,已經學會了這一點。


學習一種不同的博弈遊戲


在 games 資料夾裡有個 game.py 檔案,用於一個叫做 Metasquares 的遊戲。這個遊戲是在網格中放置 X 和 O 標記,以嘗試形成不同大小的方塊。方塊越大,玩家分數越高。當網格被填滿時,得分最多的玩家獲勝。

用Python和Keras搭建你自己的AlphaZero

如果你將《四子連珠》的 game.py 檔案替換為 Metasquare 的 game.py 檔案,那麼我們上面使用的演算法就會學習玩 Metasquares 遊戲。

換言之,通過這種方式,我們搭建的模型可以學習任何一種博弈遊戲。




推薦閱讀

“女生科技體驗節” TensorFlow Workshop

這評論有毒!——文字分類的一般套路

我做了一個叫“瑟曦”的機器人,可是她動不動就想讓格雷果爵士弄死我。

相關文章