手把手:AlphaGo有啥了不起,我也能教你做一个(附Python代码)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

在2016年3月,Deepmind研发的AlphaGo以4:1的成绩,击败了曾荣获18次世界冠军的围棋选手,李世石(Lee Sedol)。超过2亿观众见证了这一历史时刻。一台机器已经学会了一种超越人类的围棋策略。这在以前被认为是一项不可能完成的任务,或者至少需要十年之功。

9c575af29d067cb45ef58aac541c34f090a8c684

AlphaGo与李世石的第3场比赛

这已是一项了不起的成就。然而,在2017年10月18日,DeepMind又再次取得了突破。

论文《无需人类知识就能称霸围棋》(Mastering the Game of Go without Human Knowledge),揭示了一种新的算法——AlphaGo Zero,它以100:0的惊人成绩打败了AlphaGo。更令人难以置信的是,它从零开始,通过自我博弈,逐渐学会了能打败自己之前的策略。至此,开发一个超级AI不再需要依赖人类专家的游戏数据库了。

c23fa08316599fd762eff9314447cdbf4bc4316c

仅48天后的2017年12月5日,DeepMind又发布了另一篇论文《通过一种通用的强化学习算法称霸国际象棋和日本象棋》(Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm),它展示了AlphaGo Zero如何能够学会国际象棋(StockFish和Elmo)和象棋。整个学习过程,从第一次参与游戏到成为世界上最厉害的计算机程序,只用了24小时。

就这样,AlphaZero华丽丽地诞生了——它无需储备任何人类棋谱,就可以以通用算法完成快速自我升级。

关于这个成就,有两点最让人称奇:

AlphaZero对人类游戏经验根本就不需要

这点的重要性怎么说都不过分。也就是说,对于任何有充分信息的游戏(对阵双方对游戏状态都全程掌握),AlphaGo Zero的方法论都可以得到完美应用!因为除了游戏规则之外,人类任何游戏经验值都是不需要的。

AlphaGo Zero的基础方法可以应用于任何具有完美信息的游戏(游戏状态在任何时候,双方玩家都完全知道的),因为在游戏规则之外,不需要事先的专家知识

这就是DeepMind能在发表AlphaGo Zero论文48天后,马上就能发表第二篇论文。毫不夸张地说,所需要改变的仅仅是新游戏规则,及与神经网络和蒙特卡罗树搜索相关的超参数。

这个算法的优雅程度秒杀众生

即便AlphaZero使用的是世界上只有极少数人能够看懂的超复杂算法,它仍然是项了不起的成就。同它相比,之前的算法可谓不复杂不成活,这才是它真正的魅力。究其核心,无非是以下极简而美的学习逻辑:

  • 脑补各种场景,挑能赢的路走,想想别人会怎么应对,并不断探索未知。
  • 在思考未来可能的情景时,优先考虑有前途的路径,同时考虑其他人最有可能如何对你的行动作出反应,并继续探索未知。
  • 遇到不熟悉的状况,评估它的利害程度,把它同之前的各种让你走到今天这一步的场景作比较。
  • 穷尽你对未来的想象,用你试过最多的招数来应对。
  • 在你考虑了未来的可能性之后,采取你已经探索过的行动。
  • 游戏结束时,回头看看在哪里犯过错,然后洗心革面、更新认知。
  • 在游戏结束时,回过头来评估你在哪里错误地判断了未来的位置,并相应地更新你的理解。

这听起来是不是很像你学玩游戏的方式? 当做错一个动作时,要么是因为你误判了这个动作会带来的结果,要么是你误判了对手可能会采取的行动。这两点正是AlphaZero学会如何玩游戏的法门。

如何构建自己的AlphaZero

首先,我们需要学习和理解AlphaGo Zero的原理。我之前写过一篇AlphaGo Zero的知识点速查手册可供参考:

https://medium.com/applied-data-science/alphago-zero-explained-in-one-diagram-365f5abf67e0

Tim Wheeler的博客中一篇文章也讲的很详细:

http://tim.hibal.org/blog/alpha-zero-how-and-why-it-works/

代码

基于下面这个代码库进行讲解:

https://github.com/AppliedDataSciencePartners/DeepReinforcementLearning

从运行Jupyter notebook中run.ipynb的前两个panel开始。一旦它完成了游戏的足够回合,那么神经网络将开始训练。通过随后的自我对弈和训练,它将逐渐在预测胜率和下一步行动上做得越来越好,从而做出更好的决策。

现在,我们需要更详细地看看面前的代码,并且展示下AI是怎样随着时间的增加变得越来越厉害的。

四子连珠(Connect4)

我们的算法将要学习如何玩这个游戏。虽然不如围棋那样复杂,但也有4531985219092种游戏走位

63bc79b0f7fa9b36c58b755f2c7ab18e7fe5dfbf

四子连珠

游戏规则很简单。玩家轮流在任何一栏的顶部布置自己的颜色。最先在垂直、水平或对角线上放置一排同一种颜色棋子的玩家获胜,如果这种情况没有出现,那游戏就是平局。

下面是组成代码库的关键文件:

game.py——这个文件包含四子连珠的游戏规则

每个正方形都被分配了一个从0到41的数字,如下图所示:

6302ac3761ed1b1f40c9d1b7c06e3ed232b755af

game.py文件给出了从一种游戏状态到另一种状态的逻辑,并且给出了一个选择的动作。比如,考虑到empty board和38号动作,takeAction方法返回到一个新的游戏状态,也就是底部一行的中心位置。

你可以将game.py文件用任何符合相同API和算法的游戏文件替换掉,根据你给它的规则,通过自我对弈的方法学习。

run.ipynb——这个文件包含开启学习过程的代码

它通过算法中的主要环节加载游戏规则,并且由三个阶段组成:

1、自我对弈

2、重新训练神经网络

3、评估神经网络

有两个智能体也参与到这个环节中,他们分别为best_player和current_player。

best_player包含执行最佳的神经网络,并且可以用于生成自我对弈的记忆。然后,current_player在这些记忆上重新训练它的神经网络,然后再与best_player对弈。如果它赢了,best_player内部的神经网络被转换为current_player内部的神经网络,然后循环再次启动。

agent.Py——这个文件包含游戏中的一个玩家Agent class

在游戏中,每个玩家都是用自己的神经网络和蒙特卡罗搜索树进行初始化的。

我们需要用模拟的办法运行蒙特卡罗树搜索过程。具体地说,智能体移动到树的叶节点,用它的神经网络对节点进行评估,然后通过树将节点的值返回。

之后,我们还需要用act method多次重复模拟,让智能体理解从当前位置出发的最有利的移动。然后它将最终选择的动作返回到游戏中,以执行动作。

最后,replay method利用以前游戏的记忆,重新训练神经网络。

model.py——这个文件包括residual_cnn类,它定义了如何建立神经网络的实例

2d9877017b073a07e0ff220ee203073433caaafe

用Keras搭建残差卷积网络示例

它采用的是AlphaGoZero论文中浓缩版的神经网络结构——即一个卷积层,接着是许多剩余层,然后分成一个数值和指挥中枢。

可以在config文件中指定卷积筛选器的深度和数量。

Keras库是用来与后台的tensorflow建立网络。

查看个人的卷积滤波器和浓密连接层的神经网络,在run.ipynb笔记本运行以下代码:

current_player.model.viewLayers()

be5cd1d93fcf9ed2f8dc0178caa20748d9863489

神经网络中的卷积核

MCTS.py——这个文件包含节点(Node),边(Edge)和MCTS类,构成了蒙特卡洛树搜索

MCTS类包含了前文提到的 moveToLeaf 和backFill 方法,以及Edge类的实例存储有关每个潜在移动的统计信息。

config.py——这是你设置影响算法的关键参数的地方

4ae4f7113164d3cdec01015a003e20e40cdf5364

