0
| 本文作者: AI研習(xí)社-譯站 | 2018-03-05 10:51 |
本文為雷鋒字幕組編譯的技術(shù)博客,原標(biāo)題How to build your own AlphaZero AI using Python and Keras,作者David Foster。
翻譯 | 黃偉聰 董星 校對(duì) | 凡江

在這篇文章,我會(huì)試著闡明三件事:
AlphaZero之所以是人工智能前進(jìn)一大步的兩個(gè)答案
怎樣生成一個(gè) AlphaZero方法論的副本使其能玩Connect4
怎樣改代碼能使其插入其他游戲仍然有用
AlphaGo → AlphaGo Zero → AlphaZero
在2016年三月,Deepmind 公司的 AlphaGo ,在超過(guò)2億人次觀看的比賽中,4比1打敗了18次世界冠軍的圍棋選手李世石。一個(gè)機(jī)器學(xué)會(huì)遠(yuǎn)超人類的下圍棋策略,以前認(rèn)為是不可能做到的,或者退一步,當(dāng)時(shí)認(rèn)為至少也要10年完成的。

AlphaGo vs 李世石 比賽第三場(chǎng)
這本就是一個(gè)卓越的成就。但是,在 2017年10月18日,DeepMind 取得了更大的飛躍性成就。
在一篇名為 ‘Mastering the Game of Go without Human Knowledge(無(wú)師自通圍棋)’的論文公布了一種新的算法,AlphaGo Zero 用其 100–0 大敗AlphaGo。不可思議的是,它僅僅靠自我博弈做到如此,從零開始并且逐漸找方法打敗舊版本。構(gòu)建一個(gè)超越人類的人工智能不再需要專家博弈時(shí)的數(shù)據(jù)庫(kù)。

圖表來(lái)自 ‘Mastering the Game of Go without Human Knowledge’
僅僅48天之后,在2017年12月5日,DeepMind 放出另一篇論文 ‘Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm(通過(guò)使用通用的強(qiáng)化學(xué)習(xí)算法,自我博弈來(lái)掌握國(guó)際象棋和日本象棋)’ ,文章展示了 AlphaGo Zero 如何成長(zhǎng),并最終能在國(guó)際象棋和日本象棋分別打敗世界冠軍程序StockFish和Elmo。整一個(gè)學(xué)習(xí)過(guò)程,AlphaGo Zero從第一次觀看比賽到成為世上最強(qiáng)象棋程序不到24小時(shí)。
由此,AlphaZero橫空出世?—而這個(gè)通用算法,無(wú)需人類專家的先驗(yàn)策略便能讓它快速掌握某些知識(shí)。
關(guān)于這個(gè)成就令人驚奇的兩點(diǎn):
1. AlphaZero 無(wú)需以人類知識(shí)作為輸入
這點(diǎn)是非常重要的。這意味著 AlphaGo Zero 根本的方法論能適用于 任何 完全信息的游戲(游戲臺(tái)面總是完全公開可見)因?yàn)樗螒蛞?guī)則外無(wú)需知道其他專業(yè)的知識(shí)。
這就是DeepMind 為什么能在原 AlphaGo Zero論文發(fā)表僅48天后,又發(fā)表國(guó)際象棋和日本象棋論文的原因。毫不夸張的說(shuō),要做得只是改變闡述博弈機(jī)制的輸入頭文件和調(diào)整與神經(jīng)網(wǎng)絡(luò)和蒙特卡洛搜索有關(guān)的超參數(shù)。
2. 這個(gè)算法出人意料的簡(jiǎn)潔
如果AlphaZero用的是世界上只有少數(shù)人能理解的超級(jí)復(fù)雜算法,那么這將是令人難以置信的成就。而讓它特別的是,實(shí)際上論文中許多理念遠(yuǎn)沒有以前的版本復(fù)雜。它的核心思路正是下面簡(jiǎn)單的學(xué)習(xí)口訣:
通過(guò)模擬演繹可能的未來(lái)場(chǎng)景,優(yōu)先考慮有前景的路徑,同時(shí)考慮其他人對(duì)你行為最有可能做出的反應(yīng)并繼續(xù)探索未知情況。
在到達(dá)一個(gè)陌生的場(chǎng)景后,評(píng)估所選位置有利程度并通過(guò)模擬路徑級(jí)聯(lián)先前位置的得分。
完成對(duì)未來(lái)可能性思考后,采取探索的最多次的行動(dòng)。
游戲結(jié)束,退回并且評(píng)估哪一步錯(cuò)判了對(duì)未來(lái)的影響由此來(lái)更新認(rèn)知。
這聽起來(lái)不像你當(dāng)時(shí)學(xué)習(xí)玩游戲的的過(guò)程? 當(dāng)你下一步壞著,可能你錯(cuò)判了著后位置對(duì)未來(lái)的影響,或者你錯(cuò)誤預(yù)測(cè)了對(duì)手的某個(gè)行動(dòng),所以你沒有去想這種可能性。而這正是AlphaZero在游戲中學(xué)習(xí)訓(xùn)練的兩個(gè)方面。
怎樣構(gòu)建你自己的AlphaZero
首先,為了得到較深層次AlphaGo Zero工作原理的理解,需要認(rèn)真看AlphaGo Zero背后的文檔。當(dāng)我們過(guò)代碼的每個(gè)部分時(shí)這很值得參考。這里同樣有一篇好文章更詳細(xì)解釋 AlphaZero如何工作。
代碼
套用這個(gè)包含我將引用代碼的Git庫(kù)。
開始學(xué)習(xí)流程之前,在Jupyter notebook頂部?jī)蓚€(gè)面板運(yùn)行run.ipynb 。一旦它建立了足夠的游戲位置的來(lái)填補(bǔ)它的記憶,神經(jīng)網(wǎng)絡(luò)就會(huì)開始訓(xùn)練。通過(guò)額外的自我博弈和訓(xùn)練,它會(huì)逐漸在預(yù)測(cè)上變好,從而做出更好的決策和使總體游戲行動(dòng)更智能。
現(xiàn)在我們來(lái)更深入地了解代碼,并且展示一些AI隨著時(shí)間變強(qiáng)大的成果。
注意—?這是我自己基于上面參考文獻(xiàn)對(duì)AlphaZero工作原理的理解.。如果以下有任何錯(cuò)誤,我請(qǐng)求原諒并且會(huì)盡力改正!
Connect4
我們算法學(xué)習(xí)的游戲是 Connect4 (或者Four In A Row)。遠(yuǎn)沒有圍棋復(fù)雜… 但總計(jì)仍有 4,531,985,219,092種位置情況。

