摘要: 相信不少朋友都會玩國際象棋,那麼有嘗試過構建一個國際象棋引擎嗎,一塊兒來玩玩看吧!
我不擅長國際象棋。javascript
我父親在我年幼的時候教過我,但我猜他是那些一直讓他們的孩子獲勝的爸爸之一。爲了彌補世界上最受歡迎的遊戲之一的技能的缺少,我作了任何數據科學愛好者會作的事情:創建一我的工智能來擊敗我沒法擊敗的人。遺憾的是,它不如AlphaZero(甚至普通玩家)好。但我想看看國際象棋引擎在沒有強化學習的狀況下如何作,以及學習如何將深度學習模型部署到網絡上。html
比賽在這裏!java
FICS擁有一個包含3億場比賽,我的走法,結果以及所涉玩家評級的數據庫。我下載了全部在2012年的比賽,其中至少有一名玩家超過2000 ELO。這總計約97000場比賽,有730萬個走子。勝利分配是:43000次白方勝利,40000次黑方勝利和14000次平局。python
瞭解如何作一個深度學習象棋AI,我必須首先了解傳統象棋AI程序。來自於極小極大算法。Minimax是「最小化最大損失」的縮寫,是博弈論中決定零和博弈應如何進行的概念。git
Minimax一般用於兩個玩家,其中一個玩家是最大化者,另外一個玩家是最小化者。機器人或使用此算法獲勝的人假設他們是最大化者,而對手是最小化者。該算法還要求有一個棋盤評估函數,來衡量誰贏誰輸。該數字介於-∞和∞之間。最大化者但願最大化此值,而最小化者但願最小化此值。這意味着當你,最大化者,有兩個走法能夠選擇的時候,你將選擇一個給你更高評估的那個,而最小化者將作相反的選擇。這個遊戲假設兩個玩家都發揮最佳狀態而且沒有人犯任何錯誤。github
以上面的GIF爲例。你,最大化者(圓圈)有三個你能夠選擇的走法(從頂部開始)。你直接選擇的走法取決於你的對手(方塊)在走子後將選擇的走法。可是你的對手直接選擇的走法取決於你走子後選擇的走法,依此類推,直到遊戲結束。玩到遊戲結束會佔用大量的計算資源和時間,因此在上面的例子中,選擇一個深度,2。若是最小化者(最左邊的方塊)選擇左移,你有1和-1可供選擇。你選擇1,由於它會給你最高分。若是最小化者選擇正確的走法,則選擇0,由於它更高。如今是最小化者的回合,他們選擇0由於這更低。這個遊戲繼續進行,一直進行到全部的走子都完成或你的思惟時間耗盡。對於個人國際象棋引擎來講,假設白方是最大化者,而黑方是最小化者。若是引擎是白方,則算法決定哪一個分支將給出最高的最低分數,假設人們在每次走子時選擇最低分數,反之亦然。爲了得到更好的性能,該算法還能夠與另外一種算法結合使用:alpha-beta剪枝。 Alpha-beta剪枝截止系統適用於決定是否應該搜索下一個分支。web
個人研究始於Erik Bernhardsson關於國際象棋深度學習的優秀文章。他講述了他如何採用傳統方法制做AI下棋並將其轉換爲使用神經網絡做爲引擎。算法
第一步是將棋盤轉換爲輸入層的數字形式。我借用了Erik Bernhardsson的編碼策略,其中棋盤是一個熱編碼,每個方塊中都有一個棋子。這總計爲768個元素數組(8 x 8 x 12,由於有12種棋子)。數據庫
Bernhardsson選擇將輸出圖層設爲1表示白方勝利,-1表示黑方勝利,0表示平局。他認爲遊戲中的每一個板位置都與結果有關。若是黑方贏了,每一個棋的位置都被訓練成「支持黑方」,若是白方贏了,則「支持白方棋」。這容許網絡返回介於-1和1之間的值,這將告訴你該位置是否更有可能致使白贏或黑贏。flask
我想用稍微不一樣的評估函數來解決這個問題。網絡是否可以看到不是白方仍是黑方獲勝,而是可以看到哪一個走子將致使勝利?首先,我嘗試將768元素的棋盤表示放入輸出,其中一個位置是輸入,下一個位置是輸出。固然,這沒有用,由於這把它變成了一個多分類問題。這致使引擎適當地選擇合法走子時出現太多的錯誤,由於輸出層中的全部768個元素能夠是1或0。所以,我查閱了Barak Oshri和Nishith Khandwala的斯坦福大學論文《利用卷積神經網絡預測國際象棋中的運動》,瞭解他們如何解決這個問題。他們訓練了7個神經網絡,其中1個網絡是棋子選擇器網絡。這個網絡決定哪個方格最有可能被移動。其餘六個網絡專門針對每個棋子類型,並決定將一個特定的棋子移動到哪裏。若是棋子選擇器選擇了一個帶有兵的方格,那麼只有棋子神經網絡會響應最有可能移動到的方格。
我從他們的想法中借鑑了兩個卷積神經網絡。第一個,從網絡移動,將被訓練成採用768元素數組表示並輸出專業棋手移動的方格(在方塊0和方塊63之間)。 第二個網絡:移動到網絡,將作一樣的事情,除了輸出層將是專業棋手移動到的地方。我沒有考慮誰贏了,由於我認爲訓練數據中的全部移動都是相對最優的,不管最終結果如何。
我選擇的架構是兩個128卷積層,帶有2x2濾波器,後面是兩個1024神經元徹底鏈接層。我沒有應用任何池,由於池提供位置不變性。圖片左上角的貓就像圖片右下角的貓同樣。然而,對於國際象棋,,棋子國王的值是徹底不一樣於車兵。隱藏圖層的激活功能是RELU,而我將softmax應用到最後一層,所以我基本上獲得一個機率分佈,其中全部方格的機率總和加起來達到100%。
個人訓練數據是訓練集的600萬個位置,其他130萬個位置用於驗證集。在訓練結束時,我從網絡上得到了34.8%的驗證準確率,而且在轉移到網絡時得到了27.7%的驗證準確率。這並不意味着70%的時間它沒有學習合法的走子,這隻意味着AI沒有像驗證數據中的專業玩家那樣作出相同的舉動。相比之下,Oshri和Khandwala的網絡平均驗證準確率爲37%。
由於如今這是一個分類問題,其中輸出能夠是64個類之一,這就留下了很大的錯誤空間。關於訓練數據(來自高級別玩家的比賽)的一個警告是,優秀的棋手不多會玩到「將軍」。他們知道何時輸了,一般沒有必要跟進整場比賽。這種缺少平衡的數據使得網絡在最終遊戲結束時很是混亂。它會選擇車來移動,並試圖沿對角線移動。若是失敗,網絡甚至會試圖指揮對手的棋子(厚顏無恥!)。
爲了解決這個問題,我命令輸出的機率。而後,我使用python-chess庫獲取給定位置的全部合法走子的列表,並選擇具備最高結果機率的合法走子。最後,我應用了一個帶有懲罰的預測分數方程式,用於選擇較不可能的走子:400(選擇的走子指數之和)。名單上的合法走子越遠,其預測得分就越低。例如,若是從網絡移動的第一個索引(索引0)與移動到網絡的第一個索引相結合是合法的,那麼預測分數是400(0 + 0),這是最高可能分數:400。
在與材料分數結合使用數字後,我選擇了400做爲最大預測分數。材料分數是一個數字,能夠判斷所作的走子是否會捕獲一個棋子。根據捕獲的棋子,走子的總體得分將獲得提高。我選擇的材料價值以下:
兵:10,馬:500,象:500,車:900,後:5000,王:50000。
這特別有助於殘局。在將殺走子將是第二個最可能的合法行動且預測得分較低的狀況下,國王的物質價值將超過它。兵的分數如此之低,由於網絡在早期比賽中考慮得足夠充分,因此若是它是戰略舉措,它將會採用兵。
而後我將這些分數結合起來,以返回給定任何潛在走子的棋盤的評估。我經過深度爲3的minimax算法(使用alpha-beta修剪)提供了這個,並獲得了一個能夠將殺的可運行國際象棋引擎!
我在Youtube上使用了Bluefever Software的指南,展現瞭如何經過向flask服務器發出AJAX請求來製做javascript國際象棋UI並經過它來路由個人引擎。 我使用Heroku將python腳本部署到Web並將其鏈接到個人自定義域:Sayonb.com。
雖然引擎的性能沒有我但願的那麼好,可是我學到了不少關於AI的基礎知識,將機器學習模型部署到web上,以及爲何AlphaZero不使用卷積神經網絡來玩遊戲!
能夠經過如下方式進行改進:
查看代碼,或者在GitHub repo用本身的訓練數據本身訓練一個新網絡!
本文爲雲棲社區原創內容,未經容許不得轉載。