0
雷锋网 AI 科技评论按:本文是 otoro.net 的系列技术博客之一,以通俗可视化的方法讲解了进化策略(Evolution Strategies)中的诸多概念。本篇介绍了如何使用进化策略来寻找前馈神经网络智能代理的策略,以执行由 gym 环境接口定义的各式各样的连续控制强化学习任务。前一篇参见《进化策略入门:最优化问题的另一种视角》。雷锋网 AI 科技评论编译。
代码传送门:GitHub
在上一篇文章中,我已经介绍过了一些可以用于优化函数参数而不用显式地计算梯度的进化策略(Evolution strategies, ES)算法。这些算法可以用于解决强化学习(Reinforcement learning, RL)问题,从而帮助神经网络智能体(Neural network agent)找到合适的模型参数。在本文中,我将探讨如何将进化策略应用于某一些增强学习问题中,并重点介绍一些方法,以帮助我们找到更加稳定和健壮的策略。
虽然强化学习算法需要在每个时间步都给予智能代理一个奖励信号,但是进化策略算法只关心智能体在特定环境中展示(rollout)阶段结束之后所获得的最终累积奖励。在许多问题中,我们只知道任务结束时的结果,比如智能体是赢还是输、机器人手臂是否拿起了物体、或者智能体是否存活了下来,而这些方面的问题都是进化策略可能优于传统强化学习的点。下面是一段伪代码,它将智能体的展示阶段封装在一个 OpenAI Gym 环境中,在这个环境下我们只关心累积奖励:
def rollout(agent, env):
obs = env.reset()
done = False
total_reward = 0
while not done:
a = agent.get_action(obs)
obs, reward, done = env.step(a)
total_reward += reward
return total_reward
我们可以将 rollout 定义成目标函数,因为目标函数可以将智能代理的模型参数映射到最合适的分数,然后正如上一篇文章所讲解的,再使用一个进化策略求解器去找到一组合适的模型参数:
env = gym.make('worlddomination-v0')
# use our favourite ES
solver = EvolutionStrategy()
while True:
# ask the ES to give set of params
solutions = solver.ask()
# create array to hold the results
fitlist = np.zeros(solver.popsize)
# evaluate for each given solution
for i in range(solver.popsize):
# init the agent with a solution
agent = Agent(solutions[i])
# rollout env with this agent
fitlist[i] = rollout(agent, env)
# give scores results back to ES
solver.tell(fitness_list)
# get best param & fitness from ES
bestsol, bestfit = solver.result()
# see if our task is solved
if bestfit > MY_REQUIREMENT:
break
我们的智能体将环境给予它的观察结果作为输入,然后在环境内部展示期间的每个时间步输出一个动作。我们可以根据需要对代理进行建模,并使用硬编码规则、决策树、线性函数以及递归神经网络中的方法。在这篇文章中,我使用一个带有两个隐含层的简单前馈网络,将智能体的观测结果(向量 x)直接映射到相应的动作(向量 y):
其中的激活函数 fh、fout 可以是 tanh、sigmoid、relu 或是其它你想要使用的函数。而对我而言,我喜欢使用 tanh。对于输出层而言,有时我们可能希望 fout 是一个不含非线性变换的传递函数。如果我们将所有的权重和偏置项连接成一个向量 W,我们可以看到上述神经网络是一个确定性函数 y=F(x, W),然后我们可以使用进化策略,结合之前介绍的搜索循环来找到一个解决方案 W。
但是如果我们不希望我们的智能体是确定性的呢?对于特定的某些任务,即使像石头剪刀布一般简单,最优策略也是一种随机行为,所以我们希望智能代理能够学习到一种随机策略。将 y=F(x, W) 转换为随机策略的一种方法是使得 W 随机。模型中的每个参数 wi ∈ W 都是符合正态分布的随机变量 N(μi, σi)。
这种随机网络被称为贝叶斯神经网络。贝叶斯神经网络是一个权重带有先验分布的神经网络。在这种情况下,我们想要求解的模型参数是 μ 和 σ 的向量集,而不是权重 W。在网络每一次前向传播的过程中,生成一个全新的符合 N(μ, σ I) 分布的 W。文献中有许多有趣的工作将贝叶斯网络应用于许多问题中,并解决了许多训练网络的挑战。通过设置解空间为 μ 和 σ,而不是 W,进化策略也可以用于直接找到随机策略的解。
随机策略网络在强化学习的研究中也非常流行。例如,在近端策略优化(PPO)算法中,最后一层是 μ 和 σ 的参数集合,并且动作是从 N(μ, σ I) 中进行采样的。为参数增加噪音的操作也被称为鼓励智能代理探索环境并逃离局部最优。我发现对于需要智能代理进行探索的许多任务,我们并不需要整个 W 都是随机的,而仅仅只有偏置项满足随机性就足够了。对于具有挑战性的运动任务,例如 roboschool 环境中的运动任务,我通常使用进化策略来找到一个随机策略,其中只有偏置项的参数才符合正态分布。
我发现健壮策略研究是另一个可以应用进化策略算法的领域。我想控制数据效率之间的平衡,以及该策略在多个随机实验中的健壮程度。为了证明这一点,我在一个叫做 BipedalWalkerHardcore-v2 的环境中测试了进化策略,该环境是由 Oleg Klimov 使用 Box2D 物理引擎创建的,该引擎曾被用于开发《愤怒的小鸟》。
我们的智能代理解决了 BipedalWalkerHardcore-v2
在这种情况下,我们的智能代理必须学习到一个策略,以实现在有限时间内能够通过一个随机生成的地形还不摔倒。这里涉及 24 个输入,其中包括有 10 个雷达激光传感器、角度参数和接触器参数。智能体不知道自己在地图中的绝对坐标。动作空间是 4 个连续值,控制着 4 台电机的转矩。总奖励的计算则基于智能体走过的总路程。一般情况下,如果智能体顺利走完整个地图,它将得到 300多分。此外根据全程施加的电机扭矩情况,还要再减去少量的分数,因此这样使得能量也成为了一个限制条件。
BipedalWalkerHardcore-v2 将任务完成定义为在超过 100 次连续的随机试验中,智能代理的平均分达到 300 多。虽然使用强化学习算法训练智能体成功穿越地图一两次相对容易,但是要保证智能代理能始终如一且高效完成却是很困难的,这使得该任务成为一项很有趣的挑战。据我所知,到 2017 年 10 月为止,我的智能体是唯一已知能解决此问题的方案。
由于地形图是针对每个实验随机生成的,因此有时候地形也许会非常简单,而有时候地形也可能非常复杂。我们并不希望我们的自然选择过程允许那些弱策略的智能体(通过简单的地形地图)进入下一代。另外我们也希望给那些拥有好策略的智能代理一个救赎的机会。所以我最终所做的是定义一个智能体分组(episode),作为 16 次随机展示的平均值,并使用 16 次展示的累积奖励平均值作为其最适分数(Fitness score)。
另一种对待这种事件的方法是,即使我们正在对智能体进行超过 100 次试验的测试,我们通常会在单次试验中对其进行训练,所以测试任务和我们正在优化的训练任务并不一样。通过在随机环境中对所有智能代理进行多次平均,我们缩小了训练集和测试集之间的差距。如果我们可以对训练集进行过度训练,那么也可能会对测试集进行过度训练,因为这在强化学习中是一件好事情。
当然,我们算法的数据效率比现在差 16 倍,但最终的策略却要健壮得多。当我在超过 100 次连续随机试验中测试最终策略时,我顺利通过了这个环境,并得到了一个超过 300 点的平均分数。如果没有这种平均方法,最好的智能体在超过 100 次试验中智能的平均分数大约只有 220 到 230。据我所知,截止 2017 年 10 月,这是解决该环境问题的第一个解决方案。
我还使用了 PPO,这是一种针对强化学习的最先进的策略梯度算法,然后我试图将其进行调整以最佳化应用到这项任务中。最后,我在 100 次随机试验中只能让 PPO 取得大约 240 到 250 的平均成绩。但是我确信将来其他人可以使用 PPO 或其它强化学习算法来解决这个环境挑战。
后续更新(2018 年 1 月):
dgriff777 能够使用带有 4 个堆栈帧的 A3C+LSTM 连续版本作为输入来训练 BipedalWalkerHardcore-v2,以在超过 100 次随机试验中取得 300 分的成绩。他在 GitHub 上开源了这个模型,由 pytorch 进行编写。
在现实世界中我们需要足够安全的策略,所以控制数据效率和策略健壮性之间的权衡能力是非常有用和重要的。理论而言,如果有足够的计算能力,我们甚至可以对所需的 100 次展示进行平均,并将我们的双足步行者直接优化到满足需求。专业工程师通常要求他们的设计满足特定的质量保证并满足某些安全因素。当我们训练智能代理去学习那些可能影响到现实世界的策略时,我们需要考虑到这些安全因素。
以下是进化策略发现的一些其它解决方案:
我还使用具有高初始噪音参数的随机策略网络对智能体进行训练,因此智能体可以在任何地方看到噪音,以至于它的行为也有点混乱。它导致了智能体在没有对其输入和输出信息的准确性进行确认的情况下也依然学习任务(这个智能体无法获得 300 以上的分数):
我还试图在简化的 Kuka 机器人手臂抓取任务中使用带有该项平均技术的进化策略。这个环境在 pybullet 环境中可以获得。仿真中使用的 Kuka 模型被设计为类似于真正的 Kuka 机器人手臂。在这个简化的任务中,智能体被告知了物体的坐标。
更高级的强化学习环境可能需要智能体直接从像素输入中推理出一个动作,但是在原则上,我们可以将此简化版模型与预训练好的卷积网络组合在一起,通过卷积网络给出坐标的估计值。
使用随机策略训练的机器人手臂抓取任务
如果智能体成功抓取物体,它将获得 10000 分,否则为 0。然后再扣除一些能源消耗的分数。通过对 16 个随机试验的稀疏奖励进行平均,我们可以让进化策略对健壮性进行优化。然而最终,我得到确定性策略或者随机策略只能在 70% 至 75% 的时间内抓取物体。这里还有提升的空间。
学习同时执行多项复杂任务使得我们能更好地执行单一任务。例如,少林寺的僧侣站在树桩上举重可以使得他们在没有举重的情况下更好地维持平衡。学习如何在山上以 80 英里/小时的速度驾驶汽车,并且还要保证不把杯子里的水洒出来,这会使得司机成为一个更好的非法街头赛车手。我们还可以训练智能代理去执行多项任务,以使得它们学习到更加稳定的策略。
最近关于自我控制(Self-playing)智能体的研究工作表明,学习诸如 Sumo 摔跤(需要许多技巧的运动)等艰巨任务的智能代理也能用于执行更简单的任务,例如迎着风行走,而不需要额外的训练。Erwin Coumans 最近尝试让 Minitaur 在上方放着一只玩具鸭的情况下学会行走。如果鸭子掉下来,Minitaur 也就失败了,其中所蕴含的想法是期望这些类型的任务增强能够有助于将学习策略从模拟转移到真正的 Minitaur。我取用了他的一个例子,并尝试使用进化策略训练 Minitaur 和玩具鸭子的组合。
pybullet 中的 Minitaur 模型旨在模仿真实的物理 Minitaur。然而,在完美的模拟环境下训练出来的策略往往不适用于真实世界。它甚至无法泛化到模拟环境内部的小小任务增强。例如,在上图中有一个 Minitaur 被训练用于朝前走(使用 CMA-ES),但是我们看到,当把一只鸭子放在它上面的时候,这个策略并不总是能够保持鸭子不掉而走出房间。
额外把鸭子放到 Minitaur 上的时候,从单纯的步行任务中学到的策略在某种程度上依然可以发挥作用,这也意味着添加玩具鸭子并没有增加太多的难度。玩具鸭子有一个较为平稳的底部,所以 Minitaur 不会让鸭子从背部脱落。我试图用一个球去代替鸭子,从而让任务变得更加困难。
然而,用球代替鸭子并不会立即产生稳定的平衡策略。相反,CMA-ES 发现了一项策略,首先将球滑入其腿部形成的孔中,然后将球带入该孔内,从而以取巧的方式把球带出了房间。这里学到的教训是,一个目标驱动(Objective-driven)的搜索算法将学会利用环境中的任何设计缺陷,并利用它们以实现自己的目标。
在将球缩小之后,CMA-ES 能够找到一个随机策略,它能够同时实现前行和保持平衡。这项策略也可以转移到更容易的鸭子任务中。在未来,我希望这类任务增强技术对于真实机器人的迁移学习能发挥重要作用。
进化策略最大的卖点在于,可以使用在 CPU 不同核心上的不同线程或者甚至是不同的机器来运行多个工作器,以轻松实现并行化。Python 的多重处理机制使得启动并行进程变得简单。我更喜欢在 mpi4py 中使用消息传递接口(MPI)为每个作业启动单独的 python 进程。这让我们可以绕过全局解释器锁的限制,并且让给我确信每个进程都有自己的沙盒化 numpy 以及 gym 实例,这一点对于播种随机数生成器非常重要。
在各式各样的 roboschool 任务中,智能代理借助 estool 实现演进
我实现了一个名为 estool 的简单工具,它使用前一篇文章中介绍的 es.py 库来训练简单的前馈策略网络,以执行用 gym 接口编写的连续控制强化学习任务。我已经使用 estool 工具轻松训练了前面所述的所有实验,以及 gym 和 roboschool 内部提供的各种各样其它的连续控制任务。estool 使用 MPI 进行分布式处理,因此不需要太多工作就可以将工作器分配到多台机器上。
除了 gym 和 roboschool 自带的环境之外,estool 还适用于多数 pybullet gym 环境。通过修改现有的环境来构建自定义 pybullet 环境也很容易。例如,我可以毫不费力地在球场环境中制作 Minitaur(在该仓库的 custom_envs 目录下),并且也能够对环境进行修改以使得更加容易实现新想法。另外如果你想将其它软件包(例如 ROS 或者 Blender)的 3D 模型纳入进来,你可以尝试构建新的有趣的 pybullet 环境,为其他人提供新的挑战。
作为近期迁移学习研究中令人兴奋的成果,pybullet 中的许多模型和环境,例如 Kuka 机器人手臂和 Minitaur,都在最大的程度上模拟了真实机器人。事实上,这些最新的尖端研究论文(1,2,3,4)中有很多都使用 pybullet 来进行迁移学习实验。
因此你不需要购买昂贵的 Minitaur 或 Kuka 机器人手臂来尝试从仿真到真实的实验。pybullet 内部有一个赛车模型,它是参照 MIT 开源赛车硬件工具包进行建模的。甚至还有一个 pybullet 环境,可以将虚拟摄像机安装到虚拟赛车上,为智能代理提供虚拟屏幕的像素作为观察结果输入。
让我们首先尝试更简单的版本,赛车只需要学习一个跟踪巨型球移动的策略。在 RacecarBulletEnv-v0 环境中,智能代理获取球的相对坐标作为输入,并输出控制电机速度和转向方向的连续动作。该任务非常简单,在 2014 款 Macbook Pro(8 核 CPU)上只需要花费 5 分钟(50 次迭代)即可完成训练。使用 estool,下面的命令将启动一个含有 8 进程的训练程序,每个进程负责 4 项作业,这样总共就有 32 个工作器,然后使用 CMA-ES 来演进策略:
python train.py bullet_racecar -o cma -n 8 -t 4
训练的进度以及模型参数将被保存在日志子目录中。我们可以运行这个命令来可视化环境中智能代理所找到的最佳策略:
python model.py bullet_racecar log/bullet_racecar.cma.1.32.best.json
pybullet 赛车环境,基于 MIT 赛车实现
在这个仿真中,我们可以使用鼠标来移动圆球,如果有需要的话,甚至也可以用来移动赛车。
IPython notebook plot_training_progress.ipynb 可用于可视化赛车智能代理每次迭代的训练记录。每次迭代中,我们都可以获得最高分、最低分、以及所有赛车的平均分数。
标准运动任务类似于 roboschool 中的运动任务,例如 Inverted Pendulum、Hopper、Walker、HalfCheetah、Ant 和 Humanoid 也可以在 pybullet 中使用。我发现了一个策略,在 pybullet 的蚂蚁任务中获得了 3000 分,我是使用 PEPG 在智能代理数为 256 的多核机器上花费几个小时完成训练的。
python train.py bullet_ant -o pepg -n 64 -t 4
AntBulletEnv 的一个样例展示。我们还可以使用 gym.wrappers.Monitor 将展示结果保存成一个 mp4 格式的视频
在本文中,我讨论了如何使用进化策略来寻找前馈神经网络智能体的策略,以执行由 gym 环境接口定义的各式各样的连续控制强化学习任务。我介绍了 estool,它允许我使用 MPI 框架在分布式处理环境中快速尝试不同配置的进化策略算法。
到目前为止,我只讨论了通过让智能体在环境中反复试验来训练智能代理学习策略的方法。这种从头开始训练的形式被称为无模型强化学习。在下一篇文章中,我会更多地讨论基于模型的学习,我们的智能体将学习利用以前学习过的模型来完成一个给定任务。另外我仍然会采用进化策略。
“Fires of a Revolution” Incredible Fast Piano Music (EPIC)
A Visual Guide to Evolution Strategies
Stable or Robust? What’s the Difference?
Evolution Strategies as a Scalable Alternative to Reinforcement Learning
Edward, A library for probabilistic modeling, inference, and criticism
History of Bayesian Neural Networks
Emergent Complexity via Multi-Agent Competition
Via Evolving Stable Strategies,雷锋网 AI 科技评论编译
雷峰网原创文章,未经授权禁止转载。详情见转载须知。