调整这些变量会影响运行时间,神经网络的准确性和整体算法的成功。以上参数产生一个高品质的四子连珠选手,但要花很长时间才能做到。为了加快算法的速度,请尝试以下参数。

797052cf8f3a60e64283815ac740adaf02b99b54

funcs.py——包含可以在两个智能体之间进行比赛的playMatches和playMatchesBetweenVersions函数

如果你想挑战之前创建的智能算法,可以运行下面的代码(在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.py——当你运行该算法,所有的模型和存储文件保存在 runfolder的根目录下

稍后要从此检查点重新运行算法,请将运行文件夹传输到run_archive文件夹,并将运行编号附加到文件夹名称。然后,将运行编号,型号版本号和内存版本号输入到initialise.py文件中,对应于run_archive文件夹中相关文件的位置。像往常一样运行算法,然后从这个检查点开始。

memory.py

Memory类的一个实例存储以前游戏的记忆,该算法用于重新训练current_player的神经网络。

loss.py

该文件包含一个自定义损失函数,在传递到交叉熵损失函数之前,屏蔽了来自非法移动的预测。

settings.py

run和run_archive文件夹的位置。

loggers.py

日志文件保存到运行文件夹内的日志文件夹中。

要打开日志记录,请在此文件中将logger_disabled变量的值设置为False。

查看日志文件将帮助你了解该算法的工作原理,并在其“头脑”中查看。 例如,下面是logger.mcts文件中的示例。

0172c1d060f84b2bd37d925050b2f10368bc422f

logger.mcts文件的输出

同样从logger.tourney文件,你可以在评估阶段看到每个移动的概率:

4fc44652a33c0ce673e6efb035fdcb353453c182

logger.tourney文件的输出

训练出的结果让人惊喜

通过几天的训练,得到以下小批量迭代次数与损失的关系图:

6856cf4de4dca0cd313093bc29919922811a3f6b

小批量迭代次数与损失的关系图

最上面的线是策略头中的误差(MCTS移动概率的交叉熵,相对于神经网络的输出)。底部的线是价值头(实际游戏数值和神经网络预测值之间的均方误差)。中间的线是两者的平均值。

显然,神经网络在预测每个游戏状态的值以及可能的下一步移动方面正在变得更好。为了说明这个结果如何变得越来越强大,我让17个参与者组成联赛,从神经网络的第1次迭代到第49次。每一组比赛两次,两个玩家都有机会先玩。

这是最后的排名:

5ebdd310f6e5f1ff8e62c31524732a83cc4ce798

显然,神经网络的最新版本比早期版本更胜一筹,赢得了大部分的游戏。 这也似乎表明学习过程没有达到极限 - 随着训练时间的进一步延长,玩家将会继续变得更强大,学习越来越复杂的策略。

作为一个例子,随着时间的推移,一个神经网络挑选的策略较早的占据了中间列。观察算法的第一个版本与第三十个版本之间的区别:

e9a04862b9a3f17d1f5b5a814c7ac35af31854bc

这是一个很好的策略,因为很多线路都需要中间列 – 尽早占领这一列可以确保你的对手无法利用这一优势。 神经网络已经在没有人类指导下,学到了这一点。

学习其他游戏

在游戏文件中有一个称为“Metasquares” 的game.py文件。其中的X和O用于形成不同大小的正方形。较大的方格意味着要落更多的棋子,当棋盘布满时,落子多的一方获胜。

如果你将Connect4 (四子连珠) 的game.py文件替换成Metasquares的game.py文件,同样算法将会用于学习玩Metasquares游戏。


原文发布时间为:2018-02-22

本文作者:文摘菌

本文来自云栖社区合作伙伴“大数据文摘”,了解相关信息可以关注“大数据文摘”微信公众号

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
2天前
|
缓存 开发者 Python
探索Python中的装饰器:简化和增强你的代码
【10月更文挑战第32天】 在编程的世界中,简洁和效率是永恒的追求。Python提供了一种强大工具——装饰器,它允许我们以声明式的方式修改函数的行为。本文将深入探讨装饰器的概念、用法及其在实际应用中的优势。通过实际代码示例,我们不仅理解装饰器的工作方式,还能学会如何自定义装饰器来满足特定需求。无论你是初学者还是有经验的开发者,这篇文章都将为你揭示装饰器的神秘面纱,并展示如何利用它们简化和增强你的代码库。
|
3天前
|
机器学习/深度学习 自然语言处理 API
如何使用阿里云的语音合成服务(TTS)将文本转换为语音?本文详细介绍了从注册账号、获取密钥到编写Python代码调用TTS服务的全过程
如何使用阿里云的语音合成服务(TTS)将文本转换为语音?本文详细介绍了从注册账号、获取密钥到编写Python代码调用TTS服务的全过程。通过简单的代码示例,展示如何将文本转换为自然流畅的语音,适用于有声阅读、智能客服等场景。
20 3
|
5天前
|
设计模式 缓存 测试技术
Python中的装饰器:功能增强与代码复用的艺术####
本文将深入探讨Python中装饰器的概念、用途及实现方式,通过实例演示其如何为函数或方法添加新功能而不影响原有代码结构,从而提升代码的可读性和可维护性。我们将从基础定义出发,逐步深入到高级应用,揭示装饰器在提高代码复用性方面的强大能力。 ####
|
3天前
|
算法 IDE API
Python编码规范与代码可读性提升策略####
本文探讨了Python编码规范的重要性,并深入分析了如何通过遵循PEP 8等标准来提高代码的可读性和可维护性。文章首先概述了Python编码规范的基本要求,包括命名约定、缩进风格、注释使用等,接着详细阐述了这些规范如何影响代码的理解和维护。此外,文章还提供了一些实用的技巧和建议,帮助开发者在日常开发中更好地应用这些规范,从而编写出更加清晰、简洁且易于理解的Python代码。 ####
|
6天前
|
缓存 测试技术 数据安全/隐私保护
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第29天】本文通过深入浅出的方式,探讨了Python装饰器的概念、使用场景和实现方法。文章不仅介绍了装饰器的基本知识,还通过实例展示了如何利用装饰器优化代码结构,提高代码的可读性和重用性。适合初学者和有一定经验的开发者阅读,旨在帮助读者更好地理解和应用装饰器,提升编程效率。
|
13天前
|
开发者 Python
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第22天】在Python的世界里,装饰器是一个强大的工具,它能够让我们以简洁的方式修改函数的行为,增加额外的功能而不需要重写原有代码。本文将带你了解装饰器的基本概念,并通过实例展示如何一步步构建自己的装饰器,从而让你的代码更加高效、易于维护。
|
10天前
|
算法 测试技术 开发者
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗;代码审查通过检查源代码发现潜在问题,提高代码质量和团队协作效率。本文介绍了一些实用的技巧和工具,帮助开发者提升开发效率。
14 3
|
14天前
|
开发框架 Python
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第20天】在编程的海洋中,简洁与强大是航行的双桨。Python的装饰器,这一高级特性,恰似海风助力,让代码更优雅、功能更强大。本文将带你领略装饰器的奥秘,从基础概念到实际应用,一步步深入其内涵与意义。
|
12天前
|
机器学习/深度学习 缓存 数据挖掘
Python性能优化:提升你的代码效率
【10月更文挑战第22天】 Python性能优化:提升你的代码效率
12 1
|
15天前
|
机器人 Shell Linux
【Azure Bot Service】部署Python ChatBot代码到App Service中
本文介绍了使用Python编写的ChatBot在部署到Azure App Service时遇到的问题及解决方案。主要问题是应用启动失败,错误信息为“Failed to find attribute 'app' in 'app'”。解决步骤包括:1) 修改`app.py`文件,添加`init_func`函数;2) 配置`config.py`,添加与Azure Bot Service认证相关的配置项;3) 设置App Service的启动命令为`python3 -m aiohttp.web -H 0.0.0.0 -P 8000 app:init_func`。

热门文章

最新文章