星際爭霸2 AI 開發探索與展望
《星際爭霸》的國服重置版正在預售中,將在暑假期間登陸戰網。今年是星際爭霸發行20週年,這20年間RTS即時戰略遊戲從興起到沒落,在遊戲屆的地位已經大不如前。這其中的一個原因是它的高度複雜性,從巨集觀的戰略,到微觀的操作,需要考慮並迅速做出反應的點太多太多。這樣的特點使得星際看的人多玩的人少,但卻恰恰適合征服圍棋後的AI來一展身手。當2016年AlphaGo擊敗李世石後DeepMind宣佈進軍星際2,眾多媒體紛紛發文:既圍棋之後,電子競技也要被AI征服了。而到了2017年,DeepMind聯合暴雪釋出了星際2的機器學習環境SC2LE和PySC2,使得廣大研究者都可以參與到這項挑戰中來,但另一方面也說明了AI征服星際絕非易事。
SC2LE,即StarCraft II Learning Environment(地址附於文末),星際爭霸2學習環境,它提供了完整的API介面來從外部對一局星際2遊戲進行控制。並且還包含錄影分析工具,可以把一局比賽中玩家的指令集依次提取出來。在windows、mac、linux上,SC2LE都有相應客戶端。而PySC2,則是DeepMind基於SC2LE開發出的python元件,使得研究者可以更方便的使用python編寫星際2的強化學習程式。並且PySC2中還額外包含7個小遊戲(地圖),分別是座標尋路、尋找收集礦物、尋找消滅跳蟲、槍兵vs蟑螂、槍兵vs毒爆跳蟲、採集礦物和瓦斯、建造槍兵
AlphaGo在圍棋上之所以能表現的如此完美,根本原因自然是近年來卷積神經網路的進步和計算機效能的不斷提升。但另一方面,圍棋本身的簡潔也很重要。雖然所需計算量很大,可圍棋的規則和輸入輸出卻非常簡單。而星際2的輸入輸出呢?讓我們來看看PySC2中是怎麼定義的。輸入共12種,可分為4類:
1. 遊戲資訊。
遊戲畫面資訊。這類似圍棋的棋盤輸入,是最主要的輸入資訊。畫面大小預設為84*84,分為13個子項。分別為:地形高度,地圖可見性,是否有蟲族菌毯,是否在己方神族水晶塔範圍內,單位所屬玩家ID,單位所屬玩家與己方關係,單位型別,單位是否被選中,單位剩餘生命值,單位剩餘護盾值,單位剩餘能量值,單位密度(部隊有可能堆疊在一起),單位密度精細值。
小地圖資訊。與遊戲畫面資訊類似,大小預設為64*64,只有7個子項:地形高度,地圖可見性,是否有蟲族菌毯,當前小地圖位置,單位所屬玩家ID,單位所屬玩家與己方關係,單位是否被選中。
己方玩家資訊。分為11個子項,包括:玩家ID,礦物數,瓦斯數,當前人口,當前人口上限,部隊所佔人口,農民所佔人口,閒置農民數,部隊數量,傳送門數量(神族),幼蟲數量(蟲族)。
2. 單位資訊。
單個單位資訊。選擇單個單位時提供,包括:單位型別,單位所屬玩家與己方關係,單位剩餘生命值,單位剩餘護盾值,單位剩餘能量值,運輸單位(所選單位為運輸機時),傳送百分比(所選單位為正在傳送的神族部隊時)。
多個單位資訊。選擇多個單位時提供,每個單位的具體資訊與上面一致。
運輸機中所有單位資訊。選擇運輸機時提供,每個單位的具體資訊與上面一致。
建築中所生產單位資訊。選擇產兵建築時提供,每個單位的具體資訊與上面一致。
運輸機中可用空位。選擇運輸機時提供,代表運輸機中還剩下多少位置。
編組資訊。提供玩家各個編組的單位資訊,最多10組,每組提供本組的單位數量和第一個單位的型別。
3. 環境資訊。
遊戲迴圈。代表當前遊戲是第幾局。
累計得分。提供當前遊戲己方玩家的多項得分,以作為獎勵進行強化學習。
4. 可用指令集資訊。給出當前所有的可用指令,也就是對輸出範圍進行了指定。
可以看到,PySC2的輸入擁有眾多類別,複雜性遠遠超過圍棋,當然玩過即時戰略遊戲的玩家對這些應該還是比較熟悉的哈哈。另一方面,以這樣的形式給出輸入,使得AI和人類玩家所獲得的資訊是一模一樣的,嚴格保證了遊戲公平性。而在輸出時,PySC2還可以對AI的APM進行限制,預設為180,和中等水平人類玩家相當。所有的輸出指令共計524個,每個指令又有各自的引數,所有的引數型別共13種。常用的指令比如:
·移動小地圖位置。引數型別為小地圖的座標,顯示這個座標的畫面。
·框選單位。引數型別為兩個遊戲畫面的座標,代表遊戲畫面中一個矩形的左上角和右下角,對這個矩形中的已方單位進行框選。
·基於遊戲畫面的移動攻擊。引數型別為遊戲畫面的座標,控制所選單位平A到遊戲畫面中的指定位置。
·建造建築。引數型別為建築型別,控制所選農民建造指定建築物。
瞭解了輸入輸出,接下來我們就可以編寫AI了。PySC2提供了一個在MoveToBeacon小遊戲中的簡單訓練指令碼AI。MoveToBeacon小遊戲,類似各種即時戰略遊戲新手教程的第一關,就是控制一個機槍兵不停的移動到指定位置。
class MoveToBeacon(base_agent.BaseAgent):
"""An agent specifically for solving the MoveToBeacon map."""
def step(self, obs):
super(MoveToBeacon, self).step(obs)
if _MOVE_SCREEN in obs.observation["available_actions"]:
player_relative = obs.observation["screen"][_PLAYER_RELATIVE]
neutral_y, neutral_x = (player_relative == _PLAYER_NEUTRAL).nonzero()
if not neutral_y.any():
return actions.FunctionCall(_NO_OP, [])
target = [int(neutral_x.mean()), int(neutral_y.mean())]
return actions.FunctionCall(_MOVE_SCREEN, [_NOT_QUEUED, target])
else:
return actions.FunctionCall(_SELECT_ARMY, [_SELECT_ALL])
程式碼結構為:繼承BaseAgent定義一個類,實現step函式,引數obs包含了所有的輸入資訊。首先判斷_MOVE_SCREEN控制單位移動指定是否可用,如果不可用則說明還沒有選中機槍兵,那麼就返回帶_SELECT_ALL的_SELECT_ARMY指令(F2)選中所有部隊。在可以呼叫_MOVE_SCREEN時,則檢視輸入中screen遊戲畫面中的_PLAYER_RELATIVE部隊歸屬子項,統計出所有部隊歸屬為_PLAYER_NEUTRAL中立單位的位置。再計算這些位置的平均值,得到需要移動到的Beacon的中心點target。最後呼叫帶[_NOT_QUEUED, target]的_MOVE_SCREEN指令,讓所選機槍兵立即移動到target位置。
我也編寫了一個不帶學習能力的指令碼AI,在Simple64地圖上用人族擊敗了各族的瘋狂電腦。Simple64地圖是一個比較小的雙人對戰地圖,為正常的採礦造兵模式。這個指令碼選的戰術和當初我剛打星際2時所選的一樣,6BB(表鄙視我- -)...流程相當簡潔粗暴,就是不停造農民造滿16個,要卡人口了就造房子,有錢了就造兵營直到6個,兵營不停出機槍兵,機槍兵夠24個了就神聖的F2A(全部選中進攻敵人基地)。具體效果怎麼樣,相信用過的人都知道哈哈。而用指令碼來實現的話,除了編寫上述流程外,還有一些細節需要注意:基地與兵營集結點的設定,建築位置的選擇,讓造完建築的農民回來採礦,對人口增長速度的預判。通過這個指令碼,我充分熟悉了PySC2環境,也清楚了強化學習AI在正常對戰中的具體訓練目標(程式碼地址見文末)。
那麼對於一個強化學習的AI,每回合需要進行的操作流程是哪些呢:
·對輸入的遊戲資訊進行資料處理,轉換成自己模型所需的形式。
·搜尋模型對於本輪輸入,權值最大的輸出。
·根據本輪的得分變化和最大權值,對模型的引數進行更新。
我用深度強化學習先後訓練了MoveToBeacon移動到指定位置、CollectMineralShards收集礦物、DefeatRoaches機槍兵vs蟑螂、DefeatZerglingsAndBanelings機槍兵vs跳蟲毒爆這四個小遊戲。為了降低訓練難度,每次都先選中所有部隊,之後進行的指令限定為移動或移動攻擊,通過卷積神經網路來學習指令引數中的座標。那麼在MoveToBeacon中,需求其實就是在screen中選出相應的_PLAYER_RELATIVE;在CollectMineralShards中,需求是選出距離槍兵最近的礦物;在DefeatRoaches中,則是選出血量最少的蟑螂進行攻擊;在DefeatZerglingsAndBanelings中,需求是識別出最近的毒爆進行優先攻擊。在這四個任務中,所需的輸入資訊其實有限,我也就只從screen遊戲畫面資訊中選取了一部分,包括:unit_type單位型別、player_relative單位歸屬、unit_hit_points單位剩餘生命值、selected選中單位。為了加速訓練速度提升訓練效果,我對這幾個輸入進行了進一步增強,把unit_type、player_relative、unit_hit_points按是否被選中又各分為了selected和unselected兩部分。並且統計出了所有選中單位的平均座標,計算了地圖上各個點到這個座標的距離作為又一個輸入,從而讓網路更容易學習到離機槍兵最近的礦物或者毒爆。最後,我為了程式又添加了基於錄影的學習方式。相比於自主強化學習,從錄影中學習的step函式中多了一個action引數,從而告訴程式在本輪中錄影裡玩家如何選擇。使用從錄影中學習時,AI可以通過一個幾十秒的replay訓練一遍就可以對MoveToBeacon、CollectMineralShards和DefeatRoaches學習完畢(github地址見文末)。
雖然這樣的訓練速度堪稱光速,但畢竟不夠通用,而且效果也只能算一般。最近DeepMind倒是又發了一篇PySC2的論文,提出了用Relational Deep Reinforcement Learning關係性深度強化學習來訓練這7個小遊戲,從而提升模型的泛化能力並更容易使用背景知識。通過RDRL,DeepMind在6個小遊戲上達到了當前的最高水平,訓練效果的視訊地址見:http://bit.ly/2kQWMzE(需翻牆)。可以看到,在機槍兵vs跳蟲毒爆的小遊戲中,AI學會了用一兩個機槍兵頂在前面吸引毒爆,用大部隊在後麵點毒爆瘋狂輸出,取到了很好的效果。當然,在這背後也仍然需要海量的模型迭代計算量,我們一般還是很難玩得起的。
PySC2已釋出近一年之久,對於其中的7個小遊戲,可以通過錄像來迅速訓練好模型,可以通過更先進的模型來取得超越人類的效果。這能讓我們感到一些慰藉,看到一絲光亮,但真正能與人類玩家對戰的星際2 AI仍舊遙遠。相信在之後的研究中,從錄影中學習、對輸入的人為增強處理以及背景知識的錄入在很長一段時間內仍然是必要的。另一方面,AlphaGo可以通過蒙特卡洛樹、價值網路和快速走子來對棋局的發展做出預測,可星際2的AI呢?是通過暴雪的SC2LE來提前模擬比賽的發展,還是在AI中自己儲存各單位的詳細資料以對遊戲進行粗略預測,這也是一個至關重要的問題。最後,上個月中國剛成年的智障人皇李中堂time宣佈暫時離開星際,在此緬懷一下他在《中國好星際》第四季中的音容笑貌,期待他可能的迴歸,祝一切順利~
相關連結