connect 4
游戲規(guī)則很簡(jiǎn)單。玩家在棋盤輪流從有空位列的頂部放一個(gè)他們顏色的棋子。第一個(gè)達(dá)到同色四珠相串的玩家即贏(包括水平,豎直,對(duì)角線)。如果棋盤放滿也沒有四珠相串,則游戲平局。
以下是組成代碼庫(kù)的核心文件總覽:
game.py
每個(gè)方塊被分配了一個(gè)從0到41的數(shù)字, 如下:
這個(gè)文件包含了connect4的游戲規(guī)則。

Connect4的行動(dòng)方格
這個(gè) game.py 文件提供了從一個(gè)游戲狀態(tài)移動(dòng)到另一個(gè)的邏輯,給出可選的動(dòng)作。例如,給出一個(gè)空棋盤并進(jìn)行放置38號(hào)空位,這個(gè)行動(dòng)返回一個(gè)新的游戲臺(tái)面,就是開始玩家的這枚棋子將在中間列底部。
你能用任何游戲文件替換game.py文件,只要它適用于相同的API,并且算法會(huì)在你給定的規(guī)則上通過(guò)自我博弈學(xué)會(huì)策略。
run.ipynb
這個(gè)文件包含了啟動(dòng)學(xué)習(xí)過(guò)程的代碼。首先它會(huì)加載游戲規(guī)則,然后迭代算法的主循環(huán),其中包含三個(gè)階段:
自我博弈
神經(jīng)網(wǎng)絡(luò)再訓(xùn)練
神經(jīng)網(wǎng)絡(luò)評(píng)估
這個(gè)循環(huán)涉及到兩個(gè)智能體,最強(qiáng)玩家和當(dāng)前玩家。
最強(qiáng)玩家擁有表現(xiàn)最優(yōu)的神經(jīng)網(wǎng)絡(luò),用來(lái)產(chǎn)生自我博弈的學(xué)習(xí)記憶。當(dāng)前玩家在這些記憶的基礎(chǔ)上重新訓(xùn)練它的神經(jīng)網(wǎng)絡(luò),然后再與最強(qiáng)玩家進(jìn)行比賽。如果它贏了,最強(qiáng)玩家內(nèi)部的神經(jīng)網(wǎng)絡(luò)就會(huì)被切換到當(dāng)前玩家的神經(jīng)網(wǎng)絡(luò),再開啟新一輪循環(huán)。
agent.py
這段程序包含了智能體類(游戲中的一個(gè)玩家)。初始時(shí),每個(gè)玩家都有自己的神經(jīng)網(wǎng)絡(luò)和蒙特卡羅搜索樹。
模擬方法會(huì)運(yùn)行蒙特卡羅樹搜索過(guò)程。具體地說(shuō),智能體將移動(dòng)到樹的葉節(jié)點(diǎn),用它的神經(jīng)網(wǎng)絡(luò)對(duì)節(jié)點(diǎn)進(jìn)行評(píng)估,然后沿著樹向上填充節(jié)點(diǎn)的值。
行動(dòng)方法會(huì)多次重復(fù)模擬方法,從而獲得從當(dāng)前位置最有利的移動(dòng)方式。接著,它將所選操作返回到游戲中,并執(zhí)行這個(gè)動(dòng)作。
重玩方法利用以前游戲中的記憶重新訓(xùn)練神經(jīng)網(wǎng)絡(luò)。
model.py

