作者:龙心尘 && 寒小阳
时间:2016年3月。
出处:http://blog.csdn.net/longxinchen_ml/article/details/50900070
http://blog.csdn.net/han_xiaoyang/article/details/50903562
声明:版权全部,转载请联系作者并注明出处
1.文章声明
- 博主是围棋小白。下棋规则都记不清楚,也没有设计过棋类AI程序。这篇文章主要是阅读《Nature》论文及关于AlphaGo的相关文章的学习心得。
- 本文的主要目的是增进分享。交流学习。方便刚開始学习的人了解AlphaGo中的算法,以及一些机器学习中的常见思路。真正的project实现过程远比本文介绍得复杂。
- 本文很多其它是启示式地进行阐述与分析,包含一些作者结合自己的理解进行的简化处理。
- 文章中不严谨和理解不当之处。欢迎大家批评指出,我们努力改动完好。
2.围棋的业务特点
机器学习的第一步都是先了解业务。围棋的业务特点包含其基本规则、对弈特性和下棋的典型思路。根据这些业务特点。我们能够分阶段实现我们的围棋算法。
2.1 围棋的基本规则
- 使用方形格状棋盘及黑白二色圆形棋子进行对弈,
- 棋盘上有纵横各19条直线将棋盘分成361个交叉点,棋子走在交叉点上。
- 两方交替行棋,落子后不能移动,
- 以围地多者为胜。
- 并且两方能够相互吃子(提子)。仅仅要我方棋子将对方某一片紧邻的棋子周围围住,就能够将对方这片棋子吃掉。
2.2 对弈特性
基于以上规则,围棋对弈过程中有下面特性:
不像象棋、军棋那样盘面上的棋子越走越少,而是越走越多。所以一局棋从開始到结束。用一张标记好走棋顺序的棋谱就能保存绝大部分下棋的信息。是一个时间序列。
例如以下图就是《Nature》论文中的樊麾与AlphaGo对弈的一个棋谱:
对弈从开局到中局变化都非常大,尤其是中局,往往是一着不慎,满盘皆输。用数学的描写叙述叫做估值函数(得分函数)非常不平滑。
- 到收尾阶段,由于棋盘上总体的棋子是越来越多的,其变化就越来越少。能够看成是一个动态收敛的过程。
- 状态空间非常大,约为
2×10170 ,超过眼下的计算机的计算能力,无法通过暴力穷举解决。
2.3 下围棋的基本思路
而人类不须要搜索这么多状态空间也能够下好围棋。说明还是有规律的,仅仅是这些规律比較抽象。我们机器学习算法就是要尽量找出人类下围棋的一些规律。我们能够简单总结一些人类下围棋典型思路例如以下:
- 首先是明白基本规则,这个方便。
- 其次是掌握一些基本“定式”,也就是在一个给定的局面下人类通常会怎么走。这个过程不涉及优劣的推断,也比較难以用确定性的规则描写叙述。
- 基于对棋局未来演化情况的评估。决定当今当下的下棋策略。所谓“手下一着子,心想三步棋”。
这是围棋最复杂的情况。
2.4 分阶段实现下棋算法
基于以上这些初步了解,我们能够分阶段实现我们的下棋算法:
- 第一步是学会人类下棋的一般定式,形成一些优秀考虑的下棋策略。
- 第二步是对落子之后的棋局演化做出有效评估。基于评估的结果优化自己的终于落子策略。
3. 先做一个baseline系统
如今我们思路大概有了。但仍然不知道模型的终于样子应该是怎样。此时我们建议先动简单手做一个baseline。然后在模型调优的过程中不断地分析问题、解决这个问题。
这样就非常有可能更快找到问题的最佳解决方式。设计baseline思路基本例如以下:
3.1 抽象成数学问题:多分类
通过以上分析可知。下围棋的过程就是一个不断地决策在哪个位置落子的过程。在落子之前,你已知棋盘上全部已落子的情况。而棋盘上总共就
3.2 哪些特征,怎样选择?
分类器的输出我们知道了。就是361个标签。那分类器的输入又是哪些特征呢?事实上就是当前的棋盘分布。
我们先考虑第一类特征。
围棋一共是361个交叉点,每一个交叉点有三种状态(白子、黑子、无子):能够用1表示黑子。-1表示白字,0表示无子。于是一个361维度的向量就能够全然表示当前棋盘的情况。
理论上说,仅仅输入这些特征就能够了。例如以下图就是演示用矩阵表示棋局状态的情况,而矩阵拉长就是一个向量了:
可是,由于围棋的极端复杂性,这些棋子(输入特征)的关系是非线性的。尽管理论上採用神经网络的算法能够处理非线性特征,可是计算量和对资源的消耗都太大。相反,假设有根据地添加一些新的特征的维度。使特征间的非线性关系不那么复杂,将使得模型变得更加简单、更加便于训练,优势还是非常明显的。
那怎么添加很多其它的特征呢?这就须要利用部分围棋领域中的知识,比方围棋中的术语:气、目、空等概念都能够作为我们构造新特征的基础。
在AlphaGo的论文中就是採用了下面很多其它的特征:
所以。输入模型的特征是一个361×n维度的向量。基于这些向量来训练模型。
终于,AlphaGo仅仅依靠一个13层的卷积神经网络就能训练出一个比較好的落子分类器。
比起图像识别竞赛用到的20、30层的深层神经网络还是比較浅了。
这些都是特征project的功劳。
3.3 初步採用什么样的模型?
我们了解到,下围棋的算法本质上就是一个分类器,而最简单的分类器就是逻辑回归。能够预期它的分类效果不一定非常好。可是速度非常快,在须要高速迭代的业务场景中可能有优势。所以逻辑回归是我们考虑的一类模型。
可是在复杂的围棋博弈中,须要很多其它高维度的抽象特征,这些构造起来非常麻烦,而经过我们之前的博文介绍。神经网络具有这样抽象高维特征的能力。可是神经网络有很多种类。什么卷积神经网络、全连接神经网络、反馈神经网络等等,究竟用哪一种呢?
我们能够继续研究围棋的业务特点来寻找启示。我们发现,围棋的棋盘本来就是个
并且我们之前的博文专门介绍过卷积神经网络。其最关键特质的在于假设图像空间中局部的像素联系较为紧密,所以其卷积层的每一个神经元仅仅关注上一层的一些局部区域,这样能够充分利用输入数据的二维结构和局部特性,降低运算过程中的參数。你能够想象成。上一层的数据区。有一个滑动的窗体,仅仅有这个窗体内的数据会和下一层的某个神经元有关联。
而这种 “局部连接性”刚好与围棋的一些特点相似。比方围棋的大部分争夺是在局部区域进行的。不同的局部争夺共同组成了围棋的全局性。所以卷积神经网络也是我们考虑的一类模型。
3.4 採用哪些数据做训练?
标签、特征、模型基本定好了,剩下的就是数据了。从哪里得到数据呢?还是回到我们之前的棋谱,那本质上是个有时间顺序的序列。假设我们能够搜集到大量标记好落子顺序的棋谱,每一步落子之前的局面全都作为特征(s,361×n维度的向量),这一步落子位置作为标签(a,361维度的向量),那不就得到了大量的有标注的数据< s , a >吗?
这还是得感谢网络时代。如今网络上有大量棋牌室。全都记录了人类下棋的过程,每天都产生大量有标注的数据。
DeepMind就是直接从围棋对战平台KGS(能够理解成外国的联众围棋游戏大厅)获得16万局6至9段人类选手的围棋对弈棋谱,总共同拥有3000万个的< s , a >位置,训练出来了一个相似人类下棋行为的模型。
4. 分析baseline的优化思路
DeepMind团队基于卷积神经网络和逻辑回归做了两个模型:一个叫做“监督学习策略网络”
4.1 评估baseline的效果
这个两个模型模型的效果例如以下:
- “监督学习策略网络”已经能够和业余水平的人类选手过招。能正确符合57%的人类落子行为,互有胜负。
- 能够把“高速策略”看做是“监督学习策略网络”的轻量级版本号。它能够比“监督学习策略网络”快1000倍,可是仅仅能正确符合24%的人类落子行为。
- 总体来说还是蛮惊人的。
可是距离职业棋手,还是有非常大的距离。
4.2 分析其下棋水平不高的原因
为什么baseline的下棋水平不高呢?推測可能有下面几个原因:
- 我们主要是拿网络棋牌室的数据去训练,这些人的水平本来就离顶尖职业棋手就有相当大一段距离。
俗话说:“跟臭棋篓子下棋,越下越臭”。
与大量业余选手下棋,训练出来的行为也难以达到职业水准。
- 古往今来,真正顶尖的棋手本来就不多。顶尖的对局棋谱相应也就不多。拿这些数据做训练远远不够。
- 更本质的问题是,我们的“估值函数”有问题。不管是卷积神经网络还是逻辑回归,都能够近似理解为基于3000万个的有标注的数据< s , a >。评价在当前局面s下,落在某一位置a的概率。也就是p(a|s)。
我们选择p(a|s)取最大值情况下的落子位置a。但这个过程没有考虑棋局的输赢信息。也就是说赢棋的落子方案也学,输棋的落子方案相同学习。
这种话。让模型怎么去分辨自己落子是赢棋还是输棋的落子方案呢?
- 即便分出了赢棋输棋方的落子方案。赢棋者的落子不一定都是好棋(如两个臭棋篓子下棋),输棋者的落子不一定都是差棋(如两个顶尖高手的精彩对弈)。那究竟应该学习赢棋过程中的哪一步落子< s , a >呢?像baseline这种模型看来更适合学习对弈两方都会走的棋路。也就是常见的“定式”。
- 更进一步,落子之后的棋局演化情况在上面的模型中根本没有体现。不把这种行为考虑进来预计非常难在棋力上有一个质的飞跃。
4.3 从对原因的分析中产生优化的思路
经过以上的原因分析,我们大致知道猜想到了问题的所在。由此能够进一步确定我们的优化思路:
- 核心目标是改进评估函数,使之更好地体现某一步落子对全局的输赢结果的影响。以全局的输赢为目标进行优化。
- 一方面,能够基于历史棋局的输赢情况进行又一次训练。
假设训练数据不够。能够考虑通过落子选择器自己与自己对局来添加训练样本数或者强化学习。
- 还有一方面,在下棋实战的时候,须要对棋局的演化情况有一个评估,须要蒙特卡罗树搜索(Monte Carlo Tree Search,MCTS)。详细展开内容见后文。
- 将两个指标综合评估。得到落子优劣情况的评判。指导我们落子。
5. 基于历史棋局评估落子优劣:估值网络
5.1 採用新的标签
在之前的模型中,我们是基于标注数据< s , a >进行训练的。也就是以当前局面s作为特征,下一步落子a作为标签。如今我们要基于局面总体的输赢进行训练。就要对原有的标签和特征进行改造。
须要添加新的标签z。表示局面相应的胜负情况:能够用1表示赢棋。-1表示输棋,0表示和棋(博主理解是“多劫循环”。也就是两方能够无休止地走下去的情况)。
而特征就是(s,a),它表示在a处落子之后的新的局面(本质上还是一个局面,能够用s’表示。《Nature》原文就是这样表示的)。
也就是说基于有标注的数据<(s,a),z>(表示当前局面为s。下一步落子为a的新局面下。输赢情况为z的数据)进行训练。
5.2 採用很多其它的数据
既然要基于历史棋局。可不能够直接以之前的16万局棋谱的输赢情况和落子情况一起进行训练呢?DeepMind团队试了一试,发现结果过拟合。
分析原因。大概就是我们刚才说的赢棋者的落子不一定都是好棋(如两个臭棋篓子下棋),输棋者的落子不一定都是差棋(如两个顶尖高手的精彩对弈)的情况。
围棋的落子是相互之间强烈相关(strongly correlated) 的,有时候一两着棋就觉得了整个棋局的输赢。
那究竟应该学习赢棋过程中的哪一两步落子< s , a >呢?
事实上我们能够换一个思路。假设真存在一两着决定胜负的棋,那就说明其它的走法非常可能就会演化到输棋,那把演化到输棋的棋局也拿过来进行训练,就能够在这一步棋上训练出赢棋的概率非常高的权重。 而之前过拟合的原因非常可能就是我们训练数据当做仍未穷尽棋局演化的各种可能,把臭棋也当做好棋来学了。所以须要想一个办法产生很多其它高质量的棋局演化可能用来训练。
既然靠人类对弈已经满足不了机器的胃口,那就用机器自己与自己对局来添加训练样本数,这就是传说中的左右互搏。
比方开局,先用某个落子选择器走n步,由于n是随机的,这就产生出n个局面分支。
觉得局面还不够多样化,再全然随机掷m次骰子。就又在每一个局面分支上产生m新的局面分支。如此循环往复。就得到了非常丰富的局面s和这些局面相应的结果z。有了这些训练样本< s , z >。再加上卷积神经网络。就能够得到一个函数
按《Nature》原文的说法,他们通过自我博弈(self-play)产生了3000万个标注样本< s , z >,每一个样本的局面s都来自不同的一局棋(each sampled from a separate game)。以此来防止过拟合(这些挑出来的样本是否可能也是臭棋?)。注意。之前也是3000万个标注样本< s , z >。但它们仅仅来自于16万局人类博弈的棋谱。
而基于此训练出来的函数叫做“估值网络”(value network
5.3 估值网络与走棋网络下棋的对照
我们知道,走棋网络输入的s是361×n维度的向量。下一步落子位置a是361维度的向量。其下棋规则是推断选择p(a|s)取最大值情况下的落子位置a。
p(a|s)就是模型的估值函数。
而估值网络输出的仅仅是一个值
所以这两个网络作为落子选择器的区别本质上就是估值函数的算法不一样。
5.4 增强学习
我们继续分析,既然走棋网络p(a|s)能够自己产生数据。那么可否用自己产生的数据来训练走棋网络p(a|s)自己(而不是估值网络
比方我们已经有了一个“走棋网络”
然后再让
当然,详细的训练过程比較复杂。这里先不展开。仅对其详细效果进行分析。既然
所以增强学习“还有非常长的路要走”(田渊栋)。
可是增强学习能够提供很多其它质量更好的样本便于估值网络
5.5 评估估值网络的效果
实践表明:估值网络
less computation)。
注意这里是对输赢的预測效果。而不是对落子可能性的预測。
6. 基于棋局演化评估落子优劣:蒙特卡罗树搜索
以上的方法我们都是基于当下的落子情况来评估落子路径优劣的。
但人类的下棋思维是“手下一着子,心想三步棋”(selects actions by lookahead search),要对之后的棋局有个评估。那怎么让机器去思考接下来的发展呢?这就须要传说中的蒙特卡罗树搜索(MCTS)。
6.1 基于估值网络v(s) 的MCTS
我们就先不说蒙特卡罗树搜索(MCTS)的术语吧,什么选择、扩展、模拟、反向传播啥的的。
这里直接下面棋的思维方式来解释这个过程,尽量生(shuo)动(ren)些(hua)。
首先,我们有一个“走棋网络”
那怎么从这些选择中找出最优的那个落子呢?咱不是刚好有个估值网络
这已经完毕了一步落子选择。可是距离“手下一着子。心想三步棋”的标准还差一些。那就继续假设走了
其思路与上面一样。
那这样对方走了一招
紧接着能够再走一着
好了。如今走了3步棋了。
是不是就够了呢?未必。假设评估
这须要我们又一次理解
network against itself)。而在我们蒙特卡罗树搜索过程中,不是用
这就须要用新的方法来评估局面s下的赢棋的概率,也就是要对原来位置的赢棋的概率
为了不至于混淆,我们直接用
此时
须要又一次挑选出一个位置
这就是蒙特卡罗树搜索的基本过程。可见,这套思路是能够不断演化下去的,越到后面。算出来的
这种算法的一个优点是:能够并行化。因此能够大量提高计算速度。
它还有一个优点,就是:它演化出来的各种状态都能够保存起来。假设对方的落子就在自己的演化路径之中,这些状态就能够直接拿来用了。这就节省了大量运算时间。
须要说明的是,这里仅仅是对蒙特卡罗树搜索做一个原理性的简化解释。真实的搜索过程能够添加很多策略,远比这里复杂。对MCTS感兴趣的读者能够看这篇文章。
6.2 基于高速走子pπ 的MCTS
事实上,我们还有还有一种蒙特卡罗树搜索。
基本演化过程与上面相似,可是选择落子的方式是基于高速走子
首先。我们还是有一个“走棋网络”
然后,对手从“胜利”的落子选项中用“走棋网络”
此时能够更新
这就体现出
6.3 综合两种搜索策略形成新的估值函数
这两种搜索各有优劣,并且在一定程度上互补。所以DeepMind将这两种策略组合到一起,效果就有质的飞跃了。下面是他们对照各种组合方式的结果:
其组合方式非常easy粗暴,就是做一个算术平均:
project实现上,还对估值函数添加了一个附加值(bonus)。目的是在高速定位比較好的落子方案的同一时候,又给其它小概率位置一定的探索可能,添加搜索丰富性。
事实上蒙特卡罗树搜索是一个非常传统的技术,可是假设不用先验的知识随机搜索。这棵树的宽度和深度要非常巨大才干返回一个相对靠谱点的值,这种计算量是天文数字。
可是通过16万局人类对弈训练出来的“走棋网络”
而通过相同数据训练出来的“高速走子”
再加上一些细节的策略,总体的效果就是降低了计算量,提高了预測精度。
7. 总结
到此为止,AlphaGo的算法原理基本介绍完了。事实上也并不复杂。并且这些都不是AlphaGo或者DeepMind团队首创的。可是强大的DeepMind团队将这些结合在一起,再加上Google公司的超级计算资源,成就了超越绝大部分顶尖棋手的人工智能。
真令人赞叹不已,向这些背后的project师致敬。
8. 參考文献
《Nature》:Mastering the game of Go with deep neural networks and tree search
田渊栋:AlphaGo的分析
How AlphaGo Works
木遥:关于 AlphaGo 论文的阅读笔记
董飞编译How AlphaGo Works
袁行远:左右互搏,青出于蓝而胜于蓝?—阿尔法狗原理解析
Introduction to Monte Carlo Tree Search