游戏AI的创造思路-技术基础-蒙特卡洛树搜索(1)

本篇介绍蒙特卡洛树搜索算法,AlphaGo用于围棋计算的应用就是基于蒙特卡洛树搜索研发的~~~

目录

1. 定义

2. 发展历史

3. 公式和函数

3.1.算法的公式和函数

3.2. Python实现公式和函数

4. 运行原理

4.1. 运行原理

4.2. 各步骤用Python代码

5. 优缺点和缺陷的解决方案

5.1. 优缺点

5.1.1. 优点

5.1.2. 缺点和缺陷

5.2. 缺陷的解决方案

5.2.1. 收敛速度慢

5.2.2. 计算资源消耗大

5.2.3. 探索与利用的平衡

5.2.4. 并行化困难

6.  在游戏AI中的使用实例

6.1. 简单介绍

6.2. 围棋AI中的蒙特卡洛树搜索

Python代码实现


1. 定义

蒙特卡洛树搜索(Monte Carlo Tree Search, MCTS)是一种结合了蒙特卡洛方法和树搜索的算法,特别适用于那些通过模拟能够预测结果的问题,如棋类游戏。

MCTS通过模拟大量随机游戏来评估每个可行的行动,并基于这些模拟结果选择最优行动。

2. 发展历史

蒙特卡洛方法起源于上世纪四十年代中期,为解决当时原子能事业中的复杂问题而发展。

而蒙特卡洛树搜索的概念则是在2006年由Rémi Coulomb提出,作为围棋中的移动规划方法。

近年来,随着AlphaGo等AI系统的成功,MCTS在游戏AI领域的应用得到了广泛关注。

3. 公式和函数

3.1.算法的公式和函数

MCTS算法的核心公式通常包括UCB1(Upper Confidence Bound 1)公式,用于在树搜索过程中平衡开发与探索:

[ UCB1(S_i) = \overline{V_i} + c \sqrt{\frac{\log N}{n_i}} ]

其中,

(\overline{V_i}) 是节点 (S_i)的平均价值,

(c)是常数(通常取2),

(N) 是总探索次数,

(n_i) 是节点 (S_i) 的探索次数。

3.2. Python实现公式和函数

以下是一个简化的Python代码示例,用于实现MCTS中的选择函数,该函数使用UCB1公式来选择子节点:

import math  class Node:  def __init__(self, state, parent=None):  self.state = state  self.parent = parent  self.children = []  self.visits = 0  self.wins = 0  def ucb1(self, N, c=2):  if self.visits == 0:  return float('inf')  return self.wins / self.visits + c * math.sqrt(math.log(N) / self.visits)  def select(node, N):  while node.children:  best_child = max(node.children, key=lambda c: c.ucb1(N))  node = best_child  return node

4. 运行原理

4.1. 运行原理

MCTS的运行原理主要包括四个步骤:选择(Selection)、扩展(Expansion)、模拟(Simulation)、反向传播(BackPropagation)。

  1. 选择(Selection):从根节点开始,使用UCB1公式递归选择最优子节点直到叶子节点。

  2. 扩展(Expansion):如果当前叶子节点不是终止节点,则创建一个或多个子节点,并选择其中一个进行扩展。

  3. 模拟(Simulation):从扩展节点开始,随机模拟游戏直到结束,记录模拟结果。

  4. 反向传播(BackPropagation):将模拟结果反向传播,更新所有祖先节点的统计信息。

4.2. 各步骤用Python代码

以下是简化版的MCTS实现框架:

import math# 节点类定义
class Node:  def __init__(self, state, parent=None):  self.state = state  self.parent = parent  self.children = []  self.visits = 0  self.wins = 0  def is_terminal(self):  # 实现判断节点是否为终止节点的逻辑  # 这里只是示例,具体实现需要根据游戏规则来  return False  def uct_value(self, parent_visits):  if self.visits == 0:  return float('inf')  # 未访问过的节点UCB值设为无穷大  win_rate = self.wins / self.visits  exploration_factor = 2  # 探索因子,可以调整  return win_rate + exploration_factor * sqrt(log(parent_visits) / self.visits) # 算法函数定义
def mcts(root, num_iterations):  for _ in range(num_iterations):  node = root  # 选择Selection  while node.children:  node = select(node, node.visits)  # 扩展Expansion  if not node.is_terminal():  node = expand(node)  # 模拟Simulation  result = simulate(node.state)  # 反向传播Backpropagation  backpropagate(node, result)  # 选择逻辑函数
def select(node, parent_visits):  # 实现选择逻辑,这里使用UCT(Upper Confidence Bound for Trees)  return max(node.children, key=lambda child: child.uct_value(parent_visits))  # 节点扩展逻辑
def expand(node):  # 实现节点扩展逻辑 # 这里只是示例,具体实现需要根据游戏规则来生成新的状态  new_state = node.state.generate_next_state()  # 假设状态对象有一个生成下一个状态的方法  new_node = Node(new_state, node)  node.children.append(new_node)  return new_node  # 模拟逻辑函数  
def simulate(state):  # 实现模拟逻辑# 从当前节点的状态开始模拟  current_state = node.state  # 模拟游戏进行,直到达到终端状态  while not current_state.is_terminal():  # 根据当前状态随机选择一个动作  action = current_state.sample_random_action()  # 执行动作,得到新的状态  current_state = current_state.apply_action(action)  # 返回模拟结果,通常是胜负标识  return current_state.get_result()    # 反向传播函数  
def backpropagate(node, result):  while node:  node.visits += 1  if result > 0:  # 假设result为正表示胜利  node.wins += 1  node = node.parent#-------------------------------------------------------  
# 示例用法  
root = Node(initial_state)  # 假设有一个初始状态  
num_iterations = 1000  
mcts(root, num_iterations)

5. 优缺点和缺陷的解决方案

5.1. 优缺点

5.1.1. 优点

  1. 高效性:MCTS通过模拟大量随机游戏来评估每个可行的行动,相比其他算法,它能够在较短的时间内找到相对较好的解决方案。这种高效性使得MCTS在实时决策系统中特别有用,如游戏AI和自动驾驶。

  2. 通用性:MCTS不需要对问题的具体特性有先验知识,因此可以灵活应用于多种领域,包括博弈游戏、组合优化、决策制定等。它的通用性使得MCTS成为许多复杂问题求解的有力工具。

  3. 自我提升:MCTS通过不断模拟和自我对弈来提升样本的利用率,从而改善状态空间建模、策略提升和探索/利用效率等方面的性能。这种自我提升机制使得MCTS能够在面对新问题时逐渐适应并找到更好的解决方案。

  4. 动态适应:MCTS能够动态地调整搜索策略,专注于那些获得高评估回报的仿真结果,并基于这些结果不断向外扩展搜索树。这种动态适应性使得MCTS在复杂多变的环境中表现出色。

5.1.2. 缺点和缺陷

  1. 收敛速度慢:对于复杂的问题,MCTS往往需要大量的模拟才能达到可靠的估值,这可能导致收敛速度较慢。在某些情况下,为了在有限时间内做出决策,可能需要牺牲一定的解的质量。

  2. 计算资源消耗大:为了达到较高的决策质量,MCTS需要进行大量的模拟,这在处理复杂的游戏或问题时,会消耗大量的CPU时间和内存资源。这限制了MCTS在某些资源受限环境中的应用。

  3. 探索与利用的平衡:传统的MCTS算法需要在搜索树的每个节点上进行平衡探索(exploration)与利用(exploitation)的决策。当搜索空间庞大时,如何有效地维持这种平衡是一个挑战。如果探索过多,可能会导致收敛速度变慢;如果利用过多,则可能陷入局部最优解。

  4. 并行化困难:尽管MCTS算法在理论上可以并行化,但在实际操作中,如何有效地管理并行计算以减少性能损失仍是一个难题。特别是如何确保每个并行计算单元都能使用最新的统计数据来进行有效的探索和利用权衡。

5.2. 缺陷的解决方案

针对蒙特卡洛树搜索(Monte Carlo Tree Search, MCTS)的缺点和缺陷,以下是一些具体的解决方案:

