如何使用Python构建自己的MuZero AI

如何使用Python构建自己的MuZero AI

作者:David Foster

发表时间:2019年12月2日

原文连接:

MuZero: The Walkthrough(Part1/3),https://medium.com/applied-data-science/how-to-build-your-own-muzero-in-python-f77d5718061a

MuZero: The Walkthrough(Part2/3),https://medium.com/applied-data-science/how-to-build-your-own-deepmind-muzero-in-python-part-2-3-f99dad7a7ad

MuZero: The Walkthrough(Part3/3),https://medium.com/applied-data-science/how-to-build-your-own-deepmind-muzero-in-python-part-3-3-ccea6b03538b

如果你想了解最复杂的人工智能系统是如何工作的,那么,你来对地方了!

在这篇由三部分组成的系列中(翻译后合并为一个长篇),我们将探讨DeepMind发布的MuZero模型内部工作机制,MuZero是AlphaZero年轻的弟弟,但甚至更令人印象深刻。

还可以查看我的最新帖子,关于如何训练多人棋盘游戏的强化学习智能体,使用自我对弈!

我们将研究一下MuZero论文附带的伪代码——所以,沏一杯茶,找张舒服的椅子,开始吧。

α \alpha α

到目前为止的故事…

2019年11月19日,DeepMind向全球发布了最新的基于模型的强化学习算法——MuZero(译者:2012年12月23日,论文被《自然》收录)。

从2016年的AlphaGo论文开始,这已经是DeepMind深度强化学习不断突破的一系列论文中的第四篇。

要阅读从AlphaGo到AlphaZero的全部历史,请查看我以前的博客。

AlphaZero被誉为是一种通用的算法,它可以在没有任何人类专家先验知识的情况下快速地做好某件事。

那么,现在呢?

μ \mu μ

MuZero:用学习模型规划玩转雅达利、围棋、国际象棋和日本将棋。

MuZero跨出了终极的一步,MuZero拒不接受人类玩家的策略,甚至也不接受游戏规则。

换句话说,对于国际象棋,AlphaZero面对的挑战是:

学习如何自己与自己玩好这个游戏,这里有规则手册,解释每个棋子如何移动,哪些移动是合法的。它还告诉你如何判断一个棋局已经被将死(或者是平局)。

而MuZero面对的挑战是:

学会如何自己与自己玩好这个游戏,我会告诉你当前棋局什么动作是合规的,什么时候某一方赢了(或是平局),但我不会告诉你游戏中的整体规则。

因此,除了制定能赢的策略,MuZero还必须开发自己的的环境动力学模型,以便能够理解其选择的含义和未来规划。

想象一下,在一场从未被提前告知规则的比赛中,你试图玩得比世界冠军更好。MuZero恰恰做到了这一点!

在这篇文章中,我们将详细介绍MuZero是如何实现这个惊人壮举的。

MuZero伪代码

随MuZero论文,DeepMind还发布了Python伪代码,详细描述了算法每个部分之间的相互作用关系。

在本文中,我们将把其中的类和函数掰开了揉碎了,按逻辑摆放,并解释每个部分的功能和原理。我们假设MuZero正在学习下国际象棋,但这个过程对于任何游戏起始都一样,只是参数不同而已。全部伪代码都来自DeepMind开源伪代码

让我们从对整个过程的描述开始,起点是入口函数muzero
在这里插入图片描述
MuZero自我博弈(self-play)和训练(training)过程概述

def muzero(config: MuZeroConfig):
  storage = SharedStorage()
  replay_buffer = ReplayBuffer(config)

  for _ in range(config.num_actors):
    launch_job(run_selfplay, config, storage, replay_buffer)

  train_network(config, storage, replay_buffer)

  return storage.latest_network()

入口函数muzero的参数是一个MuZeroConfig对象,该对象存放了重要的运行参数,例如action_space_sizenum_actors(要同时启动的游戏总数)。在其它函数中遇到这些参数时,我们再详细地介绍它们。

在较高的层次上,MuZero算法有两个独立的部分:自我博弈self-play(创建游戏数据)和训练training(不断改进神经网络)。算法的这两个部分都可以访问SharedStorageReplayBuffer对象,并分别保存神经网络和游戏数据。

共享存储和回放缓冲区

SharedStorage对象包含用于保存神经网络和从存储中获取最新神经网络的方法。

class SharedStorage(object):

  def __init__(self):
    self._networks = {
   }

  def latest_network(self) -> Network:
    if self._networks:
      return self._networks[max(self._networks.keys())]
    else:
      # policy -> uniform, value -> 0, reward -> 0
      return make_uniform_network()

  def save_network(self, step: int, network: Network):
    self._networks[step] = network

