过程包括以下四步:

选择 Selection:从根节点 R 开始,递归选择最优的子节点(后面会解释)直到达到叶子节点 L。
扩展 Expansion:如果 L 不是一个终止节点(也就是,不会导致博弈游戏终止)那么就创建一个或者更多的字子节点,选择其中一个 C。
模拟 Simulation:从 C 开始运行一个模拟的输出,直到博弈游戏结束。
反向传播 Backpropagation:用模拟的结果输出更新当前行动序列。

代码实现:

import sys
import math
import random
import numpy as npAVAILABLE_CHOICES = [1, -1, 2, -2]
AVAILABLE_CHOICE_NUMBER = len(AVAILABLE_CHOICES)
MAX_ROUND_NUMBER = 10class Node(object):def __init__(self):self.parent = Noneself.children=[]self.visit_times=0self.quality_value = 0.0self.state=Nonedef set_state(self,state):self.state = statedef get_state(self):return self.statedef set_parent(self,parent):self.parent = parentdef get_parent(self):return self.parentdef set_children(self,children):self.children = childrendef get_children(self):return self.childrendef get_visit_times(self):return self.visit_timesdef set_visit_times(self, times):self.visit_times = timesdef visit_times_add_one(self):self.visit_times +=1def get_quality_value(self):return self.quality_valuedef set_quality_value(self, value):self.quality_value = valuedef quality_value_add_n(self,n):self.quality_value +=ndef is_all_expand(self):if len(self.children)==AVAILABLE_CHOICE_NUMBERreturn Trueelse:return Falsedef add_child(self,sub_node):sub_node.set_parent(self)self.children.append(sub_node)def __repr__(self):return "Node:{},Q/N:{}/{},state:{}".format(hash(self),self.quality_value,self,visit_times,self.state)class State(object):#某游戏的状态,例如模拟一个数相加等于1的游戏def __init__(self):self.current_value=0.0#当前数self.current_round_index=0#第几轮self.cumulative_choices = []#选择过程记录def is_terminal(self):#判断游戏是否结束if self.current_round_index = MAX_ROUND_NUMBER-1return Trueelse:return Falsedef compute_reward(self):#当前得分,越接近1分值越高return -abs(1-self.current_value)def set_current_value(self,value):self.current_value=valuedef set_current_round_index(self,round):self.current_round_index=rounddef set_cumulative_choices(self,choices):self.cumulative_choices=choicesdef get_next_state_with_random_choice(self):#得到下个状态random_choice=random.choice([choice for choice in AVAILABLE_CHOICES])next_state=State()next_state.set_current_value(self.current_value+random_choice)next_state.set_current_round_index(self.current_round_index+1)next_state.set_cumulative_choices(self.cumulative_choices+[random_choice])return next_state
def monte_carlo_tree_search(node):#蒙特卡洛树搜索总函数computation_budget=1000for i in range(computation_budget):expend_node = tree_policy(node)reward = default_policy(expand_node)backup(expand_node,reward)best_next_node = best_child(node,False)return best_next_node
def best_chile(node,is_exploration):#若子节点都扩展完了,求UCB值最大的子节点best_score=-sys.maxizebest_sub_node = Nonefor sub_node in node.get_children():if is_exploration:C=1/math.sqrt(2.0)else:C=0.0left=sub_node.get_quality_value()/sub_node.get_visit_times()right=2.0*math.log(node.get_visit_times())/sub_node.get_visit_times()score=left+C*math.sqrt(right)if score>best_score:best_sub_node = sub_nodereturn best_sub_node
def expand(node):#得到未扩展的子节点tried_sub_node_states= [sub_node.get_state() for sub_node in node.get_children()]new_state = node.get_state().get_next_state_with_random_choice()while new_state in tried_sub_node_states:new_state=node.get_state().get_next_state_with_random_choice()sub_node=Node()sub_node.set_state(new_state)node.add_child(sub_node)return sub_node
def tree_policy(node):#选择子节点的策略while node.get_state().is_terminal()==False:if node.is_all_expand():node=best_child(node,True)else:sub_node = expand(node)return sub_nodereturn node
def defaut_policy(node):current_state = node.get_state()while current_state.is_terminal==False:current_state = current_state.get_next_state_with_random_choice()final_state_reward=current_state.compute_reward()return final_state_reward
def backup(node,reward):while node != None:node.visit_times_add_one()node.quality_value_add_n(reward)node = node.parent

提升
很多种 MCTS 强化的技术已经出现了。这些基本上可以归纳为领域知识或者领域独立两大类。

领域知识
特定博弈游戏的领域知识可以用在树上来过滤掉不合理的行动或者在模拟过程中产生重要的对局(更接近人类对手的表现)。这意味着交战结果将会更加的现实而不是随机的模拟,所以节点只需要少量的迭代就能给出一个现实的收益值。

