1. 概述
简单来讲,AlphaGo Zero 的训练能够分为三个同时进行的阶段:git
- 自我对战
- 再训练网络
- 评估网络
在自我对战阶段, AlphaGo Zero 建立一个训练集合,自我完成对战 25000 次。棋局每变更一次,博弈、搜索可能性和胜出者的信息将被存储。github
训练网络阶段,是神经网络权值获得优化的过程。在一次完整的训练循环中, AlphaGo Zero 将从 50 万局博弈中选取 2048 个移动位置做为样品,并对这些位置的神经网络进行训练。以后,经过损失函数,来对比神经网络预测与搜索可能性和实际胜出方的信息。每完成一千次这样的训练循环,就对神经网络进行一次评估。算法
在评估网络阶段,测试新的神经网络是否获得优化。在这个过程当中,博弈双方都经过各自的神经网络评估叶节点,并使用蒙特卡洛树搜索进行下一步棋路的选择。网络


a 部分是利用初始化的神经网络和MCTS进行自博弈,收集到对弈的数据以及胜负关系数据结构
程序自我对弈完成一个棋局产生一个状态序列 \(s_1,…,s_T\) ,在 \(T\) 时刻棋局结束,产生了获胜方,用 \(z\) 表示。在其中的每个时刻 \(T\) ,棋局状态用 \( s_t\) 表示,会在神经网络 \( f_{\theta} \) 的引导下执行一次 MCTS 搜索 \({\alpha}_{\theta}\) ,经过 MCTS 搜索计算获得的几率 \(a_t \sim {\pi}_t\) 肯定如何行为(在何处落子)架构
b 部分是利用收集到的数据训练当前棋盘的价值和每个走子的几率 (神经网络的训练过程) app
神经网络的输入是某时刻 \(t\) 的棋局状态 \(s_t\) 外加一些历史和额外信息,输出是一个行为几率向量 \( p_t\) 和一个标量 \(v_t\) ide
Alpha Zero 算法主体思想就是在策略迭代过程当中重复使用上述两个工具:神经网络的参数得以更新,这样可使得神经网络的输出 \((p, v) = f_{\theta}(s) \) :移动几率和获胜奖励更接近与通过改善了的搜索获得的几率以及经过自我对弈获得的棋局结果,后者用 \( (\pi, z) \) 表示。获得的新参数能够在下一次自我对弈的迭代过程当中让搜索变得更增强大。函数
- \(p\) (move probabilities) 在当前棋局状态下采起每种可能落子方式的几率
- \(v\) 当前棋局状态 \(s\) 下棋手最终获胜仍是落败(分别用 \(1\) 和 \(-1\) 表示)
- \(\pi\) 表示通过神经网络改善了的蒙特卡洛树搜索输出的选择每个 move 的几率
- \(z\) 表示经过自我对弈获得的棋局结果
The vector of move probabilities \(p\) represents the probability of selecting each move a (including pass), \(p_a = Pr(a|s)\) . The value \(v\) is a scalar evaluation, estimating the probability of the current player winning from position \(s\) . 工具
The MCTS search outputs probabilities π of playing each move. These search probabilities usually select much stronger moves than the raw move probabilities p of the neural network \(f_θ(s)\) ; MCTS may therefore be viewed as a powerful policy improvement operator. Selfplay with search—using the improved MCTSbased policy to select each move, then using the game winner \(z\) as a sample of the value—may be viewed as a powerful policy evaluation operator.
2. 传统蒙特卡洛树搜索 MCTS
2.1 树搜索
围棋第一手有 \(361\) 种下法,第二手有 \(360\) 种,第三手有 \(359\) ,依次类推,即一共有 \(361!\) 种下法。这个一个天文数字,比目前可观测宇宙的全部原子数还要多。要进行彻底树搜索,是不可能的。所以咱们必须进行剪枝,并限制思考的深度。