5.2.1. 收敛速度慢

解决方案及实施步骤

  • 结合领域知识
    • 步骤一:收集和分析特定领域的先验知识,如游戏规则、专家经验等。
    • 步骤二:在MCTS的模拟过程中,将这些先验知识融入模拟策略中,例如通过调整模拟动作的选择概率来引导模拟过程。
    • 步骤三:评估结合领域知识后的模拟效果,根据反馈调整先验知识的应用方式。
  • 使用渐进展开
    • 步骤一:在搜索过程中,为每个节点维护统计信息,如访问次数、胜利次数等。
    • 步骤二:根据节点的统计信息,优先扩展那些具有更高潜力的节点,即访问次数较少但胜利次数较多的节点。
    • 步骤三:随着搜索的进行,逐步展开其他节点,确保搜索过程的全面性和有效性。
  • 动态调整模拟次数
    • 步骤一:为每个节点设置初始模拟次数,并根据搜索进度和结果进行调整。
    • 步骤二:在搜索初期,增加模拟次数以充分探索搜索空间;在搜索后期,减少模拟次数以加快收敛速度。
    • 步骤三:监控搜索过程的收敛情况,根据实时反馈动态调整模拟次数。

5.2.2. 计算资源消耗大

解决方案及实施步骤

  • 并行化计算
    • 步骤一:将MCTS算法分解为可并行化的子任务,如多个模拟实例可以同时运行。
    • 步骤二:利用现代计算机的多核处理器或分布式计算资源来并行执行这些子任务。
    • 步骤三:设计有效的数据同步和通信机制,确保并行计算单元之间的协作和数据一致性。
  • 剪枝技术
    • 步骤一:分析MCTS搜索过程中的无效搜索分支,识别出可以剪枝的节点。
    • 步骤二:开发适用于MCTS的剪枝策略,如基于节点统计信息的剪枝规则。
    • 步骤三:在搜索过程中应用剪枝策略,减少不必要的搜索分支,降低计算资源消耗。
  • 自适应终止条件
    • 步骤一:为每个节点设置自适应的模拟终止条件,如基于模拟次数、时间限制或节点统计信息的终止规则。
    • 步骤二:在模拟过程中监控这些终止条件,一旦满足条件则提前终止模拟过程。
    • 步骤三:评估自适应终止条件对搜索效果和计算资源消耗的影响,根据反馈调整终止条件。

5.2.3. 探索与利用的平衡

解决方案及实施步骤

  • 使用UCB公式变体
    • 步骤一:分析传统UCB公式的优缺点,并探索其他形式的UCB公式变体。
    • 步骤二:在MCTS算法中引入新的UCB公式变体,调整其中的参数以平衡探索和利用。
    • 步骤三:评估新公式变体对搜索效果的影响,根据反馈调整参数和公式形式。
  • 渐进式调整探索率
    • 步骤一:为MCTS算法设置初始探索率,该探索率决定了随机选择动作的概率。
    • 步骤二:在搜索过程中,根据搜索进度和结果渐进式地调整探索率。例如,随着搜索的深入,逐渐降低探索率以增加利用已有信息的比重。
    • 步骤三:监控搜索过程中的探索与利用情况,确保在保持多样性的同时提高搜索效率。
  • 结合其他搜索策略
    • 将MCTS与其他搜索策略(如贪婪搜索、局部搜索等)相结合,利用各自的优势来弥补不足。
    • 例如,可以在MCTS的模拟阶段使用局部搜索策略来快速找到当前状态下的局部最优解。

5.2.4. 并行化困难

