Gomoku AI通过Monte Carlo树搜索


Jupyter Notebook中的Gomoku

在Jupyter Notebook中,显示框架,您可以排列Gomoku。 Gomoku AI是通过搜索Monte Carlo树实现的,旨在与人类对抗。
jupyter notebookの中で五目並べ

棋盘的大小为5x5,如果将四块垂直,水平和对角线对齐,则获胜者获胜(一排四排称为Gomoku,而四排则称为Gomoku另一个游戏名称(因为)。

下载程序文件

gomoku.ipynb
确认的操作环境:Microsoft Azure笔记本
有关执行方法,请使用jupyter notebook阅读上述文件后,查看第一个单元格。

蒙特卡洛树搜索

蒙特卡洛树搜索是一种模拟每块木板的良性的方法,该方法用于生长一棵树,该树的木板是节点(叶子),而可以从该木板击打的手是边缘(分支)。

大致来说,这是一种在板上尽可能多地预读的方法,这可能是更好的选择,但它也可以调查尚未尝试太多的板。某个董事会对AI有利还是不利,取决于该董事会随机采取的步骤,并确定哪个获胜。这种随机采取行动以了解结局的方法称为播出。

更具体地说,请执行以下操作。

モンテカルロ木探索

  • 假设有一块板(1)。
  • 在(1)之前一步,创建搜索树(2)至(5)。此时,请勿创建同一板。
  • 根据以下条件从(2)至(5)中选择一个。如果它是一个像(2)和(3)一样的分支节点,它将重复选择其子节点之一。
  • 如果所选叶节点的选择数量为n或更多,则会创建一个超出该数量的搜索树。如果不是,则随机进行比赛以确定获胜者。
  • 执行播放时,结果将传播到上层节点。
  • 返回处理3指定的次数。
  • 经过指定的次数后,从板子(1)的子节点(2)到(5)中选择具有最大选择数的移动并将其击中。
  • AI执行上述处理以选择移动。特别是,在时间允许的范围内运行3至5次。可以说,次数越多,人工智能越强。在这种Gomoku AI的情况下,根据经验已知,可以通过重复3到5 1000次来创建强大的AI。此外,AI在重复仿真后实际采取的动作是最频繁地仿真到板子的动作,如参考文献 1所示。

    从子节点中选择一个节点的标准:以下公式选择具有最大值的节点。

    1
    Q(s,a)+C_p\frac{\sqrt{2\log{n_s}}}{n_{s,a}}

    Q(s,a)Cp√2lognsns,<脚本类型="数学/特克斯;模式=显示" id =" MathJax-Element-1"> {Q(s,a)C_p \\ frac {\\ sqrt {2 \\ log {n_s}}} {n_ {s,a}}
    }

    Q(s,a)<脚本类型="数学/特克斯" id =" MathJax-Element-2"> Q(s,a):等于当您在某个棋盘上击中a时的获胜百分比值
    Cp <脚本类型="数学/特克斯" id =" MathJax-Element-3"> C_p:系数,用于平衡获胜百分比和选择次数
    ns <脚本类型="数学/特克斯" id =" MathJax-Element-4"> n_ {s}:选择板s的次数
    ns,<脚本类型="数学/特克斯" id =" MathJax-Element-5"> n_ {s,a}:从某块板s敲击a的次数

    Jupyter Notebook中的处理概述

    屏幕使用JavaScript编写,并通过IPython的HTML在Jupyter Notebook中显示。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    from IPython.display import HTML
    html = '''
    <div id="dialog" title="Gomoku">
        <div id="canvas-wrapper">
            <canvas id="dlg-canvas"></canvas>
        </div>
        <button id="start">Start</button>
        <div id="status"></div>
    </div>
    <script>
        $("#dialog").dialog();
    </script>
    '''
    HTML(html)

    在某一板上创建函数以确定哪一个获胜(或尚未决定是赢还是输)

    板的状态表示为一个数组,并通过操纵数组的索引确定帧是否垂直,水平和对角线排列。详细信息将在另一篇尚未发布的文章中进行解释。
    盤面のインデックス

    1
    2
    3
    4
    # 勝者判定
    def judge(cells,length=params["length"],n_pieces=params["n_pieces"]):
        # ....
        return 0

    创建一个类来判断将与板

    相同的布置

    同一板面是当从相反侧观察某个板面时具有相同框架布置的板面。当AI搜索移动时,组成同一块板的安排与进一步移动时的结果相同,因此为了提高效率,第二出现的同一块板是不处理目的地。此过程的详细信息将在另一篇尚未发布的文章中进行描述。

    盤面を回転、反転させて同じかどうかを判定する

    1
    2
    3
    4
    5
    # 予めすべての同一盤面ケースのインデックス配列を作成しておいて、
    # それによって同一盤面かをチェックするクラス
    class cell_comparator:
        # ....
        pass

    分开进行蒙特卡洛树搜索过程和Gomoku游戏第

    部分

    详细信息将在另一篇尚未发布的文章中给出。

    取决于游戏类型的部分由Game类实现。通过交换此类游戏,您可以为不同的游戏实现蒙特卡罗树搜索。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    # ゲームの種類によって変わる部分
    class Game():
        # 勝利判定を行う。player番号は1と-1とし、勝者の番号を出力する。勝利状態ではない場合は0を返す。
        def judge(self,state):
            return 0

        # 2つの盤面が同一かどうかを比較する。同じ場合True、違う場合はFalseを返す。
        def compare(self,state0,state1):
            return False

        # 引数の盤面からの有効手を取得する。同じ盤面になる手は、ここでは考慮しなくて良い。
        # MTCSは、game.compareを使用して、有効手から同じ盤面になる手を除外して処理を進める。
        # playoutは、この有効手をシャッフルしてランダムに手を進める。
        def actions(self,state):
            return []

        # 現在の盤面から一手を打つ
        # state: 盤面、player: 手を打つプレイヤの番号、action: 何をするか(五目並べの場合は、打つ場所)
        def move(self,state,action):
            return state2

        # playout
        def playout(self,state):
            return 0.0 #引き分け

        # 盤面の状態を、文字表現からおこす。
        def str2state(self,state_str):
            return {}
    game = Game()

    这是蒙特卡洛树搜索部分的代码。屏幕处理JavaScript调用python的next_ai方法。该过程执行蒙特卡洛树搜索并返回下一步。模拟次数由n决定,n的next_ai默认参数为1000。增加此数量将增加仿真数量并增强AI。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #
    # モンテカルロ木探索
    # 1つ前のセルにある、勝利判定と盤面の同一性調査を使用する。
    #

    # この回数だけ選択された盤面は、Expand処理として子ノードを作成して木を成長させる。
    exp_limit = 8
    # 選択フェーズにおいて、選択の評価値q+c(n) (q:盤面の評価値、c(n)選択回数の評価値)の
    # 選択回数の方にかける係数
    cp = 1.0

    # Stateオブジェクトを再利用するために、グローバル変数に配列を用意してそこにすべて保存する。
    # この配列内のインデックスは、Stateオブジェクトのcss_indexで保持している。
    css = []


    # class a state representing an condition of all stones on the borad
    class State():
        # ....
        pass

    # next ai interface
    def next_ai(state_str,n=1000):
        # 現在の盤面状態(cells)、次の手番(-1)、最初のStateは無条件でExpandするので
        # expand=TrueによってStateオブジェクトを生成する。
        cs = State(game.str2state(state_str),expand=True)
        cs.set_css_index(0)

        # グローバル変数のstate一覧に、最初のstateを追加する。
        global css
        css = [cs]

        # 指定回数分だけ、selectを実施する。selectの中では、
        # evaluate, expand, (暗黙的に)backupを実行している。
        for epoch in range(n):
            cs.select()
            pass
        return cs.solution()

    AI力量

    经验表明,具有1000次模拟的AI比人类更强大。如果第一步是人工智能,那么如果第一步是错误的,那么第二步往往会输给人工智能。但是,1000次模拟的AI有时会做出微弱的动作,因此人类可能会在那时获胜。

    具有2000次仿真的AI几乎没有出错。因此,如果第一步是AI,即使有平局,AI也几乎不会输。

    AI在做什么?

    无论如何,我会随机采取行动,并从中选择一个好的行动。 AI所知道的是(1)连续四块棋子的棋盘是AI或人类的胜利,并且(2)无法将新棋子放置在已经放置棋子的正方形上。人们认为这是游戏的一种策略,例如,在本游戏中,如果您连续制作两块两端都留有空格的棋子,那么对手将阻止一端,但在下一轮中击中剩下的另一端。对决定游戏的策略一无所知。结果,AI的行为就像不执行这些知识就知道那些人类知识。

    蒙特卡罗树搜索的可能性和限制

    除非可以完全搜索代表棋盘所有状态的搜索空间,否则将使用某种方法以有限的方式搜索手牌。那时,确定哪个是搜索目标和哪个不被搜索的差异是搜索方法的差异。例如,利用诸如αβ搜索的方法,不可能在没有实际搜索的情况下知道搜索需要多少时间。换句话说,如果搜索在中间停止,则通常不是该阶段的最佳解决方案。另一方面,蒙特卡罗树搜索基本上是从最佳解的可能性很高的地方搜索的。因此,即使在中间停止搜索,也可以认为在该阶段获得了最佳解。当实际上被用作游戏AI等时,与该时间成比例的搜索性能是非常好的特性。

    另一方面,这很自然,但是蒙特卡罗树搜索不能有效地用于无法从某个称为"淘汰赛"的棋盘获得游戏结束(很难获得)的问题。在此播出部分中,有一个 1,它使用诸如深度学习之类的技术,例如从某个板子上学习结尾。

  • https://www.nature.com/articles/nature16961?