领域知识可以产生巨大的性能提升,但在速度和一般性上也会有一定的损失。

领域独立
领域独立强化能够应用到所有的问题领域中。这些一般用在树种(如 AMAF),还有一些用在模拟(如 在交战时倾向于胜利的行动)。领域独立强化并不和特定的领域绑定,具有一般性,这也是当前研究的重心所在。

AlphaGo的基本原理
围棋是一类完全信息的博弈游戏。然而,其庞大的搜索空间,以及局面棋势的复杂度,使得传统的剪枝搜索算法在围棋面前都望而却步。在AlphaGo出现之前,MCTS算法算是一类比较有效的算法。它通过重复性地模拟两个players的对弈结果,给出对局面s的一个估值v(s)(Monte Carlo rollouts);并选择估值最高的子节点作为当前的策略(policy)。基于MCTS的围棋博弈程序已经达到了业余爱好者的水平。

然而,传统的MCTS算法的局限性在于,它的估值函数或是策略函数都是一些局面特征的浅层组合,往往很难对一个棋局有一个较为精准的判断。为此,AlphaGo的作者训练了两个卷积神经网络来帮助MCTS算法制定策略:用于评估局面的value network,和用于决策的policy network。(后面会看到,这两个网络的主要区别是在输出层:前者是一个标量;后者则对应着棋盘上的一个概率分布。)

首先,Huang等人利用人类之间的博弈数据训练了两个有监督学习的policy network:pσ(SL policy network)和pπ(fast rollout policy network)。后者用于在MCTS的rollouts中快速地选择策略。接下来,他们在pσ的基础上通过自我对弈训练了一个强化学习版本的policy network:pρ(RL policy network)。与用于预测人类行为的pσ不同,pρ的训练目标被设定为最大化博弈收益(即赢棋)所对应的策略。最后,在自我对弈生成的数据集上,Huang等人又训练了一个value network:vθ,用于对当前棋局的赢家做一个快速的预估。

pipeline of neural networks

因此,用一句话简单概括一下AlphaGo的基本原理:在MCTS的框架下引入两个卷积神经网络policy network和value network以改进纯随机的Monte Carlo模拟,并借助supervised learning和reinforcement learning训练这两个网络。

接下来将对AlphaGo的细节进行展开讨论。

有监督学习的Policy Networks
Huang等人首先训练了一个有监督的Policy Network用来模拟人类专家的走子。SL policy network是一个卷积神经网络;其输出层是一个Softmax分类器,用来计算在给定的棋面状态s下每一个位置的落子概率pσ(a|s)。对一个棋面状态s的描述如下:
input features for policy networks
(这里的Features对应着卷积神经网络里的Channels。)

经过人类高手三千万步围棋走法的训练后,SL policy network模拟人类落子的准确率已经达到了57%;相应地,网络的棋力也得到大大的提升。但是,如果直接用这个网络与人类高手,甚至是MCTS的博弈程序进行对弈,依然是输面居多。而且,这个网络的走子太慢了!平均每步3ms的响应时间,使得这个网络很难被直接用于MCTS的rollout中进行策略的随机。因此,Huang等人通过提取一些pattern features又训练了一个更快速(响应时间达到了2μs)但准确率有所降低(24.2%)的rollout policy network: pπ。

强化学习的Policy Networks
接下来,为了进一步提高policy network的对弈能力,Huang等人又采用一种policy gradient reinforcement learning的技术,训练了一个RL policy network:pρ。这个网络的结构与SL policy network的网络结构相同,依然是一个输出为给定状态下落子概率的卷积神经网络。网络的参数被初始化为pσ的参数;接下来,通过不断地自我对弈(与历史版本),网络的权重向着收益最大化的方向进化。此时,网络的学习目标不再是模拟人类的走法,而是更为终极的目标:赢棋。

具体来说,我们定义了一个reward function r(st):对于非终止的时间步t<T,总有r(st)=0。每一步的收益z(t)被定义为±r(sT):即对当前玩家而言对弈的最终结果(+1代表赢棋;−1代表输棋)。网络的权重通过随机梯度上升法进行调整:
Δρ∝∂logpρ(at|st)∂ρzt

通过这种方式训练出来的RL policy network,在与SL policy network对弈时已有80%的赢面。即便是与依赖Monte Carlo搜索的围棋博弈程序相比,不依赖任何搜索的RL policy network,也已经达到了85%的赢面。

强化学习的Value Networks
最后,Huang等人又开始寻求一个能快速预估棋面价值(棋势)的Value Network。一个棋面的价值函数vp(s),被定义为在给定的一组对弈策略p的情况下,从状态s出发,最终的期望收益(也即赢棋的概率):
vp(s)=E[zt|st=s,at…T∈p]

