最近偶然看到一个写轻量版(5*5)围棋的问题,当时第一时间就想到了当年(2015年吧)让世界震惊的AlphaGo。好奇心驱使,查了一下相关理论。发现AlphaGo已经被它的新一代版本AlphaGo Zero(2017)给打败了。怀着对科研前辈瞻仰的心情,浅显的研究了一下AlphaGo Zero的原理。原来,AlphaGo Zero才是真正的棋神
Tittle
分析:
AlphaGo Zero主要是有两部分组成:MCTS+神经网络。
MCTS是什么东西?
那么博弈论中,我们把zero-sum、perfect、information、deterministic、discrete、sequential的游戏统称为Combinatorial Game,例如围棋、象棋等,而MCTS只能解决Combinatorial Game的问题。
MCTS全程Monte Carlo tree search,就是一个处理决策的搜索算法。我们在下围棋的时候,每一个落子都是一个决策的过程。
source
以5x5的棋盘为例,一开始棋盘为空,那么为初始窗台s0,s0向下可以有25个地方放置黑子,那么s0下实际上有25个子状态(s0有25个儿子),同理,在s0的孙子辈,就改下白子了,那么每个儿子下面都有24个子状态,s0有25*24个孙子。这样来看,如果对于国际围棋来19x19来说,它的子子孙孙无穷匮也!这将是一个又宽、又深的一颗树。
暂且先不考虑多深,所有棋局都是从s0开始,黑白双方每次落子一次,都会决定分支的走向。当棋局结束,实际上就是走过了这颗大树的某一个分支而已。
每次完成一个对局,我们都记录这个分支,那么根据对局的结果,就可以知道这个分支是黑棋赢了还是白棋赢了。一旦我们完成这个树的所有分支,我们就可以得到每一个树的节点的黑白棋输赢概率。假设我们知道了每个节点黑棋的胜率,我们如果作为黑方,就一直选择胜率高的方向。如果作为白方,我们就一直选择黑棋胜率低的方向。其实这就是MinMax策略
但是当搜索空间巨大,就像围棋这种,我们不能穷举出这个树的每一个节点,那么我们就无法准确计算每个节点的黑棋赢的概率。这时,在迭代的时候,我们可以使用UCB(Upper Confidence Bound)算法来兼顾探索和利用。该算法的思路是如果存在没有被探索的节点,我们先去尝试探索他,如果都被探索了,我们就根据访问次数等综合指标来评价去选择哪个子节点(找哪个儿子的问题)。
arg
max
v
′
∈
c
h
i
l
d
r
e
n
o
f
v
Q
(
v
′
)
N
(
v
′
)
+
c
2
ln
N
(
v
)
N
(
v
′
)
\arg \max_{v' \in children of v} \frac{Q(v')}{N(v')} + c \sqrt{\frac{2 \ln N(v)}{N(v')}}
argv′∈childrenofvmaxN(v′)Q(v′)+cN(v′)2lnN(v)
Q是我们这个节点的累计quality值。例如黑棋如果赢了,我们给他1的奖励。那么这个奖励就会从叶子节点不断往上回溯,增加该路径每个节点的Q值
N 该节点的访问次数
c 常数 1 / 2 1/\sqrt 2 1/2 经验值。
v代表节点
MCTS流程:
主要有四个关键步骤:
- 选择:如果有没被探索的,就选择没探索过的,否则通过UCB进行选择,一直选到一个没有儿子的节点A。
- 扩张Expand:选中的子节点A下创建该节点的儿子节点B。
- 模拟Simulation:因为创建出新节点B,我们需要确定这个节点的Q值,这时候我们进行一个模拟,自己心里在这走棋,然后得到这个子节点的Q值。
- 回溯Backpropagation:新创建的节点B的Q值估计出来了,那么我们就开始一直反向回溯更新它的父节点、爷爷节点、太爷爷节点、太太爷爷节点…的Q值。
其中TREE_POLICY就是实现了Selection和和Expansion两个阶段,DEFAULT_POLICY实现了Simulation阶段,BACKUP实现了Backpropagation阶段
AlphaGo Zero
AlphaGo Zero进步于AlphaGo的地方是它完全不需要任何的背景知识! AlphaGo还需要喂入棋谱,AlphaGo Zero完全是自我博弈的结果。其实他的原理很简单,就是一刻决策树,但是在训练的时候,对这棵树进行了处理,使他不必去探索很多无用的节点!
MCTS+NN
他有一个神经网络,这个神经网络输入端是当前的棋局状态S,输入端有两个值:p(选择每个动作的概率)和v(当前状态s下玩家(例如黑棋)的赢的概率)。神经网络使用了很多残差网络和卷积网络以及batch normalisation等。
在MCTS的simulations过程中,使用神经网络进行模拟。
在每个节点选择中,使用的最大化UBC :
Q
(
s
,
a
)
+
U
(
s
,
a
)
w
h
e
r
e
U
(
s
,
a
)
∝
P
(
s
,
a
)
/
(
1
+
N
(
S
,
a
)
)
Q(s,a) + U(s,a) \\ where \quad U(s,a) \propto P(s,a)/(1+N(S,a))
Q(s,a)+U(s,a)whereU(s,a)∝P(s,a)/(1+N(S,a))
存储在边上的几个数据:(实现的时候,存储在子节点里就可以,因为父节点到子节点只要一个边,一个动作)
Q(s,a) : action-value, 动作价值
N(s,a): 访问次数
P(s,a): 先验概率(神经网络生成的。将神经网络的生成动作概率也作为一个参考)
新的节点被创建之后,通过神经网络生成先验概率和和价值V。 ( P ( s ′ , ⋅ ) , V ( s ′ ) ) = f θ ( s ′ ) (P(s',·), V(s')) = f_\theta (s') (P(s′,⋅),V(s′))=fθ(s′) .然后开始到c的反向传播,更新Q值以及访问次数N。 Q ( s , a ) = 1 / N ( s , a ) ∑ s ′ ∣ s , a → s ′ V ( s ′ ) Q(s,a) = 1/N(s,a) \sum_{s'|s, a \rightarrow s'}V(s') Q(s,a)=1/N(s,a)∑s′∣s,a→s′V(s′)
也就是说,AphaGo Zero和传统的MCTS不同之处是Select和SImulation时,都有神经网络的参与。
神经网络的训练,是MCTS回溯后,从下向上的进行训练网络。因为我们的value值就是从下往上推的,所以训练也要从下往上边回溯边训练。因为MCTS搜索之后的结果一定好于神经网络,所以他的结果能够知道神经网络的训练。反过来,被训练的神经网络又能促进MCTS得到更好的搜索结果。
就这样经过很多很多次的迭代训练,就能得到一个较好的搜索树。减少了树的宽度和搜索的深度,使其探索的分支更加有意义。其中还有很多其他的技巧,但是大致的思路就是MCTS+NN
后记
具体的性能对比,在论文总都有写到,主要总结就是Zero NB, 在围棋领域应该远远超越了人类。Silver David团队还把Zero的思路用在了国际象棋上,也取得了不错的成绩。
Reference
-
Silver, David, et al. “Mastering the game of Go without human knowledge.” Nature 550.7676 (2017): 354-359.