寫在前面:
蒙特卡羅這個詞本身是賭城,而蒙特卡洛方法中確實體現出了賭博的隨機性、不確定性。筆者在這想討論的是基于蒙特卡羅的樹搜索方法,該方法可被應用于圍棋、五子棋等博弈類游戲,通俗地解釋,蒙特卡羅樹搜索是一種
隨機算法
,在有限時間里,只能說是盡可能地去逼近最優解,但不一定能找到。
知乎上有個例子說是:假如筐里有100個蘋果,讓我每次閉眼拿1個,挑出最大的。于是我隨機拿1個,再隨機拿1個跟它比,留下大的,再隨機拿1個……我每拿一次,留下的蘋果都至少不比上次的小。拿的次數越多,挑出的蘋果就越大,但我除非拿100次,否則無法肯定挑出了最大的。這個挑蘋果的算法,就屬于蒙特卡羅算法——盡量找好的,但不保證是最好的。
正文:
????還是先拿老虎機的例子來說事,假設你面前有兩臺老虎機,告訴你兩臺的勝率分別是0.8、0.6,哪一臺的勝率比較高呢?
????再假設兩臺老虎機各試驗了5次后,并發現5次內第一臺的的勝率是0.8、第二臺是0.6,可是此時就作出第一臺老虎機勝率高的判斷是不正確的,在試驗次數太少(只有5次)的情況下,無法斷定哪臺的老虎機勝率高,而當試驗次數足夠多時,才能夠做出準確的判斷,但同時也付出了相應的時間代價。
????接著,我們把情景移交到五子棋上邊來,我們拿下面的圖來做分析:
????圖中,每一個節點代表某種棋局情況,圈里的斜杠左邊的數字代表電腦在該節點下勝利的次數,斜杠右邊的數字代表該節點被訪問的次數。如12/21表示該節點下勝利了12次,總共訪問過21次。
????按照流程圖,該蒙特卡羅樹搜索有4個步驟:
-
選擇(Selection):從根節點走起,由于第二行已經沒有可拓展的節點(如有則需要把當前可拓展的點窮盡完),所以根據UCT(上限置信區間算法)如下圖,
????其中x是當前結點的勝率估計,N是節點的訪問次數,C是一個常數。C大就偏向于BFS,C小就偏向于DFS。此外,由于是子節點的訪問次數作分母,所以當該子節點的訪問次數較小時,反而會得到更大的score(即訪問次數少的更值得探索)
????逐步代入公式,得出:
????7/10的score為0.7+0.55C
????5/8的score為0.625+0.62C
????0/3的score為0+1.00C
????以此類推,最終選擇了第4行的3/3節點,由于該節點已經沒有了子節點,但同時五子棋游戲還沒結束(即不是終止節點),所以進入步驟2。 拓展(Expansion):在Selection步驟中我們已經選擇了3/3節點,現在要做的就是在3/3節點下再生成一個子節點,暫且命名為0/0,代表著一個新的,沒有試過的下法,或者說一個棋局局面。
模擬(Simulation):在這步,我們需要判定這個節點是好的還是壞的,可是由于此時還沒到終局,所以我們需要一種快速判定的方法。這篇文章的方法是隨機下子(夠快吧!!),即左右隨機下子互博,一直到終局,以此判定該節點的好壞。這樣的話,評估的準確性理所當然就會降低(畢竟是隨機下出來的),但勝在快,當次數足夠多的時候,模擬結果也會慢慢變得可靠。(不知道算不算是暴力窮舉算法巧用的一種)
讀者可以作如下思考:即使一開始計算機把一個不好的走子誤以為是好的走法,隨著它對這種走法的慢慢挖掘,這種走法的評估也會慢慢變壞,最后計算機就會放棄這種走法,從而讓自己能夠選擇其他更好的走法。
4.回溯(Backpropagation):在這步,由于有新的節點信息加入進來,所以需要更新我們現有的博弈樹。這里我們假設上步的結果是輸,所以0/0更新為0/1,并在該節點的基礎上,一步一步向上更新其他節點。這里還有一個小細節就是博弈游戲都是你走一步我走一步,所以回溯的時候應該把勝率變為負數,這樣的話,當切換走子方時,對方的勝率的負值就可以看作是自己的勝率,越接近零就越大。
偽代碼圖:
寫在最后:
????emmmmmm,到這里也算是我對蒙特卡羅樹搜索的一個復習了,借鑒了一些網上現有的教程,但主要都是自己的話及理解,如果讀者結合解釋來看偽代碼的話也是不難懂的,至于真代碼。。。。看我什么時候有空就用C++寫一個五子棋程序及實現蒙特卡羅算法咯。。。。記得一開始自己用Alpha-Beta剪枝算法來寫五子棋AI,結果由于評估那個環節做的不好,所以最后的AI蠻zz的。不管啦不管啦,如果說蒙特卡羅有哪里好的話,也是沒有評估這個環節(因為它自己評估了),以及能夠限定它的思考時間,這點在限時博弈里還是很好的。