所谓剪枝,就是指不必考虑每种下法,咱们只需考虑最有价值的几手下法。所谓限制思考的深度,就是咱们最多只思考5步,10步,20步。常见的算法是Alpha-beta剪枝算法。可是,剪枝算法也有它的缺陷,它颇有可能过早的剪掉了后期价值很大走法。
2.2 蒙特卡洛方法
简而言之,蒙特卡洛方法(Monte Carlo method),是一种“统计模拟方法”。
假设咱们要计算一个不规则形状的面积,咱们只需在包含这个不规则形状的矩形内,随机的掷出一个点,每掷出一个点,则 \(N+1\) ,若是这个点在不规则图形内则 \(W+1\) 。落入不规则图形的几率即为 \( W/N\) 。当掷出足够多的点以后,咱们能够认为: \(不规则图形面积=矩形面积*W/N\) 。
要应用蒙特卡洛算法的问题,首先要将问题转化为几率问题,而后经过统计方法将其问题的解估计出来。
2.3 蒙特卡洛树搜索 MCTS
这种算法简而言之是用蒙特卡洛方法估算每一种走法的胜率。若是描述的再具体一些,经过不断的模拟每一种走法,直至终局,该走法的模拟总次数 \(N\) ,与胜局次数 \(W\) ,便可推算出该走法的胜率为 \(W/N\) 。

该算法的每一个循环包含4个步骤:
- 选择: 从根节点往下走,每次都选一个“最值得看的子节点”(具体规则稍后说),直到来到一个“存在未扩展的子节点”的节点,如图中的 \( 3/3 \) 节点。什么叫作“存在未扩展的子节点”,其实就是指这个局面存在未走过的后续着法。
- 扩展: 咱们给这个节点加上一个 \( 0/0 \) 子节点,对应以前所说的“未扩展的子节点”,就是尚未试过的一个着法。
- 仿真: 从上面这个没有试过的着法开始,用快速走子策略(Rollout policy)走到底,获得一个胜负结果。按照广泛的观点,快速走子策略适合选择一个棋力很弱但走子很快的策略。由于若是这个策略走得慢(好比用 AlphaGo 的策略网络走棋),虽然棋力会更强,结果会更准确,但因为耗时多了,在单位时间内的模拟次数就少了,因此不必定会棋力更强,有可能会更弱。这也是为何咱们通常只模拟一次,由于若是模拟屡次,虽然更准确,但更慢。
- 回溯: 把模拟的结果加到它的全部父节点上。例如第三步模拟的结果是 \(0/1\) (表明黑棋失败),那么就把这个节点的全部父节点加上 \(0/1\) 。
2.4 上限置信区间算法 UCT
怎么选择节点?和从前同样:若是轮到黑棋走,就选对于黑棋有利的;若是轮到白棋走,就选对于黑棋最不利的。但不能太贪心,不能每次都只选择“最有利的/最不利的”,由于这会意味着搜索树的广度不够,容易忽略实际更好的选择。
为了在最大胜率和新节点探索上保持平衡,UCT(Upper Confidence Bound,上限置信区间算法)被引入。所谓置信区间,就是几率计算结果的可信度。打个比方,若是掷了3次硬币,都是正面朝上,咱们就认为掷硬币正面朝上几率是100%,那确定是错误的,由于咱们的样本太少了。因此UCT就是用来修正这个样本太少的问题。
具体公式以下:
$$\text{score = }\ \frac{w_i}{n_i}+c\sqrt{\frac{\ln N_i}{n_i}}$$
- \(w_i\) 是 \(i\) 节点的胜利次数
- \(n_i\) 是i节点的模拟次数
- \(N_i\) 是全部模拟次数
- \(c\) 是探索常数,理论值为 \(\sqrt{2}\) ,可根据经验调整,\(c\) 越大就越偏向于广度搜索,\(c\) 越小就越偏向于深度搜索
咱们看例子说明这是什么意思,就看以前的图吧。

