蒙特卡洛树搜索(MCTS)

概述

在“规划”语境中,“试探”意味着尝试那些改变模型的动作,而“开发”则意味着以当前模型的最优方式来执行动作。我们希望智能体通过试探发现环境的变化,但又不希望试探太多使得平均性能大大降低。可能并不存在既完美又实用的解决方案,但简单的启发式方法常常很有效。

  • 优先遍历算法在这里插入图片描述
  • 启发式搜索
    状态空间规划方法就是决策时规划,统称为启发式搜索。在启发式搜索中,对于遇到的每个状态,我们建立一个树结构,该结构包括了后面各种可能的延续,将近似价值函数应用于叶子节点,然后以根状态向当前状态回溯更新,回溯更新在当前状态的状态动作节点处停止,计算这些节点的更新值后,选择其中最好的值作为当前的动作,舍弃所有更新值。贪心策略和UCB动作选择方法与启发式搜索并没有什么不同。可以将启发式搜索视为单步贪心策略的某种扩展。启发式搜索中算力聚焦的最明显方式:可以以聚焦于当前状态及其可能的后继状态来改变更新的算力分配。极端情况下,我们可以使用启发式搜索的方法来构建搜索树,然后从下到上执行单步回溯更新。如果以这种方式对回溯更新进行排序并使用表格型表示,那么我们将得到与深度优先的启发式搜索完全相同的回溯更新方式。
  • 预演算法(rollout):
    rollout算法是一种基于蒙特卡洛控制的决策时规划算法,这里的蒙特卡洛控制应用于以当前环境状态为起点的采样模拟轨迹。rollout算法通过平均许多起始于每一个可能的动作并遵循给定的策略的模拟轨迹的回报来估计动作价值。当动作价值的估计被认为足够准确时,对应最高估计值的动作(或多个动作中的一个)会被执行,之后这个过程再从得到的后继状态继续进行。但是预演(rollout)算法的目标不是估计一个最优动作价值函数,或对于给定策略的完整的动作价值函数。相反,它们仅仅对每一个当前状态以及一个给定的被称为预演策略的策略做出动作价值的蒙特卡洛估计。预演算法只是即时地利用这些动作价值的估计值,之后就丢弃了。预演算法的目的是为了改进预演策略的性能,而不是找到最优的策略。基础预演策略越好,价值估计越准确,预演算法得到的策略就越可能更好。但是好的预演策略需要花更多的时间,效率不高的主要原因是1)轨迹之间没有聚焦,不知道哪个好坏2)轨迹利用不足,中间采样计算浪费,可以通过一些方法缓解,由于蒙特卡洛实验之间是相互独立的,因此可以在多个独立的处理器上并行的进行多次实验。另一个办法是在尚未完成时就截断模拟轨迹,利用预存的评估函数来更正截断的回报值。还有一种可行方法是监控蒙特卡洛模拟过程并对不太可能是最优的,或者最优值很接近的动作进行剪枝。

蒙特卡洛树搜索( Monte Carlo Tree Search)是一种预演策略,是一种在人工智能问题中做出最优决策的方法,结合了随机模拟的一般性和树搜索的准确性,解决了普通预演算法效率不高的问题。它的核心思想是 把资源放在更值得搜索的分枝上,即 算力集中在更有价值的地方。 MCTS 理论上可以被用在以 {状态state,行动 action} 对定义和用模拟进行预测输出结果的任何领域。
MCTS 执行一种非对称的树的适应搜索空间拓扑结构的增长。这个算法会更频繁地访问更加有趣的节点,并聚焦其搜索时间在更加相关的树的部分。 这使得 MCTS 更加适合那些有着更大的分支因子的博弈游戏,比如说 19X19 的围棋。这么大的组合空间会给标准的基于深度或者宽度的搜索方法带来问题,所以 MCTS 的适应性说明它(最终)可以找到那些更加优化的行动,并将搜索的工作聚焦在这些部分。此外MCTS 不要求任何关于给定的领域策略或者具体实践知识来做出合理的决策。这个算法可以在没有任何关于博弈游戏除基本规则外的知识的情况下进行有效工作。
MCTS 算法在某些甚至不是很大的博弈游戏中在可承受的时间内也不能够找到最好的行动方式。这基本上是由于组合步的空间的全部大小所致,关键节点并不能够访问足够多的次数来给出合理的估计。MCTS 搜索可能需要足够多的迭代才能收敛到一个很好的解上,这也是更加一般的难以优化的应用上的问题。例如,最佳的围棋程序可能需要百万次的交战和领域最佳和强化才能得到专家级的行动方案。

