AlphaGo Zero算法讲解

感情迁移 提交于 2020-02-27 14:45:05

   本篇博客讲解AlphaGo Zero算法。它对比于AlphaGo的改进在于它并不是学习人类棋谱。学习人类棋谱有一定的局限,第一就是人类下棋有局限,创新比较少;第二就是人类的棋谱少。AlphaGo Zero算法通过自我对弈完成棋力提高,可以克服以上两点。在学习AlphaGo Zero之前需要先学习MCTS搜索。

MCTS搜索

首先看下公式:
score =  wini+clnNini\text{score = }\ \frac{w_i}{n_i}+c\sqrt{\frac{\ln N_i}{n_i}}
   其中,wiw_iii节点的胜利次数,nin_iii节点的模拟次数,NiN_i是所有模拟次数,cc 是探索常数,理论值为2\sqrt{2}
比如对于下面的棋局,对于根节点来说,有3个选择,第一个选择7胜3负,第二个选择3胜5负,第三个选择0胜3负。
见下图,如Selection,白色为白子走,黑色为黑棋走;11/2111/21表示走此棋根据经验21局11胜。对于此节点来说,有3个选择,第一个选择7胜3负,第二个选择3胜5负,第三个选择0胜3负。
在这里插入图片描述
根据公式算出score,设C=10C=10
第一个节点:
score(7,10)=7/10+Clog(21)106.2score(7,10) =7/10 + C \cdot \sqrt{\frac{\log(21)}{10}} \approx 6.2
第二个节点:
score(3,8)=3/8+Clog(21)8score(3,8) = 3/8 + C \cdot \sqrt{\frac{\log(21)}{8}}
第三个节点:
score(0,3)=0/3+Clog(21)3score(0,3) = 0/3 + C \cdot \sqrt{\frac{\log(21)}{3}}
   然后根据节点score选择走那一步棋。
   C可根据经验调整,cc 越大就越偏向于广度搜索,cc 越小就越偏向于深度搜索。最后我们选择分数最高的动作节点。
   MCTS搜索一共有4步:
   第一步是选择(Selection):这一步会从根节点开始,每次都选一个“最值得搜索的子节点”,一般使用UCT选择分数最高的节点,直到来到一个“存在未扩展的子节点”的节点,如图中的 3/3 节点。之所以叫做“存在未扩展的子节点”,是因为这个局面存在未走过的后续着法,也就是MCTS中没有后续的动作可以参考了。这时我们进入第二步。

   第二步是扩展(Expansion),在这个搜索到的存在未扩展的子节点,加上一个0/0的子节点,表示没有历史记录参考。这时我们进入第三步。

   第三步是仿真(simulation),从上面这个没有试过的着法开始,用一个简单策略比如快速走子策略(Rollout policy)走到底,得到一个胜负结果。快速走子策略一般适合选择走子很快可能不是很精确的策略。因为如果这个策略走得慢,结果虽然会更准确,但由于耗时多了,在单位时间内的模拟次数就少了,所以不一定会棋力更强,有可能会更弱。这也是为什么我们一般只模拟一次,因为如果模拟多次,虽然更准确,但更慢。

  第四步是回溯(backpropagation), 将我们最后得到的胜负结果回溯加到MCTS树结构上。注意除了之前的MCTS树要回溯外,新加入的节点也要加上一次胜负历史记录,如上图最右边所示。
在此我们再举个例子(注意跟棋类无关):
  树的初始状态:
  T 表示总的 value, N 表示被访问的次数(visit count)。A表示动作(action).
在这里插入图片描述
  第一次迭代(iteration):
  从状态S0S_0开始,要在下面两个动作中进行选择(假设只有两个动作可选),选择的标准就是score值。显然可算得:
score(s2)=score(s1)=score(s_2)=score(s_1)=\infty
  这种情况下,我们就按顺序取第一个,即A1A_1 。从而,达到状态S1S_1 。按照步骤1,2的流程图,我们现在需要判断目前的结点S1S_1 (current node)是不是叶节点,这里叶节点是指其没有被展开(expansion)过。显然,此结点没有被展开过,所以是叶节点。接下来,按照流程图,需要判断结点S1S_1被访问的系数是否为0。是0,所以要进行随机采取动作,直到停止点(围棋中的对局结束),得到一个最终的value。
假设最终值为20.
在这里插入图片描述
  接下来,进行步骤4 Backpropagation,即利用Rollout最终得到的value来更新路径上每个结点的T,N值。
