我們已經知道UCB演算法能夠更快地找到靠譜的著手點,續上一篇的問,能不能再最佳化?
首先要知道的是,為什麼UCB演算法比盲目的蒙特卡羅局面評估收斂得更快?我的理解,是因為在演算法執行的過程中,UCB演算法能不斷根據之前的結果調整策略,選擇優先評估哪一個可下點。其實這是一種線上的機器學習策略。對於上一篇提到過的多臂匪徒問題,可以用UCB演算法很好地解決。對於圍棋博弈問題而言,UCB演算法相比於樸素的蒙特卡羅局面評估方法,收斂速度有很大的提高,但確實存在可進一步最佳化的地方。
上一篇中,把圍棋棋盤上的可下點比作了角子機,但他們之間有什麼不同呢?
答案是——多臂匪徒問題只有一層角子機,圍棋博弈問題則是多層角子機構成的博弈樹!
終於提到博弈樹了,需知在絕大多數棋類博弈問題中,博弈樹是必不可少的工具。這裡簡單介紹一下博弈樹搜尋中用到的最基本搜尋方法——最大最小搜尋(如果對博弈樹毫無概念,請自行google)。在一個二人零和博弈遊戲中,參與博弈的雙方所作出的每一個決策都是為了己方利益的最大化(廢話~)。假設我們把黑方獲勝時的棋局形勢設為一個正數值v,白方獲勝則是-v(其他情況下局勢介於v和-v之間),則黑棋的每一手棋都是為了使局勢儘可能的大,白棋反之。表現在博弈樹中,則黑棋層總是選擇局勢值最大的結點作為結果返回上一層,白棋層反之——這就是最大最小搜尋。
有了以上的科普,這裡就給出上一篇的答案——更最佳化的演算法,UCT演算法(UCB for tree)。以下是演算法描述:
給定一棵博弈樹。
1) 從博弈樹的根點開始向下搜尋,執行2)。
2) 遇到節點a後,若a存在從未評估過的子節點,執行3),否則執行4)。
3) 通過MonteCarlo方法評估該子節點,得到收益值後更新該子節點至根節點路徑上所有節點的平均收益值,執行1)。
4) 計算每個子節點的UCB值,將UCB值最高的子節點作為節點a,執行2)。
5) 演算法可隨時終止,通常達到給定時間或嘗試次數後終止。
根節點下平均收益值最高的子節點作為演算法的輸出。
對於這個演算法,有幾點需要解釋:
1)博弈樹的根節點指的是當前的局面。
2)評估過的節點及其平均收益值將在程式運行過程中儲存及更新。
3)收益值可自行設定合適的值。我知道MOGO的做法是將其設為1(勝)或0(負),我的程式Foolish Go的做法是,所得地區 / 總地區。
4)這個演算法是現代圍棋博弈程式的基石。
個人對這個演算法的理解是,本質上是一種迭代加深的DFS。
為了更好地理解UCT演算法的收斂性,不妨思考,這個演算法會怎樣“意識”到下一手棋應該征子?
理論的東西差不多介紹完了,下一篇將進入實戰。