解决方案及实施步骤

  • 设计有效的并行化策略
    • 步骤一:分析MCTS算法的并行化需求,识别出可并行化的部分。
    • 步骤二:设计合理的任务划分和数据同步策略,确保并行计算单元之间的有效协作。
    • 步骤三:实现并行化MCTS算法,并在实际应用中测试其性能和效果。
  • 利用现代并行计算框架
    • 步骤一:选择合适的并行计算框架(如MPI、OpenMP、CUDA等),根据具体需求和环境进行配置。
    • 步骤二:将MCTS算法转换为适合并行计算的形式,并利用并行计算框架提供的接口和工具进行实现。
    • 步骤三:优化并行算法的性能,包括减少通信开销、平衡负载、优化数据访问模式等。
  • 处理数据一致性问题
    • 在并行化MCTS过程中,需要特别注意数据一致性问题。
    • 通过引入适当的同步机制和锁策略来确保并行计算单元之间访问共享数据时的正确性。
    • 同时,还需要优化数据访问模式以减少缓存不一致性和内存带宽瓶颈等问题的影响。

6.  在游戏AI中的使用实例

6.1. 简单介绍

蒙特卡洛树搜索(Monte Carlo Tree Search,MCTS)在游戏AI中是一个强大的算法,尤其适用于那些具有庞大状态空间和/或难以评估状态价值的游戏。

一个典型的使用实例是将其应用于围棋、国际象棋或类似的策略棋类游戏。

下面,我将通过一个简化的围棋游戏AI的实例来展示蒙特卡洛树搜索的应用,并提供相应的Python代码实现。

6.2. 围棋AI中的蒙特卡洛树搜索

在围棋中,MCTS用于搜索可能的走子序列,并评估这些序列的胜负概率。算法的核心在于通过模拟(即随机走子至游戏结束)来评估节点价值,并利用这些模拟结果来指导搜索。

Python代码实现

以下是一个围棋MCTS实现的框架:

import random  
from math import sqrt, log  class GameState:  def __init__(self, board=None, turn=None, last_move=None):  self.board = board or self.create_empty_board()  self.turn = turn or 'X'  # 'X' 或 'O'  self.last_move = last_move  def create_empty_board(self):  # 创建一个空的围棋棋盘,例如 9x9  return [['.' for _ in range(9)] for _ in range(9)]  def is_terminal(self):  # 检查游戏是否结束(简化版本,实现基本的胜负判断)  # 这里只检查是否所有位置都已落子,实际游戏需要更复杂的判断  return all(cell != '.' for row in self.board for cell in row)  def generate_moves(self):  # 生成所有可能的走子  moves = []  for i in range(len(self.board)):  for j in range(len(self.board[0])):  if self.board[i][j] == '.':  moves.append((i, j))  return moves  def apply_move(self, move):  # 应用走子并返回新的游戏状态  new_board = [row[:] for row in self.board]  new_board[move[0]][move[1]] = self.turn  return GameState(new_board, 'O' if self.turn == 'X' else 'X', move)  def get_result(self):  # 返回游戏结果,简化版本只返回胜负  if self.is_terminal():  # 这里应该实现真正的胜负判断,简化版本只返回 None  return None  # 实际上应该根据棋盘状态判断胜负  return None  def __str__(self):  # 打印棋盘状态  return '\n'.join(''.join(row) for row in self.board)  class Node:  def __init__(self, game_state, parent=None):  self.game_state = game_state  self.parent = parent  self.children = []  self.visits = 0  self.wins = 0  def is_terminal(self):  return self.game_state.is_terminal()  def uct_value(self, parent_visits):  if self.visits == 0:  return float('inf')  win_rate = self.wins / self.visits  exploration_factor = sqrt(2)  # 探索与利用的权衡因子  return win_rate + exploration_factor * sqrt(log(parent_visits) / self.visits)  def expand(self):  moves = self.game_state.generate_moves()  for move in moves:  next_state = self.game_state.apply_move(move)  child_node = Node(next_state, self)  self.children.append(child_node)  def select_child(self):  return max(self.children, key=lambda child: child.uct_value(self.visits))  def simulate(node):  current_node = node  while not current_node.is_terminal():  if not current_node.children:  current_node.expand()  current_node = current_node.select_child()  # 在这个简化版本中,我们总是返回 None,因为胜负判断未实现  return None  def backpropagate(node, result):  while node:  node.visits += 1  if result is not None:  # 在这个简化版本中,我们从不更新胜利次数,因为胜负判断未实现  node.wins += result  # 实际上这里应该是 1 或 0,表示胜利或失败  node = node.parent  def mcts(root, num_iterations):  for _ in range(num_iterations):  node = root  while not node.is_terminal():  if not node.children:  node.expand()  node = node.select_child()  result = simulate(node)  # 在这个简化版本中,simulate 总是返回 None  backpropagate(node, result)  # 示例用法  
initial_state = GameState()  
root = Node(initial_state)  
num_iterations = 1000  
mcts(root, num_iterations)  
best_child = max(root.children, key=lambda child: child.visits)  
print("推荐走子:", best_child.game_state.last_move)  
print("棋盘状态:\n", best_child.game_state)