显然,理想情况下,我们想知道的是在双方均采用最优策略的条件下得到的最优期望收益v∗(s)。然而,我们并不知道什么才是最优的策略。因此,在实际应用中,Huang等人采用了目前最强的策略函数pρ(RL policy network )来计算一个棋面的价值vpρ(s),并训练了一个value network vθ(s)来拟合这个价值函数:vθ(s)≈vpρ(s)≈v∗(s)。

Value Network的网络结构与前面的Policy Network类似,也是一个卷积神经网络,只是输出层变成了一个单神经元的标量。我们可以通过构造一组(s,z)的训练数据,并用随机梯度下降法最小化网络的输出vθ(s)与目标收益z的均方差,来调整网络的参数:
Δθ∝∂vθ(s)∂θ(z−vθ(s))

在构造训练数据时有一些技巧。如果我们从人类对弈的完整棋局中抽取足够数量的训练数据,很容易出现过拟合的问题。这是因为,在同一轮棋局中的两个棋面的相关性很强(往往只相差几个棋子);此时,网络很容易记住这些棋面的最终结果,而对新棋面的泛化能力很弱。为了解决这个问题,Huang等人再次祭出强化学习的大杀器:通过RL policy network的自我对弈,产生了三千万个从不同棋局中提取出来的棋面-收益组合的训练数据。基于这份数据训练出来的Value Network,在对人类对弈结果的预测中,已经远远超过了使用fast rollout policy network的MCTS的准确率;即便是与使用RL policy network的MCTS相比,也已是不遑多让(而Value Network的计算效率更高)。

accuracy of value network

整合
到这里,我们手头上已经有一个牛逼但是巨慢的SL policy network;有一个不那么牛逼但是很快的fast policy network;有一个一心只想着如何赢棋的RL policy network;还有一个能一眼洞穿棋局的value network。那么,将这些networks放在一起互相补足,会得到什么呢?

答案就是AlphaGo。而把这些networks整合在一起的框架,就是MCTS算法。

与经典的MCTS算法类似,APV-MCTS(asynchronous policy and value MCTS)的每一轮模拟也包含四个步骤:

Selection:APV-MCTS搜索树中的每条连边(s,a)都包含三个状态:决策收益Q(s,a),访问次数N(s,a),和一个先验概率P(s,a)。这三个状态共同决定了对一个节点下行为的选择:
at=argmaxa(Q(st,a)+u(st,a))

其中,u(s,a)∝P(s,a)1+N(s,a)
Expansion:步骤1中的selection终止于叶子节点。此时,要对叶子节点进行扩展。这里采用SL policy network pσ计算出叶子节点上每个行为的概率,并作为先验概率P(sL,a)存储下来。
Evaluation。使用value network vθ(s)和fast rollout policy network pπ模拟得到的博弈结果对当前访问到的叶子节点进行估值:
V(sL)=(1−λ)vθ(sL)+λzL
Backup。更新这一轮模拟中所有访问到的路径的状态:
N(s,a)=∑i=1n1(s,a,i)

Q(s,a)=1N(s,a)∑i=1n1(s,a,i)V(siL)

其中,n是模拟的总次数;1(s,a,i)标示第i轮模拟中是否经过边(s,a);siL是第i轮模拟中访问到的叶子节点。
下图展示了一轮模拟的动态过程。

MCTS with policy networks and value networks

模拟结束后,算法会选择访问次数N(s,a)最大的策略a作为当前的走子策略。

值得注意的是,在整个模拟的过程中,我们见到了SL policy network(用于Expansion中先验概率的计算);见到了fast rollout policy network(用于Evaluation中的快速走子);见到了value network(用于Evaluation中对棋势的预估)。等等,RL policy network去哪了?为什么不用RL policy network替代SL policy network?明明RL policy network有着更强的棋力啊(85%的赢面)?

这是因为,与RL policy network相比,由人类专家走法训练出来的SL policy network在策略上的多样性更强;因此更适用于MCTS中的搜索。但是,用RL policy network的自我对弈结果训练出来的value network的泛化能力就要比SL policy network训练出来的value network要强得多了。