假设根节点是轮到黑棋走。那么咱们首先须要在 \(7/十、5/八、0/3\) 之间选择 (即第二排):
- 其中 \( 7/10 \) 对应的分数为 \(7/10 + C \cdot \sqrt{\frac{\log(21)}{10}} \approx 0.7 + 0.55 C\) 。
- 其中 \( 5/8 \) 对应的分数为 \(5/8 + C \cdot \sqrt{\frac{\log(21)}{8}} \approx 0.625 + 0.62 C\) 。
- 其中 \( 0/3 \) 对应的分数为 \(0/3 + C \cdot \sqrt{\frac{\log(21)}{3}} \approx 0 + 1.00 C\) 。
- 能够注意到, \(C\) 越大,就会越照顾访问次数相对较少的子节点。
若是 \(C\) 比较小,咱们将会选择 \(7/10\) ,接着就要在 \(2/4\) 和 \( 5/6 \) 间选择。注意,因为如今是白棋走,须要把胜率估计倒过来:
- 其中 \(2/4\) 对应的分数为 \((1-2/4) + C \cdot \sqrt{\frac{\log(10)}{4}} \approx 0.5 + 0.76 C\) 。
- 其中 \(5/6\) 对应的分数为 \((1-5/6) + C \cdot \sqrt{\frac{\log(10)}{6}} \approx 0.17 + 0.62 C\) 。
那么咱们下一步确定应该选 2/4。因此说这张图是错误的,由于制图的人并无注意到要把胜率倒过来。
3. 深度强化学习
3.1 神经网络与MCTS的结合
常见的MCTS分为4个步骤:选择,扩展,模拟和反向传播。
神经网络用来指导MCTS进行判断,主要目的是用神经网络的输出代替四个步骤中的扩展和模拟这两步。
神经网络的输出是落子几率和局面评估。从根节点开始,选择到叶节点,而后判断是否表明这结束,若是没有结束,则根据神经网络输出的评分进行更新,同时根据神经网络给出的落子策略进行扩展。若是结束,则根据玩家的胜负进行更新。
可是对于传统的MCTS,咱们没有好的策略,因此只能大规模的搜索。在到达叶节点所表明的局面的时候,咱们须要使用随机策略进行屡次模拟,一直模拟到对局结束才能获得局面的评估。这须要消耗大量的计算资源和时间。因此引入神经网络来代替模拟步骤。
因此总的来讲,落子的选择总体是根据MCTS来的。神经网络的做用是帮助缩短MCTS所须要的时间。
没有 MCTS 至关于职业棋手只凭棋感不作计算走快棋。神经网络提供几个候选的走法,MCTS 再算一算到底哪一个点更好。
3.2 神经网络架构
由残差模块构成的 CNN,输入为 \(19\times 19\times 17\)
17 是 17 个特征,使用了既往 8 个回合的 16 个特征以及一个当前玩家信息特征 \((8 \times 2 + 1 = 17)\) :
$$s_t = [X_t , Y_t , X_{t−1}, Y_{t−1}, …, X_{t−7}, Y_{t−7} , C]$$
其中 \(X_t\) 内包含的是当前棋手的数据:
加入当前棋手执黑棋,那么此时棋盘上全部黑棋对应的位置取值1,白棋和空白位置取值0。相似的 \( Y_t \) 反映的就是白棋信息,当前棋盘上全部白棋的位置取值1,黑棋和空白处取值0。
\(C\) 内的全部 \((19\times 19)\) 个数据要么都是1,要么都是0,若是此时是黑棋要落子则取1,白棋落子则取0。
网络的共同部分多数是用 \(3\times 3\) 的卷积核(stride = 1),256个特征数,后接 BatchNormalization 和 Relu 单元。每个残差单元包括 (参见下图):
- 策略端:输出特征数为 \(19\times 19+1\),分别表明在棋盘上全部可能位置落子的可能性以及 Pass 的可能性。
- 价值端:全链接一个256个特征的隐藏层,最后以tanh的激活方式输出 \([-1,1]\) 之间的值。
网络的前20层左右,是常见的神经网络结构。而后跟着是两个“头”,一个头取走了前20层的输出,而后产生了下一步的落子几率,另外一个头基于一样的数据,输出当前局面的获胜几率。

训练数据:自我对弈产生大量的 \(( s,\pi,z )\) 数据对,经过 Mini-batch 采样。
损失函数:
$$ l=(z-v)^{2}-\pi^{T}log(p)+c||\theta||^{2} $$
- 第一项:经过最小二乘最小化获胜几率偏差
- 第二项:经过交叉熵最大化先验走子几率与提高后走子几率一致性
- 第三项:L2范数权值衰减防止过拟合。
3.3 过程细节
为了在 self play 每一步获得,MCTS 须要完成1600次搜索。搜索树中每一节点 \(s\) 针对合法操做保存如下数据结构
$$\{N(s,a),W(s,a),Q(s,a),P(s,a) \}$$
- \(s\ \) 树的每个节点表明了一种棋盘布局
- \(a\ \) 每个边表明了在一种布局 \(s\) 下的一种落子方式
- \(N(s,a)\ \) 记录边的访问次数
- \(W(s,a)\ \) 合计行动价值
- \(Q(s,a)\ \) 平均行动价值
- \(P(s,a)\ \) 选择该条边的先验几率
屡次模拟过程会在独立线程并行运行。搜索算法在 \(a,b,c\) 三步迭代屡次后,根据搜索结果选择落子 \(d\) 。