使用Keras構(gòu)建的殘差卷積網(wǎng)絡(luò)樣本
這個(gè)文件包含了Residual_CNN(殘差卷積神經(jīng)網(wǎng)絡(luò))類,它定義了如何構(gòu)建一個(gè)神經(jīng)網(wǎng)絡(luò)的實(shí)例。
它使用AlphaGoZero論文中神經(jīng)網(wǎng)絡(luò)架構(gòu)的壓縮版-即一個(gè)卷積層,緊跟著是許多殘差層,然后分裂成一個(gè)數(shù)值和策略頭。
卷積濾波器的深度和數(shù)量可以在配置文件中設(shè)置。
Keras庫(kù)用來(lái)構(gòu)建網(wǎng)絡(luò),它的后端是Tensorflow。
想要查看神經(jīng)網(wǎng)絡(luò)中的單個(gè)卷積濾波器和緊密相連的層,運(yùn)行下面run.ipynb文本中的程序。
current_player.model.viewLayers()

神經(jīng)網(wǎng)絡(luò)中的的卷積濾波器
MCTS.py
這段代碼包含節(jié)點(diǎn)、邊和MCTS類,構(gòu)成了一個(gè)蒙特卡羅搜索樹。
MCTS類包含前面提到的moveToLeaf和backFill方法,并且Edge類的實(shí)例儲(chǔ)存了每個(gè)潛在移動(dòng)方式的統(tǒng)計(jì)數(shù)據(jù)。
config.py
這段程序用來(lái)定義影響算法的關(guān)鍵參數(shù)。
調(diào)整這些變量將影響運(yùn)行時(shí)間、神經(jīng)網(wǎng)絡(luò)的準(zhǔn)確性和算法整體的成功。上面的參數(shù)生成了一個(gè)高水平Connect4玩家,但這要花很長(zhǎng)時(shí)間才能做到。為了加快算法的速度,請(qǐng)嘗試以下步驟。

funcs.py
這段程序包含了 playMatches 和 playMatchesBetweenVersions 函數(shù),可以進(jìn)行兩個(gè)智能體之間的比賽。

