Day20 AlphaZero General
===
連續幾天都在介紹理論跟我猜沒什麼人看的公式,是時候該帶大家動手做了,身為一個AI工程師今天就來從零開始實作AlphaGo吧。
開玩笑的,就不要自己造輪子了吧,何況我現在沒有chatGPT + Copilot已經不會寫code了,我怕造出來的輪子長得像下圖這樣。
![image](https://hackmd.io/_uploads/SJv1e_TC0.png)
今天我們要直接用大神造好的輪子!
## AlphaZero General
分享一個知名的開源框架:[AlphaZero General](https://github.com/suragnair/alpha-zero-general),是一個基於 AlphaGo Zero 的自我對弈強化學習框架,以下簡稱AZG。
作者是Surag Nair先生,剛剛看了一下他的linkedin,發現他都博士畢業一年了,雖然他絕對看不到這篇但還是恭喜他。
### 抱在巨人的大腿上
想當初2018年時,以為他是什麼很厲害的大叔,沒想到其實年紀跟我一樣大,而且也正在讀碩士,怎麼別人的side project都是這種拿到幾千顆星星的大型專案,而我只能寫些屎project(之後會分享),當年修類神經網路的課,我還是用AZG來完成我的期末project,感恩Surag Nair讚嘆Surag Nair。
我這樣也算是抱在巨人的大腿上吧。
![image](https://hackmd.io/_uploads/HyvkEdaCR.png)
只要他一抬腳,我也是能飛得又高又遠的。
![巨人](https://hackmd.io/_uploads/BkENEd6AC.jpg)
最佛心的是他居然還有在更新,比起我2018年用的時候又更好用了,我們實驗室有幾位大神也是Contributors。
## 使用說明
(安裝python跟各種環境這裡就不教學了,網路上多到數不清了。)
使用AZG的好處就是clone下來馬上就能動,只要執行`main.py`馬上就開始訓練。
```
python main.py
```
連狀況都還沒搞清楚,他已經開始Self Play了,甚至都不知道是在Play什麼。
![image](https://hackmd.io/_uploads/S1-yOOaRC.png)
其實是他已經實作好了幾款遊戲的遊戲邏輯,包含[Othello](https://zh.wikipedia.org/zh-tw/%E5%A5%A7%E8%B3%BD%E7%BE%85)(黑白棋)、Tic Tac Toe、Connect4等遊戲,而且還有Pytorch版跟Keras版,真是貼心。
也可以換成自己想要的遊戲,只需要將遊戲邏輯實作出來即可,一樣可以套用AZG框架。
### main
這邊也蠻清楚的,設定好參數就能開始訓練。
```
'numIters': 1000,
'numEps': 100, # Number of complete self-play games to simulate during a new iteration.
'tempThreshold': 15, #
'updateThreshold': 0.6, # During arena playoff, new neural net will be accepted if threshold or more of games are won.
'maxlenOfQueue': 200000, # Number of game examples to train the neural networks.
'numMCTSSims': 25, # Number of games moves for MCTS to simulate.
'arenaCompare': 40, # Number of games to play during arena play to determine if new net will be accepted.
'cpuct': 1,
```
`numIters` 訓練的總迭代次數,這裡預設是 1000。
`numEps` 每次迭代中進行的自我對弈遊戲數量,就是那一執行馬上就開始的Self Play,這裡預設為 100。這邊在AlphaGoZero論文中是寫25000局,你可以根據不同遊戲的複雜度來設定,或是看你的硬體設備(財力)來決定。
`tempThreshold` 溫度閥值,預設為 15。這跟探索策略有關,影響遊戲前期的隨機性,當遊戲超過一定回合後溫度會降低,從而減少隨機性。
`updateThreshold` 更新閾值,預設為 0.6。這是arenaCompare中新舊神經網路的對戰勝率,設為0.6代表新神經網路勝率高於60%時,就會更新。
`maxlenOfQueue` 訓練神經網路的遊戲樣本Queue的最大長度,預設為 200000,就是最多保留 200000 個遊戲樣本用於訓練。
`numMCTSSims` 每次行動中 MCTS 進行的模擬次數,預設為 25。這決定了在每次選擇動作時,MCTS 要進行多少次模擬,這邊在AlphaGoZero論文中是寫1600次,你可以根據不同遊戲的複雜度來設定,或是看你的硬體設備(財力)來決定。
`arenaCompare` 新舊網路進行對戰的場次,這裡預設為 40 場,我記得之前學長說400場會是一個比較好的數字,具體證明我已經忘了。
`cpuct` 這個就是PUCT公式中的那個常數C
$$
a_t = \arg\max_a \left( Q(s_t, a) + c \cdot P(s_t, a) \cdot \frac{\sqrt{N(s_t)}}{1 + N(s_t, a)} \right)
$$
這個C寫成 $C_{puct}$
這邊預設為1,但其實 $C_{puct}$ 隨著模擬總數動態調整會比較好,具體要怎麼設置大家可以自行嘗試看看,或是參考其他論文的設定,這裡就不展開了。
### pit
這邊作者有提供黑白棋的pretrained model,所以直接執行`pit.py`就可以跟電腦對戰了。
```
python pit.py
```
預設是8x8的黑白棋,有點感動他終於對齊了,2018年時預設的是6x6黑白棋,並且因為棋盤印出來是歪的,有點強迫症的我當初還花了點時間慢慢喬正,不知道作者是什麼時候更新的,感動。
![](https://hackmd.io/_uploads/Hyo3wBaAC.png)
本來想放我把AI電爆的畫面截圖,但我連玩了好幾場都輸,只能交給大家去嘗試了,還差點玩到忘記發文。
### MCTS
這段就是PUCT的實際程式碼,大家就可以自由發揮,比如把它改成LCB。
```python=
cur_best = -float('inf')
best_act = -1
for a in range(self.game.getActionSize()):
if valids[a]:
if (s, a) in self.Qsa:
u = self.Qsa[(s, a)] + self.args.cpuct * self.Ps[s][a] * math.sqrt(self.Ns[s]) / (1 + self.Nsa[(s, a)])
else:
u = self.args.cpuct * self.Ps[s][a] * math.sqrt(self.Ns[s] + EPS) # Q = 0 ?
if u > cur_best:
cur_best = u
best_act = a
```
這邊是處理葉節點與更新的程式碼,這邊也可以嘗試用之前介紹到的Quick Win、Big Win之類的方式去改進。
```python=
if s not in self.Ps:
self.Ps[s], v = self.nnet.predict(canonicalBoard)
valids = self.game.getValidMoves(canonicalBoard, 1)
self.Ps[s] = self.Ps[s] * valids # masking invalid moves
sum_Ps_s = np.sum(self.Ps[s])
if sum_Ps_s > 0:
self.Ps[s] /= sum_Ps_s # renormalize
else:
log.error("All valid moves were masked, doing a workaround.")
self.Ps[s] = self.Ps[s] + valids
self.Ps[s] /= np.sum(self.Ps[s])
self.Vs[s] = valids
self.Ns[s] = 0
return -v
```
```python=
if (s, a) in self.Qsa:
self.Qsa[(s, a)] = (self.Nsa[(s, a)] * self.Qsa[(s, a)] + v) / (self.Nsa[(s, a)] + 1)
self.Nsa[(s, a)] += 1
else:
self.Qsa[(s, a)] = v
self.Nsa[(s, a)] = 1
self.Ns[s] += 1
return -v
```
### Arena
這邊是用來對戰的,可以讓新舊網路進行對戰,統計勝率來決定要不要更新網路。
但是這邊從2018到現在都有一些小問題沒有修正,也有引發了一些討論。
[Different approaches for MCTS instancing in Self Play and Arena #24](https://github.com/suragnair/alpha-zero-general/discussions/24)
[MCTS should not keep "tree" between games. #206](https://github.com/suragnair/alpha-zero-general/issues/206)
主要就是在Arena中的每場對戰結束後都沒有將樹給清掉,他會一直維護同一棵樹,
![image](https://hackmd.io/_uploads/SJiN5Dtx1x.png)
![image](https://hackmd.io/_uploads/rJsScDKgkg.png)
![image](https://hackmd.io/_uploads/SkjU5wYeyx.png)
**Dirichlet noise**
### Maverick
Maverick是目前世界上最強的黑白棋程式,作者為陳彥吉,連續拿了好幾屆的TCGA、TAAI、ICGA金牌,大家可以猜猜他是怎麼做的。
之前日本有開發[世界最弱黑白棋程式](https://www.4gamers.com.tw/news/detail/39795/computer-othello-ai-will-always-let-you-win),但其實黑白棋你只要能做出最強,那同時也可以最弱(只要把獲勝條件那邊加個負號就好了),那個標題其實只是一個噱頭吧,所以Maverick也是可以輕鬆比他還弱的,歡迎大家實作自己的黑白棋程式去參加比賽,挑戰這支多年連霸的冠軍程式。
## 其他開源框架或程式推薦
* [MuZero General](https://github.com/werner-duvaud/muzero-general)
MuZero: Mastering Go, chess, shogi and Atari without rules
也是DeepMind發表的,是一個不需要環境的明確規則或模型就能進行學習的強化學習框架,比起AlphaZero又更進一步,這次連規則都不需要就能夠學會下棋,這個可能就比較少人知道了,有興趣的可以去看看原論文。
* [KataGo](https://github.com/lightvector/KataGo)
如果是想訓練圍棋AI的話可以參考一下KataGo,當然其中的一些改進也是可以用在別的遊戲上。
* [Sayuri](https://github.com/CGLemon/Sayuri)和[pyDLGO](https://github.com/CGLemon/pyDLGO),這邊幫一位優秀的學弟推薦一下,這是他做的圍棋程式,就是**第16屆UEC亞軍的程式**,裡面有很詳細的說明,如果想學習實作圍棋AI的話,這會對你非常有幫助。
* [AlphaZero_Gomoku](https://github.com/junxiaosong/AlphaZero_Gomoku)
什麼?你說我只推薦圍棋?這不是來了嗎,各位觀眾「五子棋」,好了,剩下的大家自己探索吧。
## 論文推薦
這邊論文多到爆,歡迎大家選喜歡的遊戲去研究。
* [在下棋與訓練階段改進AlphaZero演算法](https://etds.lib.ntnu.edu.tw/thesis/detail/965feca0896757a0aadfca6515239c49/)
* [AlphaZero演算法結合快贏策略或迫著空間實現於五子棋](https://etds.lib.ntnu.edu.tw/thesis/detail/da8499e71517ac31e79e84d29238e3ec/?seq=19#)
* [改進AlphaZero的大贏策略並應用於黑白棋](https://etds.lib.ntnu.edu.tw/thesis/detail/a0b7ec867dc4fc97ba735836d0156313/)
* [基於AlphaZero General Framework實現Breakthrough遊戲](https://etds.lib.ntnu.edu.tw/thesis/detail/e82bb4e52dbfe40bc754965711b9680e/)
* [蒙地卡羅樹搜索法的必贏策略以及快速Nonogram解題程式的實作](https://etds.lib.ntnu.edu.tw/thesis/detail/1bfe92a10027d91e6733716bcbdf38fb/)
* [增強學習架構與期望最小最大算法之愛因斯坦棋實作比較](https://etds.lib.ntnu.edu.tw/thesis/detail/23e18e98ddd5e9070d36a37d8bb76194/)
* [中國跳棋對局程式研發與深度學習之探討](https://etds.lib.ntnu.edu.tw/thesis/detail/fca08fd7f1d9b5020218e3865f8821ce/)
* [六貫棋遊戲實作與強化學習應用](https://etds.lib.ntnu.edu.tw/thesis/detail/8fa7a138501962327c9a061add22c6b9/)
* [利用有利條件訓練神經網路-以六子棋為例](https://etds.lib.ntnu.edu.tw/thesis/detail/905ca36c60f16bc0ed036ee23aebfcc6/)
* [中國跳棋對弈平台與AI的實作](https://etds.lib.ntnu.edu.tw/thesis/detail/7996f1a0c15647b2268cd111e6ac0c86/)
* [基於強化學習之Surakarta棋程式開發與研究](https://etds.lib.ntnu.edu.tw/thesis/detail/8fa7a138501962327c9a061add22c6b9/)
* [利用AlphaZero框架實作與改良MiniShogi程式](https://etds.lib.ntnu.edu.tw/thesis/detail/aa4a0146968fd11afa1364536f5e55c9/)
* [基於AlphaZero作法之國際跳棋程式開發及研究](https://etds.lib.ntnu.edu.tw/thesis/detail/432e98c2a7ac390a1ef5b320fb5259f2/)
* [MuZero 演算法結合連續獲勝走步改良外圍開局 五子棋程式](https://etds.lib.ntnu.edu.tw/thesis/detail/7e204adb3f0678bff2d1a6b6ea472573/)
* [基於AlphaZero General與MuZero General框架實現點格棋](https://etds.lib.ntnu.edu.tw/thesis/detail/38a8dd6b31567f351a71529de5d90ed9/)
* [使用KataGo方法及迫著空間搜尋提升AlphaZero在六子棋的訓練成效](https://etds.lib.ntnu.edu.tw/thesis/detail/40748f8537e0d82a9dee900b261606a1/)