在这个实现中,GameState类提供了创建空棋盘、检查游戏是否结束、生成所有可能的走子、应用走子并返回新的游戏状态以及获取游戏结果的功能。

Node类和MCTS算法的实现与之前提供的示例相同。

在示例用法中,我们创建了一个初始的游戏状态,并进行了1000次MCTS迭代来选择最佳的走子。最后,我们打印了推荐的走子和当前的棋盘状态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3223825.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

一文实践强化学习训练游戏ai--doom枪战游戏实践

一文实践强化学习训练游戏ai–doom枪战游戏实践 上次文章写道下载doom的环境并尝试了简单的操作,这次让我们来进行对象化和训练、验证,如果你有基础,可以直接阅读本文,不然请你先阅读Doom基础知识,其中包含了下载、动作…

需求分析|泳道图 ProcessOn教学

文章目录 1.为什么使用泳道图2.具体例子一、如何绘制确定好泳道中枢的角色在中央基于事实来绘制过程不要纠结美观先画主干处理流程再画分支处理流程一个图表达不完,切分子流程过程数不超25 ,A4纸的幅面处理过程过程用动词短语最后美化并加上序号酌情加上…

vb.netcad二开自学笔记8:界面之任务窗格

使用net可以创建一个类似属性面板的自定义的任务窗格,从而实现应用程序更丰富的人机交互。 1、添加一个自定义控件 2、在前面创建的代码框架内增加一个命令函数ShowMyPalette Imports System.Windows.Media.Imaging Imports Autodesk.AutoCAD.ApplicationServices …

解码技术债:AI代码助手与智能体的革新之道

技术债 技术债可能来源于多种原因,比如时间压力、资源限制、技术选型不当等。它可以表现为代码中的临时性修补、未能彻底解决的设计问题、缺乏文档或测试覆盖等。虽然技术债可以帮助快速推进项目进度,但长期来看,它会增加软件维护的成本和风险…

PID控制与模糊PID控制的比较

一、PID控制器的设计 1.PID控制原理图: PID控制其结构框图如下图所示: 图1:PID控制器结构框图 2.PID控制器传递函数的一般表达式 PID控制器传递函数的一般表达形式为: 其中kp为比例增益;ki为积分增益;k…

html H5 dialog弹窗学习,实现弹窗显示内容 替代confirm、alert