在这里插入图片描述

一次循环的四步骤

基本版的MCTS的每次循环包括下面四个步骤(流程如下图所示):
1、选择。从根节点开始,使用基于树边缘的动作价值的树策略遍历这棵树来挑选一个叶子节点
2、扩展。在某些循环中,针对选定的叶子节点找到采取非试探性动作可以达到的节点,将一个或多个这样的节点加为该叶子节点的子节点,以此来实现树的扩展。
3、模拟。从选定的节点,或其中一个它新增的子节点(如果存在)出发,根据预演策略选择动作进行整个轨迹模拟,动作首先由树策略选取,而到了树外则由预演策略选取。
4、回溯。模拟整个轨迹得到的回报值向上回传,对此次循环中,树策略所遍历的树边缘上的动作价值进行更新或初始化。预演策略在树外部访问到的状态和动作的任何值都不会 被保存下来。
在这里插入图片描述
在这里插入图片描述

选择

从根结点出发,选择到一个可扩展节点或模拟节点(目前可视的叶节点),在树向下遍历时的节点选择通过选择最大化某个量来实现,可以使用贪心策略或UCB1策略,如UCB策略,公式为:
在这里插入图片描述
其中V是节点估计的预期收益,n是此节点被访问的次数,而 N 则是其父节点已经被访问的总次数。c是可调整参数。
UCB 公式对已知收益的 exploitation 和鼓励接触那些相对未曾访问的节点的 exploration 进行平衡。收益估计基于随机模拟,所以节点必须被访问若干次来确保估计变得更加可信。MCTS 估计会在搜索的开始不大可靠,而最终会在给定充分的时间后收敛到更加可靠的估计上,在无限时间下能够达到最优估计。

扩展

如果当前叶子结点不是终止节点,那么就将其子节点加入树中。选择其中一个进行模拟,一般选第一个子节点。

模拟

从扩展节点开始,运行一个模拟的输出,直到博弈游戏结束。比如,从该扩展节点出发,模拟了十次,最终胜利九次,那么该扩展节点的得分就会比较高,反之则比较低。这里也给出一个模拟过程的伪代码:

def Rollout(S_i): 
  ## S_i:当前状态
	loop forever: 
    ## 无限循环
		if S_i a terimal state: 
      ## 如果当前状态是博弈的终止状态
      ## 则返回对 S_i 这个状态的价值,跳出循环
			return value(S_i)   
		
		## 如果还没到终止状态
    ## 随机选取当前状态下能够采取的一个动作
		A_i = random(available_action(S_i)) 
    ## 通过当前状态 S_i 与随机选取的动作 A_i 来计算出下一步的状态并赋值给 S_i
		S_i = transform(A_i, S_i)

回溯

将第三步模拟得到的V值,回加到当前路径的所有状态的V值上,并且路径上所有状态的被探索索值N/n都加1。

循环结束

当环境转移到一个新的状态树前,MCTS会在动作被选择前执行尽可能多次迭代,逐渐构建一个以根为当前状态的树,每一次迭代又包括四步:选择,扩展,模拟,回溯。直至发生如下情形时停止:

  • 到达固定循环次数
  • 用尽预定循环时间

实例

  • 根节点处理
    通常第一次进行探索,只有一个根节点,其探索次数N和价值V都为0。但是如何对根节点处理,我没有看到令人信服的说法,按照上述的流程图来说,首先根节点N=0,所以应该直接模拟,并更新N=1。T=?,之后才可以扩展,但是目前的讲解都是直接对根节点进行扩展。我读到这个博客,里面并不对root进行价值和探索次数的累计,所以可以直接扩展。综合这两种看法,本文初始化根节点的探索次数V=0;N=1
    在这里插入图片描述

  • 第一轮迭代

    • 选择
      由于只有根节点,所以选择根节点

    • 扩展
      由于根节点是叶子节点,所以进行扩展,假设有两个动作,可以到两个状态
      在这里插入图片描述

    • 模拟
      将新扩展的第一个节点设为当前节点,进行模拟,发现最后价值为20
      在这里插入图片描述

    • 回溯
      在这里插入图片描述

  • 第二轮迭代

    • 选择
      从根节点出发,计算UCB值,选择S2
    • 模拟
      发现S2的N值为零,直接进行模拟,发现最终值为10
      在这里插入图片描述
    • 回溯
      在这里插入图片描述
  • 第三轮迭代

    • 选择
      从S0出发,计算UCB值,S1的UVB值大,选择S1
    • 扩展
      由于S1的N值为1,进行扩展,假设有两个动作
      在这里插入图片描述
    • 模拟
      将新扩展的第一个节点设为当前节点,进行模拟,发现最后价值为5
      在这里插入图片描述
    • 回溯
      在这里插入图片描述
  • 一直循环,直至循环结束条件发生

