yyds!用飞桨玩明日方舟
每个游戏玩家都有一个梦,希望自己在虚拟世界中成为万众瞩目、无所不能的英雄。然后…然后…闹钟响了梦醒了,又到了挤地铁上班的时间。
不过,在这个项目中,我将带大家暂时忘却现实的烦恼,用飞桨深度强化学习框架 PARL 来实现这个“英雄梦”!先放效果图:
知识回顾
大家是不是迫不及待了呢?且慢,要实现《明日方舟》游戏的深度强化学习,还是先让我带大家回顾一下深度强化学习算法历史。DQN 是深度强化学习算法开山之作,在经典街机游戏上取得了非常好的效果。它使用了 ReplyMemory 来存储和回放经验,这是 Off-policy 类型算法的常用技巧。但是,DQN 在应对手机游戏时,能力就不够看了。于是我把目光投向了更为强大的算法--- A3C。
A3C 算法与 DQN 不同,它设计了异步多线程的 Actor-Critic,每个 Agent 在自己的线程中运行,然后全局共享学习到的网络参数。这样,每时每刻都能有大量的交互数据,并且这些多线程采集到的数据没有关联性(关联性问题:请参考 DDQN 算法原理)。因此,A3C 算法通过“异步多线程+共享全局参数”达到了和 ReplyMemory 类似的效果。而且,它既有大量数据可以解决训练过程不稳定问题,同时又解决了参数关联性的问题。
在经典算法 PG 中,我们的 Agent 又被称为 Actor,Actor 对于一个特定的任务,都有自己的一个策略π。策略π通常用一个神经网络表示,其参数为θ。从一个特定的状态 State 出发,一直到任务的结束,被称为一个完整的 Episode。在每一步,我们都能获得一个奖励 r,一个完整的任务所获得的最终奖励被称为 R。
如果我们用 Q 函数来预估未来的累积奖励,同时创建一个 Critic 网络来计算 Q 函数值,那么我们就得到了 Actor-Critic 方法。
Q 函数在 A3C 里的主要作用是增加一个基线,使得反馈有正有负,这里的基线通常用状态价值函数 V 来表示。但是,当我们应用这样的方法,则需要同时计算 Q 函数和 V 函数,这并不容易。Q 函数可以用“Step t+1 的 V 函数”加上“从 Step t 到 Step t+1 的 r”来代替。这样,我们就可以得到用 V 来表示的 Q 值计算,我们一般称为 Advantage(优势函数),此时的 Critic 网络变为计算优势函数 A 的网络。
A3C 是 Asynchronous Advantage Actor-Critic 的缩写,中文翻译为异步的优势动作评价算法。其中,Advantage 就是指优势函数 A。因此,从名字这里我们可以解读出来 A3C 实质就是求解πθ网络和 Aπ(s, a)网络。
在 A3C 算法论文中,论文作者对比了四种算法——异步 Sarsa、异步 Q-Learning、DQN 和 A3C。论文发表后,各路算法大神验证一个问题——是异步更新让算法表现优于其他算法?。结果非常有趣:多线程是 A3C 算法快的原因,但是”异步更新“反而是它的缺点。于是,科学家提出同步更新算法 A2C(Advantage Actor-Critic),让它可以更有效利用 CPU 资源。
PS:算法大神照样被打脸,啪啪啪!
在下面部分,我会先对 PARL 库内置的 A2C 算法进行简单解读,这样大家在看项目实践部分时,就能少阅读一些代码。
Learner 这个类有意思的地方是,PARL 库用了 A3C 的名字。原因是 A2C 和 A3C 是同源算法。它们实现上的主要区别是 step 函数(后面会讲到)。
create_actors 这段代码有意思的地方是,它把自己连接到了 XPARL 集群,然后去执行 run_remote_sample。阅读过 DQN 源码的同学应该很好理解,它的意思就是在独立进程运行“取样”。
step 函数 step 函数是 A2C 算法中最重要、独特的函数,作用是同步等待更新操作。因为 A2C 算法会同步等待所有 Agent(Actor)完成一轮训练后,把π网络的参数θ同步上来,更新全局的π网络参数。
Actor 函数注解 @parl.remote_class 表明 Actor 类是在独立的本机进程中执行(因为 A2C 是利用本机多 CPU)。通过两行命令部署了 PARL 分布式集群,Actor 实际是在远程 server 中运行了。
注意,Actor 的 init 方法中保存了 env 数组,用同样的参数实例化了模型,用同样的模型实例化了算法并作为参数传入到了 Agent 中。
大家还要关注的点是,每个 Actor 对应一个 Agent。
sample 函数 Actor 中的 sample 函数会调用 Agent 的 sample 函数和 Agent 的 value 函数来分别更新本地的π网络和 v 网络,最终返回 sample_data 给中心节点。
sample_data 的数据结构:
其中,优势函数的的计算如下:
VectorEnv 函数这个类是 PARL 对 env 环境的封装。我们的模拟真机环境,也采用了同样的定义,主要是为了同时跑多个环境,增加并行计算的效率,如下所示:
模拟器的源数据是由此类中的 step 方法批量返回。
实战编程
1.游戏模拟器编写 &训练新建《明日方舟》模拟器项目:ArKnight_A2C_Simulator 因为《明日方舟》是手机网络游戏,数据生产速度实在太慢了!!!为了提高训练速度,需要自己开发模拟器。用模拟器后速度可提升 50-100 倍。
修改 Learner 的初始化方法:
定义新的 env.py:
修改 Actor:
定义训练用的模拟环境:
在模拟器中经过大约 10 万个 steps,模型的 loss 就收敛了。
2.编写状态推理引擎新建项目 ARKNIGHT_CLASSIFY,使用残差神经网络对《明日方舟》中的主要游戏界面做了预定义。利用这个引擎,在真机部署的时候可以推断出当前游戏的 state,用于计算 reward 和 game over 这两个重要参数。
3.评估强化学习模型在深度强化学习中,效果评估非常重要,因为我们要知道算法从数据中学到了什么?我们在第一步中得到了模型,在第二步中得到了真机环境下的 reward 和 game over 函数。那么我们就要在真机环境中去测试。
可以看到,我只用了 2 步,算法就成功达到了设定的终止状态[965]。新建部署项目 ArKnight_A2C,把模型导入,效果如下:
4.模型和状态推理引擎部署到真机定义真机环境:
这里的游戏状态推断引擎,就是 ARKNIGHT_CLASSIFY 项目输出的推理模型。有了状态的推理值,代码中的 reward 和 game over 就可以和真机环境匹配上。同时,用 AdbUtil 类来执行真实动作,就可以操作真机执行算法动作。
在这个文章中,我给大家展示了如何构建明日方舟的交互环境,以及如何通过 PARL 快速调用 A3C 算法实现并行训练,整体实现起来简单易懂。欢迎大家加入百度飞桨讨论群,跟我交流想法。
看到这儿,大家是不是迫不及待地想要自己动手尝试!
“英雄们”,快用飞桨去实现你们的美梦吧,yyds(永远滴神)!
欲知详情,请戳 PARL 开源链接:
https://github.com/PaddlePaddle/PARL
如果您想详细了解更多飞桨的相关内容,请参阅以下文档。
·飞桨官网地址·
https://www.paddlepaddle.org.cn/
·飞桨开源框架项目地址·
GitHub: https://github.com/PaddlePaddle/Paddle
Gitee: https://gitee.com/paddlepaddle/Paddle
·飞桨深度强化学习框架项目地址·
版权声明: 本文为 InfoQ 作者【百度大脑】的原创文章。
原文链接:【http://xie.infoq.cn/article/4fa28a5ece504bec89800fb50】。文章转载请联系作者。
评论