- a 每次模拟选择的分支,有最大 \(Q+U\) , 其中 \(Q\) 是动做价值, \(U\) 是上限置信, \(U\) 依赖于一个存储在分支上的优先几率 \(P\) 和该分支的访问次数 \(N\) (每访问一次 \(N+1\))
- b 扩展叶节点,神经网络 \((P(s, .), V(s)) = f_θ(s)\) 评估 \(s\) ; 将向量 \(P\) 的值被存储在 \(s\) 的扩展边上
- c 根据 \(V\) 更新动做价值(action-value) \(Q\),反映全部该动做的子树的平均值
- d 一旦搜索结束,搜索几率 \(\pi\) 被返回,与 \(Ν^{(1/τ)}\) 成正比, \(N\) 是每一个分支的访问次数,而 \(τ\) 是一个参数控制着温度(temperature)
这里先知晓有这样的神经网络结构 \((p,v)=f_{\theta}(s)\) (初始状态参数 \(\theta\) 随机赋值)
在自我对弈的每一步,根据深度神经网络计算出落子几率(先验几率 \(p\) ),如对状态 \(s_{1}\) 获得 \((p_{1},v_{1}) \) ;而后经过 MCTS(蒙特卡罗搜索树算法)进行 policy
improvement,MCTS 搜索的输出是当前状态 \(i\) 下不一样位置落子的几率 \( \pi_{i} \) ,该落子几率会优于该状态下先验几率 \(p_{i}\) ,而后基于 \( \pi_{i} \) 完成当前步骤落子,以后每步均如此过程直到完成当前对局获得最终结果 \(z( z\in[-1,1] )\) 。

神经网络经过使用 MCTS 搜索的自我对弈强化学习来进行训练。一开始神经网络的参数被随机设置称 \(\theta_0 \) ,在随后的每一次迭代中 \( i\geq1 \) ,会经过自我对弈产生许多完整的棋局,在其中每个完整棋局的一个时间步 \( T \) 时,都会利用上一个神经网络的参数来产生搜索策略 \( \pi_t = \alpha_{i-1}(s_t) \) ,而且用这个策略的采样产生实际自我对弈时的行为。
发生下列任意状况之一,游戏终止于时间 \( T \) :
- 双方都 Pass
- 搜索 value 下降至一个被 resignation(割舍?)的阈值
- 游戏对弈达到设定的最大步数
游戏结束后,会给出一个最终奖励 \(r_T \in \{ -1, +1 \}\) , 每个时间步 T 的数据以 \( (s_t, \pi_t, z_t) \) 的形式保存,其中 \(z_t = \pm r_T\) 是从 \(T\) 时刻玩家的立场获得的胜利者的奖励(是否是能够理解成: \(T \) 时刻无论是白方仍是黑方,只要最终赢得棋局, \( z_t = 1 \) 即成立?)。
不过须要在一个完整的对局结束后才能肯定这一局中每个 \( (s, \pi, z) \) 中的 \(z\) ,若是最后的胜者是 \( s \) 局面下的当前 player,则 \( z=1 \) ,若是最后的败者是 \( s\) 局面下的当前 player,则 \(z=-1\) ,若是最后打平,则 \(z=0\)
自我对弈过程当中的最后几回迭代过程当中产生的数据 \( (s,\pi,z) \) 将会以均等的几率被选中来训练神经网络。
AlphaGo Zero 里面的神经网络其实是把 AlphaGo 里面的 Policy Network 和 Value Network 糅合在一块儿了,因此这个神经网络也有两个目标,神经网络的训练目标就是要尽量的缩小两方面的差距:
- 让网络输出的落子几率向量 \(p\) 和 MCTS 搜索输出 \(\pi\) 越接近越好
- 让网络预测的当前棋手的最终结果 \(v\) 和最终游戏赢家 \(z\) 越接近越好
神经网络的损失函数由下式肯定:
$$l = (z-v)^{2} - {\pi}^\top logP + c ||\theta||^2 $$- \(c \) 是控制参数 L2 正则项的一个系数。
网络训练获得的新参数会被用来知道下一轮迭代中自我对弈时的 MCTS 搜索。
AlphaGo Zero 每1000步会将一个神经网络存档,而且把这个存档和历史最优版本比较,若是胜率超过历史最优的55%,这个版本将会被更新为历史最优。而且在生成数据时,只使用历史最优的神经网络的 self-play 数据做为深度网络的训练数据。这样能够增长算法的优化速度。
4. 搜索阶段算法