我们还需要一个ReplayBuffer来存储生成的游戏数据。其形式如下:

class ReplayBuffer(object):

  def __init__(self, config: MuZeroConfig):
    self.window_size = config.window_size
    self.batch_size = config.batch_size
    self.buffer = []

  def save_game(self, game):
    if len(self.buffer) > self.window_size:
      self.buffer.pop(0)
    self.buffer.append(game)
  ...

注意window_size参数是回放缓冲区中能保存的游戏最大数量。在MuZero中,设置为最近生成的1,000,000个游戏。

自我博弈(self-play)

在创建了共享存储和回放缓冲区之后,MuZero启动了num_actors个独立运行的并行游戏环境。国际象棋的num_actors设为3000。每个游戏环境都运行一个函数run_selfplay,从共享存储中取出最新版本网络参数,用它玩游戏play_game,并将游戏数据保存到回放缓冲区。

# Each self-play job is independent of all others; it takes the latest network
# snapshot, produces a game and makes it available to the training job by
# writing it to a shared replay buffer.
def run_selfplay(config: MuZeroConfig, storage: SharedStorage, replay_buffer: ReplayBuffer):
  while True:
    network = storage.latest_network()
    game = play_game(config, network)
    replay_buffer.save_game(game)

总之,MuZero不停地进行着成千上万次游戏,将这些游戏保存到一个回放缓冲区,然后根据这些游戏数据不断地训练自己。到目前为止,这与AlphaZero没什么不同。

我们将讨论AlphaZero和MuZero之间的关键区别——为什么MuZero有三个神经网络,而AlphaZero只有一个?

MuZero的3个神经网络

AlphaZero和MuZero都采用一种称为蒙特卡罗树搜索(MCTS)的技术来选择下一步动作的最佳方案。

这个想法是:为了选择下一步动作的最佳方案,就要“播放”从当前位置到未来可能出现的各种场景,然后用神经网络评估它们的价值,并选择未来预期价值最大化的动作。这似乎是我们人类下棋时脑子里面想的事,人工智能体也设计成利用这个技巧。

但是,这里有个问题,MuZero并不知道游戏规则,也就无从知晓一个给定的动作会如何影响游戏状态,所以它无法想象未来MCTS中的场景。它甚至不知道如何从给定的棋局中判断出下一步哪些动作是合法的,或者哪一方赢了。

MuZero论文中惊人的进展就是证明了这并不是问题。MuZero在自己的想象中创建了一个环境动力学模型,并在这个模型中进行优化学习如何玩游戏。

下图显示了AlphaZero和MuZero中MCTS进程之间的比较:

AlphaZero只有一个神经网络(预测predict),而MuZero则需要三个神经网络(预测predict动力学dynamics表征representation

AlphaZero 预测(predict) 神经网络f的工作是预测给定游戏状态下的策略p和价值v。该策略p是全部动作的概率分布,价值v是对未来奖励估计的单一数值。每次MCTS走到一个未探测的叶节点时,都会进行这种预测,这样就可以立即为新棋局分配一个估计价值,并为后续每个动作分配概率。这些值被反向写到树上,直到根节点,这样经过多次模拟,在探索了大量未来不同可能性之后,根节点对当前状态下未来价值变得胸有成竹。

MuZero同样有一个 预测(predict) 神经网络f,但它所依据的“游戏状态”是一个隐藏表征,MuZero学习如何通过 动力学(dynamics) 神经网络g生成隐藏表征。动力学网络获取当前隐藏状态s和动作a,输出奖励r和新状态。注意,在AlphaZero中,MCTS树的状态转移是向环境要;而MuZero没那么奢侈,所以需要建立自己的的环境动力学模型!

最后,为了将当前观测到的游戏状态映射到初始表征,MuZero使用了第三种**表征(representation)**神经网络h

因此,MuZero需要两个推理函数,以便通过MCTS树进行预测:

  • initial_inference为当前状态的初始推理,也就是h(表征)后面接f(预测)。

  • recurrent_inference为沿着MCTS树,在状态之间转移的递归推演,g(动力学)后接f(预测)。


MuZero中的两类推演

虽然伪代码中没有提供精确的模型,但论文中给出了详细的描述。

class NetworkOutput(typing.NamedTuple):
  value: float
  reward: float
  policy_logits: Dict[Action, float]
  hidden_state: List[float]

class Network(object):

  def initial_inference(self, image) -> NetworkOutput:
    # r
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值