ps:对于初始化的处理,我并不确定是否正确,只是个人理解

参考资料

https://www.bilibili.com/video/BV1s5411D7JT/?spm_id_from=333.337.search-card.all.click&vd_source=17e6ef0c70e053f15a0800baa45ae9d7
https://www.bilibili.com/video/BV1JD4y1Q7mV/?spm_id_from=333.337.search-card.all.click&vd_source=17e6ef0c70e053f15a0800baa45ae9d7
https://www.bilibili.com/video/BV1fY4y1876L/?spm_id_from=333.788.recommend_more_video.0&vd_source=17e6ef0c70e053f15a0800baa45ae9d7
https://blog.csdn.net/weixin_41960890/article/details/125915825
https://baijiahao.baidu.com/s?id=1588370171917873397&wfr=spider&for=pc
https://blog.csdn.net/wangmengmeng99/article/details/123710391
https://blog.csdn.net/caozixuan98724/article/details/103213795?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-1-103213795-blog-125915825.235v29pc_relevant_default_base3&spm=1001.2101.3001.4242.2&utm_relevant_index=4#1.%20%E8%92%99%E7%89%B9%E5%8D%A1%E6%B4%9B%E7%AE%97%E6%B3%95%E7%9A%84%E5%89%8D%E8%BA%AB%E4%BB%8A%E4%B8%96

基于蒙特卡洛树搜索 (Monte Carlo Tree Search, MCTS) 算法是一种用于决策问题的启发式搜索算法。MCTS 在不完全信息和高复杂度的问题中具有很好的效果。下面将介绍 MCTS 算法的 Java 版实现。 MCTS 算法的主要流程如下: 1. 创建一个根节点,表示当前的游戏状态。 2. 重复以下步骤,直到时间或迭代次数达到上限: a. 选择最有价值的子节点。从根节点开始,递归地选择子节点,直到找到一个未完全探索的节点。 b. 扩展选择的节点。根据游戏规则,生成该节点所有的合法子节点,并将其加入到树中。 c. 随机模拟选择节点的子节点。从扩展的子节点中随机选择一个,并进行模拟。直到游戏结束,得到一个模拟结果。 d. 更新选择节点和其祖先节点的价值。根据模拟结果,更新选择节点及其祖先节点的胜利次数和访问次数。 3. 选择最优的子节点作为下一步的决策。 在 MCTS 的实现中,主要涉及以下几个关键的类和方法: 1. Node 类:表示搜索树的节点,包含节点的游戏状态、访问次数和胜利次数等信息。 2. Selection 方法:通过选择最有价值的子节点来进行节点的选择。 3. Expansion 方法:扩展选中的节点,生成其所有合法的子节点。 4. Simulation 方法:随机模拟选中节点的子节点进行游戏,得到模拟结果。 5. Backpropagation 方法:根据模拟结果,更新节点和其祖先节点的访问次数和胜利次数。 6. BestChild 方法:选择最优的子节点作为下一步的决策。 通过以上关键步骤和方法的结合,可以实现 MCTS 算法的 Java 版本。使用该版本,可以在不完全信息和高复杂度问题上进行决策。例如,在棋类游戏中,MCTS 算法可以从当前局面搜索出最有希望的下一步,并进行决策。 总结而言,基于蒙特卡洛树搜索 (MCTS) 算法的 Java 版实现,通过节点的选择、扩展、模拟和回溯等关键步骤,可以用于解决复杂的决策问题。这种算法在游戏、人工智能等领域具有广泛的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值