a 选择 Select
每一次模拟的第一个阶段起自搜索树的根节点 \(s_0\) ,在第 L 个时间步结束于搜索树的叶节点 \(s_L\) 。对于其中的任意时间 \(t<L\) ,根据搜索树内的统计数据来决定选择哪个模拟行为
$$a_t = \underset{a}{argmax}(Q(s_t, a) + U(s_t, a))$$
其中:
$$U(s,a) = c_{puct}P(s,a)\frac{\sqrt{\sum_{b}{N(s,b)}}}{1+N(s,a)}$$
- \(c_{puct}\) 是决定探索程度的一个系数
this search control strategy initially prefers actions with high prior probability and low visit count, but asympotically prefers actions with high action value.
b 扩展和评估 Expand & Evaluate
叶节点 \(s_L\) 将会等待来自神经网络的评估 \((d_i (p), v) = f_\theta (d_i (s_L )) \),其中 \(d_i \) 是一个 dihedral reflection 或 rotation, \(i\in[1,2,3,…,8] \) 。
其中经过一个1至8的随机数来表示双方向镜面和旋转(由于围棋在棋盘旋转和镜像以后的胜率估算状况是同样的,以下图所示)

这些等待评估的状态会被送入一个队列,在神经网络评估队列里的状态时(使用 mini_batch_size=8),搜索将被暂时锁定。当神经网络获得结果后,该叶节点会被展开,同时每一条可能的边 \((s_L,a)\) 会如下面的数据进行初始化:
$$\{ N(s_L,a)=0,W(s_L,a)=0,Q(s_L,a)=0,P(s_L,a)=P_a \}$$
同时来自神经网络的对该叶节点的价值估计也会影响路径中每个节点的统计数据 \(W\)(见下),随后进行回溯过程。
AlphaGo Zero 会根据前面的落子规则不断的落子,这就至关于棋手在脑海中进行推演。可是围棋的搜索空间即便对于计算机来讲也是太大,AlphaGo zero 只会推演(仿真)到必定步数就中止了。假设最后的布局是 \(s’\) , 那么 AlphaGo Zero 会调用深度神经网络来预测这局推演结束时本身的胜率 \(v(s’) \) 。这样的推演过程会进行屡次。
c 回溯 Backup
等一次推演结束后,AlphaGo zero 会根据推演的结果更新本身的知识,也就是值函数 \(Q(s,u)\)
对于 \( t \leq L \) ,每个边的统计结果将被更新。
$$ N(s_t,a_t) = N(s_t,a_t)+1$$
$$ W(s_t,a_t) = W(s_t,a_t)+v $$
$$Q(s_t,a_t) = \frac{W(s_t,a_t)}{N(s_t,a_t)}$$
$$N(s,a) :\ 记录边的访问次数 $$
$$W(s,a) :\ 合计行动价值 $$
$$Q(s,a) :\ 平均行动价值 $$
d 产生实际行为 Play
路径中全部节点统计数据获得更新后(搜索结束后), AlphaGo Zero 在根节点 \(s\) 处选择 \(a\) 操做进行落子,根据最新的统计数据来产生一个实际的行为 \(\pi_{a}\) ,与访问次数成幂指数比例:
$$\pi(a|s)=\frac{N(s,a)^{1/\tau}}{\sum_{b}^{}{N(s,b)^{1/\tau}}}$$
\(\pi_{a}\ (\pi(a|s))\) 是落子到位置 \(a\) 的几率
\(\tau \) 为温度参数,控制探索的程度, \( \tau\) 越大,不一样走法间差别变小,探索比例增大,反之,则更多选择当前最优操做。
在随后的时间步 (time_steps) 中,这个搜索树将会继续使用,对应于实际所采起的行为的子节点将变成根节点,该子节点下的子树的统计数据将会被保留,而这颗树的其他部分将会丢弃 (discarded)。
另外,若是该子树的根节点和最佳价值子节点的价值低于某一个阈值 \( v_{resign}\),AlphaZero 将放弃搜索某子树。