html H5 dialog弹窗学习,实现弹窗内容 替代confirm 框架使用的mui,使用mui.confirm() 弹窗内容过多时,弹窗被撑的到屏幕外去了,使用H5 dialog 标签自定义一个固定大小的弹窗,内容过多时可下拉显示 效果展示 隐私政策内容很多,可以下拉显示 代码 myDialog.css dialog{p…

2024年信息系统项目管理师1批次上午客观题参考答案及解析(3)

51、探索各种选项,权衡包括时间与成本、质量与成本、风险与进度、进度与质量等多种因素,在整个过程中,舍弃无效或次优的替代方案,这种不确定性应对方法是()。 A.集合设计 B.坚韧性 C.多种结果…

odoo17 常见升级问题

通用问题 模型名变更 字段变更 方法名变更 方法参数变更 xml数据结构定义变化 xml的id变更 view视图变化,导致xpath路径出差 template结构变化,,导致xpath路径出差,或者id不存在 升16问题 前端owl的架构变化 升17问题 前端 标…

db期末复习自用[应试向 附习题]

第一章 数据库系统实现整体数据的结构化,主要特征之一,是db区别于文件系统的本质区别。 数据库系统三个阶段:人工、文件、数据库系统。 数据库管理系统的功能:数据库定义、操纵 、(保护、存储、维护)、数…

招投标信息采集系统:让您的企业始终站在行业前沿

一、为何招投标信息如此关键? 在经济全球化的大背景下,招投标活动日益频繁,成为企业获取项目、拓展市场的主流方式之一。招投标信息采集,作为企业战略决策的前置环节,其重要性不言而喻。它不仅关乎企业能否第一时间发…

Open3D 点对面的ICP算法配准(精配准)

目录 一、概述 1.1核心思想 1.2实现步骤 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2配准后点云 3.3计算数据 一、概述 基于点对面的ICP(Iterative Closest Point)配准算法是ICP的一种变体,它通过最小化源…

昇思MindSpore学习总结十二 —— ShuffleNet图像分类

当前案例不支持在GPU设备上静态图模式运行,其他模式运行皆支持。 1、ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型,和MobileNet, SqueezeNet等一样主要应用在移动端,所以模型的设计目标就是利用有限的计算资源来达…

数学建模中常用的数据处理方法

常用的数据处理方法 本文参考 B站西电数模协会的讲解视频 ,只作笔记提纲,想要详细学习具体内容请观看 up 的学习视频。一般来说国赛的 C 题一般数据量比较大。 这里介绍以下两种方法: 数据预处理方法 数据分析方法 数据预处理方法 1. 数据…

【电脑应用技巧】如何寻找电脑应用的安装包华为电脑、平板和手机资源交换

电脑的初学者可能会直接用【百度】搜索电脑应用程序的安装包,但是这样找到的电脑应用程序安装包经常会被加入木马或者强制捆绑一些不需要的应用装入电脑。 今天告诉大家一个得到干净电脑应用程序安装包的方法,就是用【联想的应用商店】。联想电脑我是一点…

alibabacloud学习笔记11

讲解什么是配置中心及使用前后的好处 讲解Nacos作为配置中心面板介绍 官方文档 Nacos config alibaba/spring-cloud-alibaba Wiki GitHub 加入依赖: 订单服务和视频服务也加上这个依赖。 讲解Nacos作为配置中心实战 订单服务添加配置。 我们注释掉之前的配置。 …

现代化3D Web轻量引擎HOOPS Communicator:基于ESM的代码库转型!

HOOPS Communicator自2024.2.0版本起,向基于ECMAScript Modules (ESM)的系统迁移的决策和技术细节。文章分析了这一转型对代码组织、封装、依赖管理、性能以及与现代JavaScript开发实践兼容性的积极影响,并讨论了IIFE和UMD的兼容性支持。 引言 随着Jav…

Dynamics365 UCI下的高级查找(不要留恋Classic了)

UCI界面已经用了多年了,在Classic下的的高级查找按钮(漏斗icon)已不见踪影 但因为使用习惯问题,还是有人会通过右上角高级设置,进入Classic界面找到漏斗Icon来使用高级查找 但新的UCI风格下已经没了高级查找的概念,取而代之的是基…

C++代码编程学习:基于对象的编程风格——习题4.5(Essential C++ 第四章)

C中基于对象的编程风格的学习,非常有难度,概念很抽象,操作起来也比较费脑子,这里主要把一些知识点和习题给过一遍! 一、前言 C中基于对象的编程风格的学习(Essential C 第四章)。 二、例题 -…

设计无缝体验:交互设计流程全解析

完整的产品交互设计流程是什么?完整的产品交互设计流程包括研究用户需求、指定信息架构、制作产品原型、进行用户测试和实时发布产品。交互设计就是从人与产品之间的关系入手,通过产品设计来满足大众的日常需求。随着网络技术的流行,产品交互…

快速将一个网址打包成一个exe可执行文件

一、电脑需要node环境 如果没有下面有安装教程: node.js安装及环境配置超详细教程【Windows系统安装包方式】 https://blog.csdn.net/weixin_44893902/article/details/121788104 我的版本是v16.13.1 二、安装nativefier 这是一个GitHub上的开源项目&#xff1a…