,DeepMind的围棋机器人AlphaGo在与李世石的第二局对决中第37手落子的瞬间,整个围棋界都震惊了。评棋人Michael Redmond,一位有着近千场顶级比赛经验的职业棋手,在直播中目瞪口呆,他甚至把这颗棋子从棋盘上拿下来观察周边的情况,仿佛要确认AlphaGo是否下错了棋。第二天,Redmond告诉美国围棋E杂志:“我到现在还不明白这步棋背后的道理。”李世石这位统治了世界棋坛十年的大师,花了 12 分钟来研究这一棋局,之后才做出回应。图 13-1展示了这手传说中的落子。
图13-1AlphaGo在对阵李世石的第二局中做出的传奇落子动作。这手落子震惊了许多职业棋手
这手落子完全违背了传统的围棋理论。对角落子,或者叫尖冲,会引诱白子沿着边界继续长出,并做出一道实墙。人们通常认为这是一个五五开的交换:白方获得边界的空点,而黑方则获得对棋盘中央区域的影响力。但是白棋落在离边界4格的地方,一旦让黑方做出实墙,黑方会得到过多的地盘。(我们需要对正在阅读的围棋高手表示歉意,这里的描述做了过多的简化。)第5行的尖冲看起来有些业余——至少在“AlphaGo教授”最终五局四胜战胜这位传奇棋手之前看来确实如此。在这一步尖冲之后,AlphaGo还做出了许多出人意料的落子动作。一年之后,上到顶级职业棋手,下至业余俱乐部棋手,所有人都在尝试模仿AlphaGo所采用的动作。
《深度学习与围棋》这本书的第二部分分层次深入介绍AlphaGo背后的机器学习和深度学习技术,包括树搜索、神经网络、深度学习机器人和强化学习,以及强化学习的几个高级技巧,包括策略梯度、价值评估方法、演员-评价方法 3 类技术;第三部分将前面两部分准备好的知识集成到一起,并最终引导读者实现自己的AlphaGo,以及改进版AlphaGo Zero。读完本书之后,读者会对深度学习这个学科以及AlphaGo的技术细节有非常全面的了解,为进一步深入钻研AI理论、拓展AI应用打下良好基础。
小编截选AlphaGo:全部集结的部分内容来回答这个问题。
我们将学习组成AlphaGo的所有结构,并了解它的工作机制。AlphaGo是基于职业棋谱的监督深度学习(即我们在第5章至第8章中所学的)与基于自我对弈数据的深度强化学习(即第9章至第12章所介绍的)的一种巧妙结合,然后再创造性地用这两种深度学习网络来改进树搜索。读者可能会感觉惊奇,原来我们已经对AlphaGo的所有组件都有所了解了。更精确地说,我们将要详细介绍AlphaGo系统的如下流程工作。
首先开始训练两个深度卷积神经网络(即策略网络),用于动作预测。在这两个网络架构中,其中一个深度更深,能够产生更准确的结果,而另一个则更浅,可以更快地进行评估。我们将它们分别称为强策略网络和快策略网络。强策略网络和快策略网络采用了更加复杂的棋盘编码器,包含48个特征平面。它们的网络架构深度也比我们在第6章和第7章中所见的网络更深。不过除此之外,它们看起来还是让人觉得很熟悉的。13.1节会介绍AlphaGo的策略网络架构。在13.2节中,在完成了策略网络的第一个训练步骤之后,我们将会用强策略网络作为初始点来进行自我对弈。如果用大量的算力来执行这一步,将会让机器人得到巨大的改进。在13.3节中,我们将使用这个强自我对弈网络来生成一个价值网络。这样就完成了网络训练阶段,之后就不用再做任何深度学习了。要进行一局围棋对弈,可以把树搜索作为下棋策略的基础。但与第4章的简单蒙特卡洛推演法不同的是,我们需要使用快策略网络来指导接下来的步骤。另外,还需要参考价值函数的输出,来平衡这个树搜索算法的输出。我们会在13.4节中介绍这种创新技术。从训练策略网络到自我对弈,再到使用超越人类棋手的搜索树来下棋的整个过程,都需要巨大的计算资源和计算时间。13.5节会给出几点思考,解释AlphaGo如何达到它所具有的强度,以及在进行自己的实验时合理的预期程度。
图13-2归纳了我们刚刚列出的整个流程。在本章中,我们会深入讨论图中的各个部分,并在各节中提供更多的细节。
图13-2如何训练AlphaGo AI背后的3个神经网络。首先,从人类棋谱集合开始,训练两个神经网络来预测下一步动作:一个网络更小更迅速,而另一个更大更准确。接着,我们可以继续通过自我对弈来改进较大网络的性能。自我对弈同时也为训练一个价值网络提供了数据。最后,AlphaGo会在一个树搜索算法中同时采用这3个网络,得到极强的对弈表现
13.1为AlphaGo训练深度神经网络
在前面的介绍中我们已经了解到,AlphaGo使用了3个神经网络:2个策略网络和1个价值网络。虽然看起来有点多,但在本节中我们将会看到,这几个网络以及它们的输入特征在概念上是很接近的。而关于AlphaGo所用的深度学习技术,最令人惊奇的地方反而是我们对它们的熟悉程度,本书在第5章至第12章已经对它们做了大量的介绍。在深入介绍这几个神经网络的构建和训练的细节之前,让我们先讨论一下它们在AlphaGo系统中所扮演的角色。
快策略网络——这个围棋动作预测网络与第7章和第8章中训练的网络有相似的规模。它的目的并不是成为最准确的动作预测器,而是在保证足够好的预测准确率的同时能够非常迅速地做出动作预测。13.4节介绍的树搜索推演过程会使用这个网络——而我们已经在第4章中了解到,在树搜索中要做到基本可用的程度,推演时必须能够迅速创建大量的网络。我们不会对这个网络做太深入的讨论,而会将更多的精力放在下面两个网络上。强策略网络——这个动作预测网络的优化目标是准确率,而不是速度。它是一个卷积网络,其架构比快策略网络的要深很多,而且动作预测的效果比快策略网络好两倍。和快策略网络一样,这个网络也是用人工棋谱数据训练得出的,这一点与第7章介绍的相同。训练好这个网络之后,就可以把它作为起始点来进行自我对弈,并采用第9章和第10章中介绍的强化学习技术进行改良。这个过程能够让强策略网络变得更加强大。价值网络——强策略网络进行的自我对弈产生了一个新的数据集,可以用来训练一个价值网络。具体来说,我们将采用这些棋局的输出,以及第11章和第12章中介绍的技术,来学习一个价值函数。它会在13.4节中扮演关键角色。
13.1.1AlphaGo的网络架构
现在我们已经基本了解了这3个深度神经网络在AlphaGo中的作用,下一步接着展示如何在Python的Keras库构建它们。在深入讨论代码之前,我们先概述这几个网络的架构,如下所示。如果读者需要温习卷积网络的术语,请再次阅读第7章。
强策略网络是一个13层卷积网络。这13层都产出19×19的过滤器,也就是说,在整个网络中,我们都保留了初始的棋盘尺寸。与第7章一样,我们需要把这个网络的输入进行对齐(pad)操作。第一个卷积层的核心尺寸是5,而后面的所有层的核心尺寸都是3。最后一层采用softmax激活函数,并且有一个输出过滤器。前12层都采用ReLU激活函数,且各有192个输出过滤器。价值网络是一个16层卷积网络。它的前12层与强策略网络完全一致。第13层是一个额外的卷积层,与第2~12层结构一致。第14层是一个核心尺寸为1、有一个输出过滤器的卷积层。网络最后以两个稠密层结束,一个有256个输出,采用ReLU激活函数;另一个只有单个输出,并采用tanh激活函数。
可以看到,在AlphaGo中策略网络和价值网络采用的正是第6章所介绍的深度卷积神经网络。这两个网络非常相似,我们甚至可以直接用一个Python函数来定义它们。在此之前,我们先看看Keras的一种特殊用法,它可以显著地缩短网络的定义。第7章中讲过,我们可以使用Keras的ZeroPadding2D
实用工具层来对齐输入图像。这样做完全没问题,但如果把它的功能移入Conv2D
层中,就能在模型定义时节省许多笔墨。在价值网络和策略网络中,可以对齐每个卷积层的输入,使它们的输出过滤器的尺寸与输入相同(19×19)。例如,按照我们以往的做法,第1层有19×19输入,第2层核心尺寸为5,输出是19×19过滤器,需要将第1层对齐成23×23的图像。而现在我们可以直接让卷积层维持输入尺寸,只需在定义卷积层时提供参数padding='same'
,它就能够自己处理对齐操作了。有了这种快捷定义,接下来我们就可以方便地定义AlphaGo的策略网络与价值网络所共有的11个层,如代码清单13-1所示。读者可以在GitHub代码库中的works模块中的alphago.py文件中找到这个定义。
代码清单13-1为AlphaGo的策略网络和价值网络初始化神经网络
from keras.models import Sequentialfrom keras.layers.core import Dense, Flattenfrom keras.layers.convolutional import Conv2Ddef alphago_model(input_shape, is_policy_net=False, ⇽--- 这个布尔值选项用来在初始化时指定是策略网络还是价值网络num_filters=192, ⇽--- 除最后一个卷积层之外,所有层的过滤器数量都相同first_kernel_size=5,other_kernel_size=3): ⇽--- 第1层的核心尺寸为5,其他层都是3model = Sequential()model.add(Conv2D(num_filters, first_kernel_size, input_shape=input_shape,padding='same',data_format='channels_first', activation='relu'))for i in range(2, 12): ⇽--- AlphaGo的策略网络和价值网络的前12层完全一致model.add(Conv2D(num_filters, other_kernel_size, padding='same',data_format='channels_first', activation='relu'))
注意,我们还没有指定第1层的输入形状。这是因为这个形状在策略网络和价值网络中略有不同。我们可以在13.1.2节介绍AlphaGo的棋盘编码器的代码中看到这个区别。继续model
的定义,我们还差一个最终卷积层就能完成强策略网络的定义,如代码清单13-2所示。
代码清单13-2在Keras中创建AlphaGo的强策略网络
if is_policy_net:model.add(Conv2D(filters=1, kernel_size=1, padding='same',data_format='channels_first', activation='softmax'))model.add(Flatten())return model
可以看到,最后需要添加一个Flatten
层来展平前面的预测输出,并确保与第5章至第8章中定义的模型的一致性。
如果想要返回的是AlphaGo的价值网络,可以再添加两个Conv2D
层、一个Flatten
层和两个Dense
层,然后将它们连接起来,如代码清单13-3所示。
代码清单13-3在Keras中构建AlphaGo的价值网络
else:model.add(Conv2D(num_filters, other_kernel_size, padding='same',data_format='channels_first', activation='relu'))model.add(Conv2D(filters=1, kernel_size=1, padding='same',data_format='channels_first', activation='relu'))model.add(Flatten())model.add(Dense(256, activation='relu'))model.add(Dense(1, activation='tanh'))return model
这里我们不具体讨论快策略网络的架构。快策略网络的输入特征定义与网络架构有更多技术细节,但并不能帮助我们加深对AlphaGo系统的理解。所以如果读者想要进行自己的试验,完全可以直接采用我们在works模块中已经定义好的网络,例如small
、medium
或large
。快策略网络的主要目的是构建一个比强策略网络更小的网络,能够进行快速评估。接下来我们会深入了解训练过程的细节。
13.1.2AlphaGo棋盘编码器
现在我们已经了解了AlphaGo使用的所有网络,下面讨论一下AlphaGo如何对棋盘数据进行编码。在第6章和第7章中我们已经实现了不少棋盘编码器,包括oneplane
、sevenplane
和simple
,这些编码器都存放在dlgo.encoders模块中。AlphaGo所使用的特征平面会比它们更复杂一些,但也是这些已知编码器的自然延续。
AlphaGo策略网络所用的棋盘编码器有48个特征平面,而它的价值网络还需要再添加一个平面。这48个平面包含11种概念,其中一部分是我们已经见过的,其他则是新的,我们会逐一详细讨论。总的来说,与以往的编码器相比,AlphaGo更多地利用了围棋专有的定式。最典型的例子就是在特征集合中引入了征子和引征概念(参见图13-3)。
图13-3AlphaGo将很多围棋策略概念直接编码到特征平面中,包括征子概念。在第一个例子中,白子只剩一口气了,这意味着黑方可以在下一回合吃掉它。白方可以长出来增加一口气,但是黑方也可以接着落子将白子的气减少为一口。这样一直持续下去,直到碰到棋盘边线,白子还是会被全部吃掉。而在另一种情况下,如果在征子的路线上已经有一颗白子,白方就有可能逃离被吃子的命运。AlphaGo中有一个特征平面专门用来表示征子是否能成功
我们之前所有的围棋棋盘编码器都采用了一个技巧,即二元特征(binary feature),这个技巧在AlphaGo中也被采用。例如,在捕获气的概念(棋盘上相邻的空白点)时,我们并不只用一个特征平面来表示棋盘上每颗棋子的气数,而是用3个二元表达的平面来表示一颗棋子是有1口气、2口气还是3口气。在AlphaGo中也可以看到相同的做法,但是它采用了8个特征平面来记录二元计数。在气的例子中,这意味着8个平面分别代表每颗棋子是否有1口、2口、3口、4口、5口、6口、7口和至少8口气。
AlphaGo与第6章至第8章中介绍的唯一不同点在于,它将棋子的颜色独立出来,显式地编码到另一个单独的特征平面中。回顾一下第7章的sevenplane
编码器,我们的眼平面同时包含黑子平面和白子平面,而AlphaGo只用一个特征集合用来记录气的数量,并且所有的特征都是针对下一回合的执子方。例如,在特征集“吃子数”(用来记录一个动作能吃掉的棋子数目)中,只记录当前执子方能够吃掉的棋子数量,不论它是黑方还是白方。
表13-1总结了AlphaGo所使用的全部特征平面。前48个平面用于策略网络,最后一个只用于价值网络。
表13-1AlphaGo所使用的特征平面(略)
这些特征的实现可以在本书的GitHub代码库中的dlgo.encoder模块中找到,文件是alphago.py。虽然每一个特征集的实现都不困难,但和我们将要介绍的AlphaGo其他部分相比,它们并不显得很有趣。实现“征子提子”平面难度较高,而且要对一个动作从执行时到现在的回合数进行编码,需要修改围棋棋盘的定义。因此如果读者对这些实现有兴趣的话,可以参看GitHub上的实现代码。
让我们看看AlphaGoEncoder
如何初始化,然后把它应用到深度神经网络的训练中。它需要一个围棋棋盘尺寸参数,以及一个布尔值参数use_player_plane
(代表是否包含第49个平面)。代码清单13-4展示了它的签名以及初始化过程。
代码清单13-4AlphaGo棋盘编码器的签名以及初始化
class AlphaGoEncoder(Encoder):def __init__(self, board_size, use_player_plane=False):self.board_width, self.board_height = board_sizeself.use_player_plane = use_player_planeself.num_planes = 48 + use_player_plane
13.1.3训练AlphaGo风格的策略网络
网络架构和输入特征都准备好之后,我们开始为AlphaGo训练策略网络。第一步与第7章的流程完全一致:指定一个棋盘编码器和一个代理,加载棋谱数据,并使用这些数据来训练代理。图13-4展示了这个流程。虽然我们使用了更加复杂的特征和网络,但流程还是完全一样的。
图13-4AlphaGo的策略网络监督训练过程与第6章和第7章中介绍的完全一致。我们对人工棋谱进行复盘,并重新产生一系列游戏状态。每个游戏状态编码为一个张量(这个图展示了一个只有两个平面的张量,而AlphaGo实际使用了48个平面)。训练目标是一个与棋盘尺寸相同的向量,并在实际落子点填入1
要初始化并训练AlphaGo的强策略网络,需要先初始化一个AlphaGoEncoder
,然后创建两个围棋数据生成器,分别用于训练和测试,如代码清单13-5所示。这个步骤与第7章一样。这一步的代码可以在GitHub上的examples/alphago/alphago_policy_sl.py文件中找到。
代码清单13-5为AlphaGo的策略网络的第一步训练加载数据
from dlgo.data.parallel_processor import GoDataProcessorfrom dlgo.encoders.alphago import AlphaGoEncoderfrom dlgo.agent.predict import DeepLearningAgentfrom works.alphago import alphago_modelfrom keras.callbacks import ModelCheckpointimport h5pyrows, cols = 19, 19num_classes = rows * colsnum_games = 10000encoder = AlphaGoEncoder()processor = GoDataProcessor(encoder=encoder.name())generator = processor.load_go_data('train', num_games, use_generator=True)test_generator = processor.load_go_data('test', num_games, use_generator=True)
接下来,我们可以使用本节之前定义的alphago_model
函数来加载AlphaGo的策略网络,并采用分类交叉熵损失函数和随机梯度下降法来对这个 Keras 模型进行编译,如代码清单 13-6所示。我们把这个模型称为alphago_sl_policy,以表示它是一个采用监督学习(sl是supervised learning的简写)的策略网络。
代码清单13-6用Keras创建一个AlphaGo策略网络
input_shape = (encoder.num_planes, rows, cols)alphago_sl_policy = alphago_model(input_shape, is_policy_net=True)pile('sgd', 'categorical_crossentropy', metrics=['accuracy'])
现在第一阶段的训练只剩下最后一步了。和第7章一样,使用训练生成器和测试生成器对这个策略网络调用fit_generator
。除网络更大、编码器更复杂之外,其他地方都和第6章至第8章完全一样。
训练结束后,我们可以从model
和encoder
创建一个DeepLearningAgent
,并把它存储起来(如代码清单13-7所示),以备后面讨论的两个训练阶段使用。
代码清单13-7训练一个策略网络并持久化存储
epochs = 200batch_size = 128alphago_sl_policy.fit_generator(generator=generator.generate(batch_size, num_classes),epochs=epochs,steps_per_epoch=generator.get_num_samples() / batch_size,validation_data=test_generator.generate(batch_size, num_classes),validation_steps=test_generator.get_num_samples() / batch_size,callbacks=[ModelCheckpoint('alphago_sl_policy_{epoch}.h5')])alphago_sl_agent = DeepLearningAgent(alphago_sl_policy, encoder)with h5py.File('alphago_sl_policy.h5', 'w') as sl_agent_out:alphago_sl_agent.serialize(sl_agent_out)
为简洁起见,在本章中我们并不需要像AlphaGo论文所说的那样分别训练强策略网络和快策略网络。我们不另外单独训练一个更小更快的策略网络,而是直接使用alphago_sl_agent作为快策略网络。下一节会介绍如何以这个代理为起点进行强化学习,生成一个更强的策略网络。
读到这里还想继续探索,可以阅读《深度学习与围棋》
1.本书是一本人工智能的实践性入门教程,成功地把AlphaGo这个人工智能领域中最激动人心的里程碑之一,转化为一门优秀的入门课程;
2.采用Keras深度学习框架,用Python来实现代码;
3.内容全面,层次划分细致,基本上将AlphaGo背后所有的理论知识都覆盖了;
4.提供配套源代码。
围棋这个古老的策略游戏是AI研究的特别适用的案例。,一个基于深度学习的系统战胜了围棋世界冠军,震惊了整个围棋界。不久之后,这个系统的升级版AlphaGo Zero利用深度强化学习掌握了围棋技艺,轻松击败了其原始版本。读者可以通过阅读本书来学习潜藏在它们背后的深度学习技术,并构建属于自己的围棋机器人!
本书通过教读者构建一个围棋机器人来介绍深度学习技术。随着阅读的深入,读者可以通过Python深度学习库Keras采用更复杂的训练方法和策略。读者可以欣赏自己的机器人掌握围棋技艺,并找出将学到的深度学习技术应用到其他广泛的场景中的方法。