為了和你創(chuàng)造的玩家進(jìn)行比賽,運(yùn)行下面的代碼(它也在run.ipynb文本中)
initialise.py
當(dāng)你運(yùn)行該算法的時(shí)候,所有的模型和內(nèi)存文件都保存在根目錄的run文件夾中。
之后想要從這個(gè)節(jié)點(diǎn)重新啟動(dòng)算法,需要將run文件夾轉(zhuǎn)移到run_archive文件夾,并在文件夾名稱中添加一個(gè)運(yùn)行編號(hào)。接著將運(yùn)行號(hào)、模型版本號(hào)和內(nèi)存版本號(hào)輸入到initialise.py文件,與run_archive文件夾中的相關(guān)文件位置相對(duì)應(yīng)。正常運(yùn)行算法后將會(huì)從這個(gè)節(jié)點(diǎn)開始啟動(dòng)。
memory.py
內(nèi)存類的一個(gè)實(shí)例,存儲(chǔ)了之前的游戲記錄,算法可以用它來(lái)訓(xùn)練當(dāng)前玩家的神經(jīng)網(wǎng)絡(luò)。
loss.py
這份文件包含一個(gè)自定義的損失函數(shù),在傳遞到交叉熵?fù)p失函數(shù)之前,它掩蓋了非法移動(dòng)的預(yù)測(cè)。
settings.py
定義了run和run_archive文件夾的位置。
loggers.py
日志文件保存在run文件夾中的log文件夾中。
想要啟動(dòng)日志記錄,將文件中的logger_disabled 變量值設(shè)置為False。
查看日志文件可以幫助你理解算法是如何工作的,并且參透它的“思想”。例如這里有一個(gè)log.mcts文件的樣本。

logger.mcts 文件輸出
在評(píng)估階段,同樣從logger.tourney文件中,可以看到每次移動(dòng)的概率:

logger.tourney 文件輸出
結(jié)果
經(jīng)過(guò)幾天的訓(xùn)練,我們得到了下面的損失vs小批量迭代次數(shù)關(guān)系圖。

損失vs小批量迭代次數(shù)關(guān)系圖
最上面的線形圖是策略頭中的錯(cuò)誤(MCTS移動(dòng)概率的交叉熵vs神經(jīng)網(wǎng)絡(luò)的輸出)。最下面線圖是值頭的誤差(實(shí)際游戲值和神經(jīng)網(wǎng)絡(luò)推測(cè)值之間的平均平方誤差)。中間線圖是這兩者的平均值。
顯而易見,神經(jīng)網(wǎng)絡(luò)在預(yù)測(cè)每個(gè)游戲狀態(tài)值和下一步可能動(dòng)作方面表現(xiàn)越來(lái)越優(yōu)異。為了展示它如何培養(yǎng)出一個(gè)逐步強(qiáng)大的玩家,我參加了17個(gè)玩家之間的一場(chǎng)聯(lián)賽,逐步使用神經(jīng)網(wǎng)絡(luò)的第1次到49次迭代。
每場(chǎng)比賽都進(jìn)行兩次,雙方都有機(jī)會(huì)走第一步。
這是最后的排名:

可以看出,神經(jīng)網(wǎng)絡(luò)后期版本贏得了大部分比賽,表現(xiàn)明顯要優(yōu)于前期版本。同時(shí),我們可以發(fā)現(xiàn)學(xué)習(xí)還沒有達(dá)到飽和——隨著訓(xùn)練時(shí)間的增加,玩家將會(huì)逐步變強(qiáng),學(xué)習(xí)越來(lái)越復(fù)雜的策略。
例如,盡早搶占中間列是神經(jīng)網(wǎng)絡(luò)一直偏愛的一個(gè)清晰策略。讓我們觀察一下算法的第1個(gè)版本和第30個(gè)版本之間的區(qū)別:

神經(jīng)網(wǎng)絡(luò)第一次迭代

神經(jīng)網(wǎng)絡(luò)第30次迭代
這是一個(gè)很好的策略,因?yàn)楹芏嗥遄酉噙B成線都需要占有中心列——搶先占領(lǐng)它可以確保你的對(duì)手失去優(yōu)勢(shì)。這是沒有任何人為輸入的情況下,由神經(jīng)網(wǎng)絡(luò)自己學(xué)會(huì)的策略。
學(xué)習(xí)一種不同的游戲
在games文件夾中有一個(gè)game.py 文件,它是 ‘Metasquares’ 的游戲文件。這個(gè)游戲需要在網(wǎng)格中放置X和O標(biāo)記,以形成不同大小的正方形。大方塊比小方塊得分更多,當(dāng)網(wǎng)格被填滿時(shí),得分最多的玩家獲勝。
如果你將Connect4的game.py文件替換成Metasquares游戲的 game.py文件,同樣的算法也可以用來(lái)學(xué)習(xí)如何玩Metasquares。
博客原址
更多文章,關(guān)注雷鋒網(wǎng)
添加雷鋒字幕組微信號(hào)(leiphonefansub)為好友
備注「我要加入」,To be a AI Volunteer !


雷鋒網(wǎng)雷鋒網(wǎng)
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。