【问题标题】:go bot with minimax tree search too slow使用极小极大树搜索的机器人太慢了
【发布时间】:2019-09-19 18:19:39
【问题描述】:

我正在阅读《深度学习和围棋游戏》这本书,但我在书中没有走多远;我编写了基础(规则、辅助类)和 Qt GUI 界面。所有的作品,我决定写极小极大程序的例子,看看我能不能打败它;-) 但它太慢了:下一个动作需要几分钟,初始棋盘为 9x9。默认深度为 3 步,我认为第一步的计算需要 (9x9)x(9x9-1)x(9x9-2)~ 500 000 个位置。好的,它是 python,而不是 C,但我认为这可以在最多一分钟内计算出来。

我删除了一个对 copy.deepcopy() 的调用,这似乎消耗了很多时间。但是速度太慢了。

这里有一些东西: 计算线程:

class BotPlay(QThread):
    """
    Thread de calcul du prochain coup par le bot
    """

    def __init__(self, bot, bots, game):
        """
        constructeur, pour le prochain coup à jouer

        :param bot: le bot qui doit jouer
        :param bots: l'ensemble des 2
        :param game: l'état actuel du jeu (avant le coup à jouer)
        """
        QThread.__init__(self)
        self.bot = bot
        self.bots = bots
        self.game = game

    played = pyqtSignal(Move, dict, GameState)

    def __del__(self):
        self.wait()

    def run(self):
        self.msleep(300)
        bot_move = self.bot.select_move(self.game)
        self.played.emit(bot_move, self.bots, self.game)

选择移动方法及其类:

class DepthPrunedMinimaxAgent(Agent):

    @bot_thinking(associated_name="minimax prof. -> LONG")
    def select_move(self, game_state: GameState):
        PonderedMove = namedtuple('PonderedMove', 'move outcome')
        best_move_so_far = None
        for possible_move in game_state.legal_moves():
            next_state = game_state.apply_move(possible_move)
            our_best_outcome = -1 * self.best_result(next_state, capture_diff)
            if best_move_so_far is None or our_best_outcome > best_move_so_far.outcome:
                best_move_so_far = PonderedMove(possible_move, our_best_outcome)
        return best_move_so_far.move

    def best_result(self, game_state: GameState, eval_fn, max_depth: int = 2):
        if game_state.is_over():
            if game_state.next_player == game_state.winner():
                return sys.maxsize
            else:
                return -sys.maxsize

        if max_depth == 0:
            return eval_fn(game_state)

        best_so_far = -sys.maxsize
        for candidate_move in game_state.legal_moves():
            next_state = game_state.apply_move(candidate_move)
            opponent_best_result = self.best_result(next_state, eval_fn, max_depth - 1)
            our_result = -opponent_best_result
            if our_result > best_so_far:
                best_so_far = our_result
        return best_so_far

我几乎可以肯定问题不是来自 GUI,因为本书给出的程序的初始版本完全处于控制台模式,和我的一样慢。

我的要求是什么?好吧,要确定这种缓慢的行为是不正常的,也许是为了知道出了什么问题。 minimax算法来自书本,所以没问题。

谢谢

【问题讨论】:

    标签: python algorithm artificial-intelligence


    【解决方案1】:

    机器学习通常在 Python 中完成,因为:

      1. 简单又安全
      1. 它很灵活
      1. 所有繁重的工作都在专门的模块中完成,例如 tensorflow 和 keras

    在您的情况下,3. 不成立。所有这些嵌套调用、参数传递、复制和板评估都在 Python 中完成。成本是编译语言的 10 到 100 倍[需要引用]。

    流行的 ML 项目似乎都是用 Python 完成的,但实际的 Python 代码只是围绕处理和提供数据、控制对 tensorflow 的调用以及显示结果。这就是他们能做到的原因。

    所以,是的,在你的故事中没有什么不寻常的。你查过Leela-zero吗?它更复杂/涉及更多,但开源并且做得很好,它可能已经打败了你。

    【讨论】:

    • 当然,它打败了我:它已经在一些游戏中打败了stockfish,所以它的elo应该超过3300,不是吗?
    【解决方案2】:

    在 Python 中编写高性能(快速)搜索代码可能很困难。但是,如果你想使用 Python,首先要担心的是避免所有内存分配。尝试预先分配将使用的任何内存。要担心的第二件事是不必要的复制 - 确保您没有不必要地复制数据。这两项更改可能并不容易应用,但对于加速您的代码将大有帮助。

    这些在 C 或 C++ 等语言中更容易控制,但仍然可以在 Python 中完成。根据我的经验,在 Python 中编写不佳的基于搜索的程序(内存分配和不必要的复制)可能比编写良好的 C/C++ 程序慢 100 倍甚至 1000 倍。

    顺便说一句,蒙特卡洛树搜索 (MCTS) 是当今围棋中的主要方法,因此您可能需要研究 MCTS。但是,无论哪种方式,您都需要让您的代码运行得更快,才能让它运行良好。

    【讨论】:

    • MCTS 就在书中的 alpha-beta minimax 之后,但如果它这么慢,我不会编写这个代码只是为了等待 500 万个移动......我只会编写示例深层网络部分
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    相关资源
    最近更新 更多