图:pixabay
本文来自于微信公众号:雷克世界
编译 | 嗯~是阿童木呀、KABUDA
在这篇文章中,我将试图对以下三件事情进行阐述:
1.AlphaZero之所以被认为是人工智能向前迈进一大步的两个理由。
2.如何构建AlphaZero方法的副本,从而使其能够玩Connect4游戏。
3.如何调整代码从而使其能够插入到其他游戏中。
▌AlphaGoAlphaGo ZeroAlphaZero
2016年3月,在一场超过2亿人观看次数的比赛中,Deepmind的AlphaGo以 4-1的比分击败了获得过18次世界冠军的围棋选手李世石(Lee Sedol)。一台机器已经学会了能够下围棋的超人类策略,这是一个以往从未有过被认为是不可能的壮举,或者,至少是十年之后才能达到这一水平。
AlphaGo vs李世石的第三场比赛
这本身就是一个了不起的成就。然而,2017年10月18日,DeepMind再一次向前迈出了一大步。
在这篇名为《在没有人类知识的情况下掌握围棋游戏》文章中,揭示了该算法的一个新变体——AlphaGo Zero,且以100-0的比分击败了AlphaGo。令人难以置信的是,它是通过自我学习,完全“从零开始(tabula rasa)”开始,并逐渐找到能够击败自身以往身份的策略。不再需要用人类专家游戏数据库去构建一个超越人类的AI。
《在没有人类知识的情况下掌握围棋游戏》文中的图
仅仅48天后,在2017年12月5日,DeepMind又发布了另一篇论文《使用通用强化学习算法自我学习掌握国际象棋和日本象棋》,展示了AlphaGo Zero是如何能够在国际象棋和日本象棋中击败世界冠军项目StockFish和Elmo。整个学习过程,从第一次观看游戏比赛到成为世界上最好的计算机程序,仅仅花费了不到24小时的时间。
基于此,AlphaZero就诞生了——这是一种通用算法,它能够快速获得某些知识,而不需要任何人类专家策略的先验知识。
关于这个成就,有以下两个令人惊奇的地方:
1. AlphaZero需要零人类专家知识作为输入
这一点的重要性不言而喻。这意味着AlphaGo Zero的潜在方法可以应用于任何具有完美信息的游戏(两个玩家都可以随时了解游戏状态),因为除了游戏规则之外不需要任何专业知识。
这就是为什么DeepMind能够在原始AlphaGo Zero论文发表48天后,便发表国际象棋日本象棋论文。毫不夸张地说,所有需要改变的只是输入文件,即描述游戏的机制,并调整与神经网络和蒙特卡罗树搜索有关的超参数。
2.该算法非常优雅
如果AlphaZero使用的是超级复杂的算法,世界上只有少数人能够理解,那么这将只不过是一个令人难以置信的成就。之所以让它与众不同的是,本文中的许多观点实际上远没有以前的版本那么复杂。它的核心就在于以下简单的学习方法:
对可能的未来场景进行思考,优先考虑最有前景的路径,同时考虑其他人将最有可能对自己的行为所作出的反应,并继续探索未知的情况。
在达到一个陌生的状态之后,评估你对自己的位置是否有利的置信度,并通过导致这一点的精神通路中的先前位置将分数级联回来。
在你已经思考了未来的可能性之后,采取你已经探索过最多的行动。
在游戏结束时,返回并评估在哪些位置你对未来位置进行了错误评估,并相应地更新你的理解。
这听起来不像你在学习玩一个游戏吗?当你做出不好的举动时,可能是因为你错误地判断了所得到位置的未来价值,或者你错误地判断了你的对手会采取某种行动的可能性,所以没有想到去探索这种可能性。而这些正是AlphaZero被训练去学习的游戏的两个方面。
▌如何构建你自己的AlphaZero
首先,查看AlphaGo Zero备忘录,以便高度了解AlphaGo Zero的工作原理。当我们遍历代码的每个部分时,你会发现这是很值得参考的。这里还有一篇很好的文章,更为详细地解释了AlphaZero是如何运行的。
代码
该链接里面包含我将引用的代码(https://github.com/AppliedDataSciencePartners/DeepReinforcementLearning)。
要开始学习过程,请运行run.ipynb Jupyter记事本中的前两个面板。一旦它建立了足够的游戏位置来填补它的记忆,神经网络就会开始进行训练。通过附加的自我练习和训练,在预测游戏价值和接下来的任何位置移动的过程中,它将逐渐变得更好,从而做出更好的决策和更聪明的游戏玩法。
现在我们来看看更详细的代码,并展示一些结果,证明随着时间的推移AI变得更强大。
N.B——这是我对AlphaZero运行原理的理解,主要是基于上面提到的论文中所提供的信息。如果以下存在任何不正确性,在此致以最真挚的道歉,并尽力纠正!
Connect4
我们的算法将学习玩的游戏是Connect4(或者Four In A Row)。不像围棋那么复杂,但总共还是会有4,531,985,219,092个游戏位置。
Connect4
游戏规则很简单。玩家轮流在任何可用列的顶部输入他们的颜色。第一个获得连续四个颜色的玩家——每一种都呈现垂直、水平或对角,则获胜。如果整个网格被填满而没有成功地创建出同一颜色存在于同一行的现象,则游戏终止。
以下是组成代码库的关键文件的总结:
game.py
该文件包含Connect4的游戏规则。
每个方格分配一个从0到41的数字,如下所示:
Connect4的动作方块
game.py文件给出了从一个游戏状态转移到另一个游戏状态的逻辑,给出了一个选择的动作。例如,给定一个空板和动作38,takeAction方法返回一个新的游戏状态,而起始玩家的部分位于中间列的底部。
你可以用任何符合相同API的游戏文件替换game.py文件,算法将原则上根据你给定的规则通过自我学习来学习策略。
run.ipynb
这包含启动学习过程的代码。它加载游戏规则,然后遍历算法的主循环,其中主要包括三个阶段:
1.自我练习
2.重新训练神经网络
3.评估神经网络
在这个循环中有两个智能体,best_player和current_player。
best_player包含表现最好的神经网络,并用于生成自我练习的记忆。current_player然后根据这些记忆重新训练它们的神经网络在,然后与best_player进行互搏。如果它赢了,那么best_player里面的神经网络将被切换到current_player中的神经网络,然后,循环再次开始。
agent.py
这包含智能体类(游戏中的玩家)。每个玩家都用自己的神经网络和蒙特卡罗搜索树进行初始化。
simulate方法运行蒙特卡洛树搜索过程。具体来说,智能体移动到树的叶节点,用它的神经网络评估节点,然后通过树回填节点的值。
act方法多次重复模拟,以了解从当前位置进行的移动哪个是最有利的。然后它将选定的动作返回给游戏,以执行该动作。
replay方法使用以前的游戏记忆重新训练神经网络。
model.py
使用Keras构建残差卷积网络的示例
该文件包含Residual_CNN类,该类定义了如何构建神经网络的实例。
它使用的是AlphaGoZero论文中神经网络体系结构的压缩版本——即卷积层,接着是许多残差层,然后分解为一个值和策略。
卷积过滤器的深度和数量可以在配置文件中进行指定。
Keras库是用来建立网络的,且还使用Tensorflow后端。
要在神经网络中查看单个卷积过滤器和密集连接层,请在run.ipynb记事本中运行以下内容:
来自神经网络的卷积过滤器
MCTS.py
这包含Node、Edge和MCTS class,它们构成了蒙特卡罗搜索树。
MCTS类包含前面提到的moveToLeaf和backFill方法,并且Edge类的实例存储了每个可能移动的统计信息。
config.py
你可以在此设置影响算法的关键参数。
调整这些变量将影响算法的运行时间、神经网络的精准度和整体算法的成功率。上述参数会产生一个高质量的四子连珠(Connect4)玩家,但这样做需要花费很长的时间。如果想加快算法的速度,可以进行以下尝试。
funcs.py
包含在两个智能体之间进行匹配的play matches和play matches between Versions函数。
如果要与你创建的玩家进行对战,可以运行下面的代码(这也是在run.ipynb记事本中)
from game import Game
from funcs import playMatchesBetweenVersions
import loggers as lg
env = Game()
playMatchesBetweenVersions(
env
, 1 # the run version number where the computer player is located
, -1 # the version number of the first player (-1 for human)
, 12 # the version number of the second player (-1 for human)
, 10 # how many games to play
, lg.logger_tourney # where to log the game to
, 0 # which player to go first - 0 for random
)
initialise.pyv
运行算法时,所有模型和内存文件都保存在run文件夹的根目录中。如果稍后要从此检查点重新启动算法,需要将运行文件夹转移到run_archive文件夹中,并将一个运行号附加到文件夹名称上。然后,将运行编号、型号版本号和内存版本号,按照其在run_archive文件夹中的相应位置,输入到initialise.py文件中。然后从这个检查点开始,像往常一样运行算法。
memory.py
Memory class的一个实例,用以存储游戏记录的记忆,该算法用于重新训练current_player的神经网络。
loss.py
此文件包含一个自定义损失函数,用以在传递到交叉熵损失函数之前,对非法移动的预测进行掩码处理。
settings.py
run和run_archive文件夹的位置。
loggers.py
日志文件保存到运行文件夹中的日志文件夹中。
要打开日志记录,需在此文件中将logger_disabled变量的值设置为False。
查看日志文件将帮助你了解算法的工作原理,并了解其“思想”。例如,这里是logger.mcts文件中的一个示例。
logger.mcts文件中的输出
同样来自于logger.tourney文件,你可以在评估阶段看到每个与移动相关的概率。
logger.tourney文件的输出
▌结果
经过几天的训练,可以根据最小梯度的迭代次数得出以下损失图表:
对小批量迭代数的损失
最上面的线是策略头部(policy head)的误差(MCTS相对于神经网络输出的交叉熵移动概率)。最下面一行是值头(value head)的误差(实际游戏之和神经网络预测值之间的均方误差)。中间的线是二者的平均值。
显然,神经网络在预测每个游戏状态的值和下一步可能采取的动作方面正变得越来越好。为了说明这一结果是如何在越来越强的比赛中产生的,我在17名球员中选出了一个联盟,从神经网络的第1次迭代到第49次。每一组玩两次,两个玩家都有机会先玩。
这是最后的排名:
显然,后期版本的神经网络优于早期版本,并赢得了它们之间的大部分比赛。另外,学习似乎并没有达到饱和,随着训练时间的进一步延长,球员们变得越来越强大,并且学习的策略越来越复杂。
例如,随着时间的推移,神经网络所倾向的一个明确的策略是尽早抓住中心栏。观察算法的第1个版本和第30个版本之间的差别:
第1代神经网络版本:
第30代神经网络版本:
这是一个很好的策略,因为很多行都需要中间栏——要求尽早确保对手无法利用这一点。神经网络已经学会了这一点,并且不需要任何输入。
学习不同的游戏
游戏文件中有一个名为“Metasquares”的game.py文件。它可以在网格中放置X和O标记,以尝试形成不同大小的正方形。较大的方块比小方块得分多,当网格被填满的时候,得分最多的玩家获胜。如果你将Connect4 game.py文件替换为Metasquares game.py文件,那么相同的算法将学习如何玩转Metasquares。
作者 | David Foster