蒙特卡罗树搜索的一点解析

写在前面:

蒙特卡罗这个词本身是赌城,而蒙特卡洛方法中确实体现出了赌博的随机性、不确定性。笔者在这想讨论的是基于蒙特卡罗的树搜索方法,该方法可被应用于围棋、五子棋等博弈类游戏,通俗地解释,蒙特卡罗树搜索是一种随机算法,在有限时间里,只能说是尽可能地去逼近最优解,但不一定能找到。
知乎上有个例子说是:假如筐里有100个苹果,让我每次闭眼拿1个,挑出最大的。于是我随机拿1个,再随机拿1个跟它比,留下大的,再随机拿1个……我每拿一次,留下的苹果都至少不比上次的小。拿的次数越多,挑出的苹果就越大,但我除非拿100次,否则无法肯定挑出了最大的。这个挑苹果的算法,就属于蒙特卡罗算法——尽量找好的,但不保证是最好的。

正文:

    还是先拿老虎机的例子来说事,假设你面前有两台老虎机,告诉你两台的胜率分别是0.8、0.6,哪一台的胜率比较高呢?
    再假设两台老虎机各试验了5次后,并发现5次内第一台的的胜率是0.8、第二台是0.6,可是此时就作出第一台老虎机胜率高的判断是不正确的,在试验次数太少(只有5次)的情况下,无法断定哪台的老虎机胜率高,而当试验次数足够多时,才能够做出准确的判断,但同时也付出了相应的时间代价

    接着,我们把情景移交到五子棋上边来,我们拿下面的图来做分析:


蒙特卡罗树搜索的一点解析_第1张图片

    图中,每一个节点代表某种棋局情况,圈里的斜杠左边的数字代表电脑在该节点下胜利的次数,斜杠右边的数字代表该节点被访问的次数。如12/21表示该节点下胜利了12次,总共访问过21次。
    按照流程图,该蒙特卡罗树搜索有4个步骤:

  1. 选择(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。

  2. 拓展(Expansion):在Selection步骤中我们已经选择了3/3节点,现在要做的就是在3/3节点下再生成一个子节点,暂且命名为0/0,代表着一个新的,没有试过的下法,或者说一个棋局局面。

  3. 模拟(Simulation):在这步,我们需要判定这个节点是好的还是坏的,可是由于此时还没到终局,所以我们需要一种快速判定的方法。这篇文章的方法是随机下子(够快吧!!),即左右随机下子互博,一直到终局,以此判定该节点的好坏。这样的话,评估的准确性理所当然就会降低(毕竟是随机下出来的),但胜在快,当次数足够多的时候,模拟结果也会慢慢变得可靠。(不知道算不算是暴力穷举算法巧用的一种)
    读者可以作如下思考:即使一开始计算机把一个不好的走子误以为是好的走法,随着它对这种走法的慢慢挖掘,这种走法的评估也会慢慢变坏,最后计算机就会放弃这种走法,从而让自己能够选择其他更好的走法。

4.回溯(Backpropagation):在这步,由于有新的节点信息加入进来,所以需要更新我们现有的博弈树。这里我们假设上步的结果是输,所以0/0更新为0/1,并在该节点的基础上,一步一步向上更新其他节点。这里还有一个小细节就是博弈游戏都是你走一步我走一步,所以回溯的时候应该把胜率变为负数,这样的话,当切换走子方时,对方的胜率的负值就可以看作是自己的胜率,越接近零就越大。

伪代码图:

蒙特卡罗树搜索的一点解析_第2张图片

写在最后:

    emmmmmm,到这里也算是我对蒙特卡罗树搜索的一个复习了,借鉴了一些网上现有的教程,但主要都是自己的话及理解,如果读者结合解释来看伪代码的话也是不难懂的,至于真代码。。。。看我什么时候有空就用C++写一个五子棋程序及实现蒙特卡罗算法咯。。。。记得一开始自己用Alpha-Beta剪枝算法来写五子棋AI,结果由于评估那个环节做的不好,所以最后的AI蛮zz的。不管啦不管啦,如果说蒙特卡罗有哪里好的话,也是没有评估这个环节(因为它自己评估了),以及能够限定它的思考时间,这点在限时博弈里还是很好的。

你可能感兴趣的:(蒙特卡罗树搜索的一点解析)