在这里插入图片描述
之后把Rollout的结果删除:
在这里插入图片描述
  MCTS的想法就是要从S0S_0出发不断的进行迭代,不断更新结点值,直到达到一定的迭代次数或者时间。
第二次迭代:
  我们从S0S_0出发进行第二次迭代(iteration):
  首先,计算下面两个结点S1,S2S_1,S_2,S2S_2scorescore值:
score(s2)=,score(s1)=20score(s_2)=\infty,score(s_1)=20
  所以,选动作A2A_2,从而达到状态S2S_2 。同上,现在要判断结点S2S_2是否是叶结点。是,所以继续判断其被访问的次数。是0,所以随机选择, 假设最终值为10。
在这里插入图片描述
之后进行Backpropogation:
在这里插入图片描述
  第三次迭代:
  首先,计算score值:
score(S1)21.67score(S2)11.67score(S1)≈21.67 score(S2)≈11.67
执行动作A1A_1,进入状态S1S_1​。
是否是叶节点? 是。
被访问次数是否为0?否。
按照流程图所示,现在进入Node expansion步骤。同样假设只有两个动作可选。
在这里插入图片描述
  选择S3进行随机选择,假设最终值为0。
在这里插入图片描述
更新路径上每个结点的值,之后删除线上的值:
在这里插入图片描述
第四次迭代:
首先,计算score值:
score(S1)=10+2log3211.48score(S_1)=10+2\sqrt{\frac{log3}{2}}≈11.48
score(S2)12.10score(S_2)≈12.10
  选择A2A_2,进入状态S2S_2, 接下来和第三次迭代一样的步骤:
在这里插入图片描述
更新路径上的结点:
在这里插入图片描述
  假设我们设定最大迭代次数为4,则我们的迭代完毕。这时,利用得到的树来决定在S0S_0处应该选择哪个动作。根据score值,显然我们要选择动作A2A_2

AlphaGo Zero模型基础

  AlphaGo Zero的行棋主要是由MCTS指导完成的,但是在MCTS搜索的过程中,由于有一些不在树中的状态需要仿真,做局面评估,因此需要一个简单的策略来帮助MCTS评估改进策略。
  AlphaGo Zero训练过程主要分为三个阶段:自我对战学习阶段,训练神经网络阶段和评估网络阶段。
  自我对战学习阶段主要是AlphaGo Zero自我对弈,产生大量棋局样本的过程,由于AlphaGo Zero并不使用围棋大师的棋局来学习,因此需要自我对弈得到训练数据用于后续神经网络的训练。在自我对战学习阶段,每一步的落子是由MCTS搜索来完成的。在MCTS搜索的过程中,遇到不在树中的状态,则使用神经网络的结果来更新MCTS树结构上保存的内容。在每一次迭代过程中,在每个棋局当前状态s下,每一次移动使用1600次MCTS搜索模拟。最终MCTS给出最优的落子策略π,这个策略π和神经网络的输出p是不一样的。当每一局对战结束后,我们可以得到最终的胜负奖励z,1或者-1. 这样我们可以得到非常多的样本(s,π,z),这些数据可以训练神经网络阶段。
  在训练神经网络阶段,我们使用自我对战学习阶段得到的样本集合(s,π,z),训练我们神经网络的模型参数。训练的目的是对于每个输入s, 神经网络输出的p,v和我们训练样本中的π,z差距尽可能的少。这个损失函数L其实是很简单的:
L=(zv)2πTlog(p)+cθ2L=(z-v)^{2}-\pi^{T}log(p)+c||\theta||^{2}
  损失函数由三部分组成,第一部分是均方误差损失函数,用于评估神经网络预测的胜负结果和真实结果之间的差异。第二部分是交叉熵损失函数,用于评估神经网络的输出策略和我们MCTS输出的策略的差异。第三部分是L2正则化项。
  通过训练神经网络,我们可以优化神经网络的参数θ,用于后续指导我们的MCTS搜索过程。
  首先我们看看AlphaGo Zero的输入,当前的棋局状态。由于围棋是19x19的361个点组成的棋局,每个点的状态有二种:如果当前是黑方行棋,则当前有黑棋的点取值1,有白棋或者没有棋子的位置取值为0,反过来,如果当前是白方行棋,则当前有白棋的点取值1,有黑棋或者没有棋子的位置取值为0。同时,为了提供更多的信息,输入的棋局状态不光只有当前的棋局状态,包括了黑棋白棋各自前8步对应的棋局状态。除了这16个棋局状态,还有一个单独的棋局状态用于标识当前行棋方,如果是当前黑棋行棋,则棋局状态上标全1,白棋则棋局状态上标全0。如下图所示:
在这里插入图片描述
  最终神经网络的输入是一个19x19x17的张量。里面包含黑棋和白棋的最近8步行棋状态和当前行棋方的信息。
  接着我们看看神经网络的输出,神经网络的输出包括策略部分和价值部分。对于策略部分,它预测当前各个行棋点落子的概率。由于围棋有361个落子点,加上还可以Pass一手,因此一共有362个策略端概率输出。对于价值端,输出就简单了,就是当前局面胜负的评估值,在[-1,1]之间。

  看完了神经网络的输入和输出,我们再看看神经网络的结构,主要是用CNN组成的深度残差网络。如下图所示:
在这里插入图片描述
  我们已经介绍了MCTS的基本原理,和4个主要的搜索阶段:选择,扩展,仿真和回溯。和上一篇的内容相比,这里MCTS的不同主要体现在树结构上保存的信息不同,进而UCT的计算公式也稍有不同。最后MCTS搜索完毕后,AlphaGo Zero也有自己选择真正落子点的策略。
  在上一篇里,我们的MCTS上保存的数据很简单,就是下的总盘数和赢的总盘数。在AlphaGo Zero这里,我们保存的信息会多一些。主要包括下面的4部分:

N(s,a)N(s,a):记录边的访问次数
    W(s,a)W(s,a): 合计行动价值
    Q(s,a)Q(s,a) :平均行动价值
    P(s,a)P(s,a) :选择该条边的先验概率

  其中ss为当前棋局状态,aa为某一落子选择对应的树分支。

  有了MCTS上的数据结构,我们看看AlphaGo Zero的MCTS搜索的4个阶段流程:

  首先是选择,在MCTS内部,出现过的局面,我们会使用score选择子分支。但是具体的公式稍有不同,如下:
U(s,a)=cpuctP(s,a)bN(s,b)1+N(s,a)U(s,a) = c_{puct}P(s,a)\frac{\sqrt{\sum_{b}{N(s,b)}}}{1+N(s,a)}
at=argmaxa(Q(st,a)+U(st,a))a_t = \underset{a}{\arg\max}(Q(s_t, a) + U(s_t, a))
  使用ata_t选择最大的子分支作为搜索分支,一直走到棋局结束,或者走到了没有到终局MCTS的叶子节点。
  如果到了没有到终局的MCTS叶子节点,那么我们就需要进入MCTS的第二步,扩展阶段,以及后续的第三步仿真阶段。我们这里一起讲。对于叶子节点状态s,会利用神经网络对叶子节点做预测,得到当前叶子节点的各个可能的子节点位置sL落子的概率p和对应的价值v,对于这些可能的新节点我们在MCTS中创建出来。
  这个过程如下图所示:
在这里插入图片描述
  这样扩展后,之前的叶子节点s,现在就是内部节点了。做完了扩展和仿真后,我们需要进行回溯,将新叶子节点分支的信息回溯累加到祖先节点分支上去。这个回溯的逻辑也是很简单的,从每个叶子节点L依次向根节点回溯,并依次更新上层分支数据结构如下:
  N(st,at)=N(st,at)+1N(s_t,a_t) = N(s_t,a_t)+1
  W(st,at)=W(st,at)+vW(s_t,a_t) = W(s_t,a_t)+v
  Q(st,at)=W(st,at)N(st,at)Q(s_t,a_t) = \frac{W(s_t,a_t)}{N(s_t,a_t)}
  这个MCTS搜索过程在一次真正行棋前,一般会进行约1600次搜索,每次搜索都会进行上述4个阶段。
这上千次MCTS搜索完毕后,AlphaGo Zero就可以在MCTS的根节点s基于以下公式选择行棋的MCTS分支了:
π(as)=N(s,a)1/τbN(s,b)1/τ\pi(a|s)=\frac{N(s,a)^{1/\tau}}{\sum_{b}^{}{N(s,b)^{1/\tau}}}
  其中,ττ为温度参数,控制探索的程度, ττ 越大,不同走法间差异变小,探索比例增大,反之,则更多选择当前最优操作。每一次完整的自我对弈的前30步,参数 τ=1τ=1 ,这是早期鼓励探索的设置。游戏剩下的步数,该参数将逐渐降低至0。如果是比赛,则直接为0。
参考文献:
https://www.cnblogs.com/pinard/p/10609228.html
https://blog.csdn.net/ljyt2/article/details/78332802

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!