【python】蒙特卡洛树搜索(MCTS)简单实现相关推荐

  1. 面向初学者的蒙特卡洛树搜索MCTS详解及其实现

    目录 0. 序言 1. 蒙特卡洛算法的前身今世 2. 蒙特卡洛搜索算法的原理 2.1 Exploration and Exploitation(探索与利用) 2.2 Upper Confidence ...

  2. 强化学习(八):Dyna架构与蒙特卡洛树搜索MCTS

    强化学习(八):Dyna架构与蒙特卡洛树搜索MCTS   在基于表格型强化学习方法中,比较常见的方法有动态规划法.蒙特卡洛法,时序差分法,多步引导法等.其中动态规划法是一种基于模型的方法(Model- ...

  3. 蒙特卡洛树搜索 MCTS

    原文地址 http://mcts.ai/about/index.html 什么是 MCTS? 全称 Monte Carlo Tree Search,是一种人工智能问题中做出最优决策的方法,一般是在组合 ...

  4. 蒙特卡洛搜索树python_python实现的基于蒙特卡洛树搜索(MCTS)与UCT RAVE的五子棋游戏...

    更新 2017.2.23有更新,见文末. MCTS与UCT 下面的内容引用自徐心和与徐长明的论文<计算机博弈原理与方法学概述>: 蒙特卡洛模拟对局就是从某一棋局出发,随机走棋.有人形象地比 ...

  5. python实现的基于蒙特卡洛树搜索(MCTS)与UCT RAVE的五子棋游戏

     转自: http://www.cnblogs.com/xmwd/p/python_game_based_on_MCTS_and_UCT_RAVE.html 更新 2017.2.23有更新,见文末 ...

  6. 蒙特卡洛树搜索 MCTS 入门

    引言   你如果是第一次听到蒙特卡洛,可能会认为这是一个人名.那么你就大错特错,蒙特卡洛不是一个人名,而是一个地方,还一个赌场名!!!但是这不是我们的重点.   我们今天的主题就是入门蒙特卡洛树搜索, ...

  7. 蒙特卡洛树搜索(MCTS)的实例代码

    另一篇博客对代码的讲解 原理: 在当前树节点(设为A)状态下,如果所有子节点都展开了,则按UCT算法选择最优节点作为当前节点,循环下去,直到该节点有未展开的子节点,则从未展开的子节点里瞎选一个并展开它 ...

  8. 蒙特卡洛树搜索(MCTS)实现简易五子棋AI

    蒙特卡洛树搜索算法可以通过自我对弈模拟得到不同状态分支中获胜的概率,从而获得最优的策略.代码部分可以分为Node类和State类.Node类通过关联父节点和子节点实现树结构,同时保存每个节点的属性:S ...

  9. 一种简单的蒙特卡洛树搜索并行化方法

    监控未观察样本: 一种简单的蒙特卡洛树搜索并行化方法 Watch the Unobserved: a Sample Approach to Parallelizing Monte Carlo Tree ...

  10. 蒙特卡洛树搜索(MCTS)详解

    蒙特卡洛树搜索(MCTS)详解 蒙特卡洛树搜索是一种经典的树搜索算法,名镇一时的 AlphaGo 的技术背景就是结合蒙特卡洛树搜索和深度策略价值网络,因此击败了当时的围棋世界冠军.它对于求解这种大规模 ...

最新文章

  1. kubectl技巧之通过go-template截取属性
  2. 冬至日,诚邀你来杭州网易,一起吃着饺子畅聊「B2B增长」
  3. 国外学校css profile,CSS Print Profile
  4. opencms的主工作区文件研究
  5. 数学特级老师:数学除了做习题,这份140G的资料一定要收藏!
  6. 【设计模式】7、桥接模式
  7. android 抓log暗码,「有用功」强大的安卓暗码命令 你都知道吗?
  8. GNS3全面详解系列-GNS3的前世今生
  9. [导入]Linq学习笔记(2.2)——深入DLinq查询
  10. c语言中0xa0f对应的十进制,全国计算机二级C基础知识重点讲解
  11. AD9361_AD9371_AD9363_AD9364 对比
  12. [c++]平均成绩、从尾到头打印链表、整数从大到小排序、二分法查找、斐波那契数列
  13. python powerbi知乎_数据分析-PowerBI
  14. “select count (1)”是什么意思?
  15. 内存类型:UDIMM、RDIMM、LRDIMM
  16. Linux高可用之heartbeat
  17. Opencv中的convertTo
  18. 最大后验估计(MAP)
  19. Struts2的介绍~~(跟着佟刚老师视频)
  20. Penny Pinching在云中:Azure网站何时有意义?

热门文章

  1. MySQL从MyISAM引擎转换到InnoDB引擎需要注意的地方
  2. 微信公众号开发(5)-调用jssdk获取地理位置经纬度及百度api获得城市
  3. 学习一下秒杀系统的设计,以及需要考虑的问题
  4. Mac写作软件哪款好?妙笔WonderPen for Mac非常值得一用!
  5. Ubuntu系统,安装完成却黑屏???不要慌!只需这个命令,一下搞定!
  6. 港中文Adobe提出:开放式实体分割 Open-World Entity Segmentation
  7. 宠物之家 验证码部分分享
  8. 微信小程序摇一摇功能实现
  9. 【转】人生如梦游戏间,RPG游戏开源开发讲座(JAVA篇)[2]——踏破红尘
  10. 熊猫酒仙服务器位置,《神仙道》熊猫酒仙个人分析