DeepRL · 2021年09月08日

ElegantRL: 基于PyTorch的轻量-高效-稳定的深度强化学习框架

一句话概括强化学习(RL):Agent不停地与环境互动,通过反复尝试的方式进行学习,在一定的不确定性下做出决策,最终达到exploration (尝试新的可能) 与exploitation (利用旧的知识) 之间的平衡。

「ElegantRL:小雅」的特点

深度强化学习(DRL)在解决对人类有挑战性的多个现实问题中展示了巨大的潜力,例如自动驾驶,游戏竞技,自然语言处理(NLP)以及金融交易等。各种各样的深度强化学习算法及应用正在不断涌现。ElegantRL能够帮助研究人员和从业者更便捷地“设计、开发和部署”深度强化学习技术。ElegantRL的elegant体现在以下几个方面

  • 轻量:tutorial版将一直维持在1000行以内,并保持与正式版拥有相同的API。
  • 高效:性能向Ray RLlib靠拢,支持多GPU训练。
  • 稳定:比Stable Baseline 3更加稳定。

ElegantRL支持离散动作空间以及连续动作空间下的常用DRL算法。并且提供了十分友好的教程。

在ElegantRL中,我们基于Actor-Critic框架搭建深度强化学习算法,每一个Agent(即DRL算法)由Actor网络和Critic网络组成。利用ElegantRL完整简洁的代码结构,用户可以非常轻松地开发自己的Agent。代码已上传至:

https://github.com/AI4Finance-Foundation/ElegantRL

总述:文件结构和函数

image.png

ElegantRL的“小”最直观的体现就是:整个库只有3个文件,net.py, agent.py, run.py。再加上一个env.py 用于存放与训练环境有关的代码。我们很开心能在Tutorial版用少于1000行的代码实现了一个完整的DRL库。请注意,Tutorial版的ElegantRL只是用来学习的,它可以快速地让人了解一个DRL库最为核心的结构。如果想要进一步把ElegantRL当做生产工具,则需要使用正式版的ElegantRL,它的文件结构和函数保持了与 Tutorial版的统一,降低了学习成本。

ElegantRL的文件结构如图1所示:

  • env.py:包含与Agent互动的环境

    • 包括PreprocessEnv类,可用于对gym的环境进行改动。
    • 包括自主开发的股票交易环境作为用户自定义环境的例子。
  • net.py:包含三种类型的网络,每个类型均包括一个网络基类,以便于针对不同算法进行继承与派生。

    • Q网络
    • Actor网络
    • Critic网络
  • agent.py:包含不同用于算法的Agent。
  • run.py:提供用于训练和测试的基本函数。

    • 参数初始化
    • 训练
    • 评测

我们从一个较高的层面描述这些文件之间的关系。首先,初始化env.py文件中的环境和agent.py文件中的Agent类。Agent类既包含了net.py文件中的网络,又与env.py文件中的环境进行互动。在run.py中进行的每一步训练中,Agent都会与环境进行互动,产生transitions并将其存入回放缓存(Replay Buffer)。之后,Agent从Replay Buffer中获取数据来更新它的网络。每隔一段时间,都会有一个评测器(Evaluator)来评测策略的得分,并保存表现好的策略。我们也提供了“demo.py”文件作为示例,可以帮助用户更好地理解这个过程。

网络类的集合 net.py

net.py 文件存放了算法库会使用到的4类神经网络:

'''Q 网络'''
class QNet(nn.Module):
class QNetDuel(nn.Module): 
class QNetTwin(nn.Module):
class QNetTwinDuel(nn.Module):


'''Policy 网络(Actor)'''
class Actor(nn.Module):
class ActorPPO(nn.Module):
class ActorSAC(nn.Module):

'''Value 网络(Critic)'''
class Critic(nn.Module):
class CriticAdv(nn.Module): 
class CriticTwin(nn.Module):

'''参数共享 网络(Shared)'''
class SharedDPG(nn.Module):
class SharedSPG(nn.Module): 
class SharedPPO(nn.Module):

将神经网络单独存放到一个文件,能为使用者微调算法提供便利。这种模式把深度学习的网络与强化学习隔开,提高了代码的可读性。我们提供两个实用的例子:

1.把图片作为state输入神经网络时,只需要在 net.py 将全连接层修改为卷积层即可,我们提供了这个例子,当网络检测到输入的张量是图片时,会自动启用卷积网络。

2.对于高维度状态空间的任务(high-dimensional task),共享网络的参数能明显提升RL算法性能。我们也提供了共享不同算法的网络参数的例子。

DRL算法的构建 agent.py

agent.py存放了不同的DRL算法。在这一部分,我们将分别描述DQN系列算法和DDPG系列算法。我们将会发现ElegantRL中每一个DRL算法的Agent都继承自它的基类。

DQN系列中的Agent类:

class AgentDQN:
class AgentDuelingDQN(AgentDQN):
class AgentDoubleDQN(AgentDQN):
class AgentD3QN(AgentDoubleDQN):

image.png

如图2所示,ElengtRL中DQN系列Agent的继承层级关系为:

  • AgentDQN:标准的DQN Agent。
  • AgentDoubleDQN:为了减少过高估计而包含两个Q网络的Double-DQN Agent,继承自AgentDQN。
  • AgentDuelingDQN:采用不同的Q值计算方式的DQN Agent,继承自AgentDQN。
  • AgentD3QN:AgentDoubleDQN和AgentDuelingDQN的结合,继承自 AgentDoubleDQN。

DDPG系列中的Agent类:

class AgentBase:
class AgentDDPG(AgentBase):
class AgentTD3(AgentDDPG):
class AgentPPO(AgentBase):
class AgentSAC(AgentBase):
class AgentModSAC(AgentSAC):
class AgentSharedAC(AgentBase):
class AgentSharedSAC(AgentBase):
class AgentSharedPPO(AgentBase):

image.png

如图3所示,ElegantRL中DDPG系列的继承层级关系为

  • AgentBase:所有A-C框架下Agent的基类,包括所有Agent共有的参数。
  • AgentDDPG:DDPG Agent,继承自AgentBase。
  • AgentTD3:采用新的更新方式的TD3 Agent,继承自AgentDDPG

在构建DRL算法的Agent时,采用的这种层级结构极大地提升了ElegantRL的轻量性和高效性。当然,用户也可以按照类似的方式构建自己的Agent。例如,我们使用很短短几行代码,对原版的SAC代码进行改良,得到了训练更快更稳定的ModSAC算法(Modify SAC)。在没有对多GPU模块进行修改的情况下,改良后的ModSAC算法也可以使用多GPU进行训练。

从根本上来说,每一个Agent都由两大基本功能构成,探索环境和更新网络。

  • 探索环境(explore_env):Agent利用它的网络与环境互动,在此过程中产生用于训练网络的数据。
  • 更新网络(update_net):Agent从Replay Buffer中获取一批transitions,并利用这些数据通过反向传播来更新网络

从数据流的角度可以描述为图4的形式:

image.png
经验回放缓存将极大地影响的DRL库的训练速度。我们专门根据同策略算法(on-policy)和异策略算法(off-policy)的特点,分别对 ReplayBuffer 进行了优化:https://zhuanlan.zhihu.com/p/103605702

回放缓存 Replay Buffer:

class ReplayBuffer:
class ReplayBufferMP:

训练流程 run.py:

训练一个DRL Agent包含两大步:

  • 初始化:
 args = Arguments(): 超参数集合
    env = PreprocessEnv():创建(gym)环境。
    agent = agent.XXX:基于算法创建Agent。
    evaluator = Evaluator():用于评测并保存模型。
    buffer = ReplayBuffer():.回放缓存。

通过一个while循环来控制训练过程,这个while循环只有当达到某些特定条件时才会终止,比如获得目标分数,达到最大步数或人为终止。

agent.explore_env(...):Agent在目标步数(target step)内探索环境,产生transitions并将其保存至回放缓存(Replay Buffer)中。
agent.update_net(...):Agent根据回放缓存(Replay Buffer)中的一批数据来更新网络参数。
evaluator.evaluate_save(...):评测Agent的表现,并保存具有最高得分的模型参数。 

效果展示:BipedalWalker-v3

BipedalWalker-v3是机器人研究中的一个经典任务:训练一个双足机器人尽快向前移动,同时消耗更少能量。由于它是一项连续动作空间下的简单任务,多数深度强化学习算法都能达到目标分数。我们提供这个环境供使用者快速体验算法。

另外,在此我们想要特别说明,每个DRL算法都有它的适用场景,并且要在合适的超参数设定下使用高质量的代码才能展现出它的实力。例如在此任务下,SAC算法在超参数合适、且代码实现高质量的情况下可以通关;而PPO算法需要很大的采样数量(甚至要接近显存极限)才能通关。

接下来我们将展示如何利用ElegantRL一步一步训练能通关BipedalWalker-v3的深度强化学习算法。以下代码,可以在https://github.com/AI4Finance-Foundation/ElegantRL的根目录找到三个文件并直接运行。

eRL_demo_BipedalWalker.ipynb # 运行在Colab 的代码
eRL_demos.ipynb           # 登陆Colab有困难的,可以在本地运行这段代码
eRL_demo_PPOinSingleFile.py     # 我们甚至提供了单个文件运行PPO算法,更容易上手

步骤1:安装ElegantRL

pip install git+https://github.com/AI4Finance-LLC/ElegantRL.git

步骤2:导入相关的库

  • ElegantRL
  • OpenAI Gym:用于开发和比较不同强化学习算法的工具
  • PyBullet Gym: OpenAI Gym的MuJoCo环境的开源实现
from elegantrl.run import *
from elegantrl.agent import AgentPPO
from elegantrl.env import PreprocessEnv
import gym
gym.logger.set_level(40) # Block warning

步骤3:指定Agent和环境

  • args.agent:首先选定DRL算法,用户可以选择agent.py中的Agent
  • args.env: 创建并修饰环境,用户在env.py中既可以创建自定义的环境,也可以修饰OpenAI  Gym和PyBullet Gym的环境
args = Arguments(if_on_policy=False)
args.agent = AgentPPO() # AgentSAC(), AgentTD3(), AgentDDPG()
args.env = PreprocessEnv(env=gym.make(‘BipedalWalker-v3’))
args.reward_scale = 2 ** -1 # 不同算法实现在该任务上的收益区间: -200 < -150 < 300 < 334

步骤4:训练并评测Agent

训练和评测过程都在这个函数中实现train_and_evaluate__multiprocessing(args), 参数为args。其中包含了DRL中的两大对象:

AgentXXX()
EnvXXXXX()

其中包括用于训练的参数:

批次数据数量(batch_size),
目标步数(target_step),
收益大小比例调整(reward_scale),
折扣率(gamma), 等等。另外还包括用于评测的参数:
最大训练步数(break_step),
随机种子(random_seed),等等。

一旦满足某个条件,训练过程将会自动终止。然后画出 learning curve 等数据帮助使用者调整超参数、算法以及环境。

train_and_evaluate_mp(args)

步骤5:测试结果

我们提供的一段代码,调用 env.render()把训练的结果渲染出来,并合成视频:

get_video_to_watch_env_render()
for i in range(1024):
    frame = gym_env.render('rgb_array')
    cv2.imwrite(f'{save_dir}/{i:06}.png', frame)
    
    states = torch.as_tensor((state,), dtype=torch.float32, device=device)
    actions = agent.act(states)
    action = actions.detach().cpu().numpy()[0]
    next_state, reward, done, _ = env.step(action)

    state = env.reset() if done else next_state
 ...

9.8.gif
图5-1 训练前的双足机器人

我们提供了Colab:  https://github.com/AI4Finance-Foundation/ElegantRL/blob/master/eRL\_demo\_BipedalWalker.ipynb
的代码,帮助你运行双足机器人 BipedalWalker-v3 的demo,也许你能解锁出这个机器人的其他步态。如果你认为这个例子难度太低,该任务的进阶版BipedalWalkerHardCore-v3 是一个困难任务,环境中将会随机出现阻挡前进的台阶、沟壑以及大小箱子。由于它要求智能体在随机因素大的环境下训练(Dynamically Varying Environments 或者叫 非平稳环境 Non-Stationary Environments),(在Gym的Leaderboard(https://github.com/openai/gym/wiki/Leaderboard) 搜索这个环境的名字,可以看到有很多没有标注通关步数的算法 。)

ElegantRL 就能通关这个很难的环境,选对了算法,用对了超参数的情况下,单GPU训练超过半天就能通关,有兴趣的可以挑战一下(用SAC、ModSAC 可以通关,而PPO比较难)。
除了以上这些应用展示外,令人激动的是,ElegantRL已经可以支持Nvidia推出的用于强化学习的物理模拟环境Isaac Gym。可以帮助用户更方便地在Isaac Gym中高效地训练自己的Agent。我们将会在近期展示使用ElegantRL在Isaac Gym环境中训练可以胜任任务的Agent的应用案例,届时也会将代码上传至github仓库,敬请期待。

ElegantRL的缺点(改进的方向)

最后,我们想谈一下ELegantRL目前存在着一些不足:

  • 最高只支持8GPU训练:尽管我们内部已经实现了ElegantRL的80GPU版本,但我们将在提高80GPU以上的资源利用效率后,才开源这个版本。
  • 算法少:我们清楚还有很多重要的DRL算法需要实现,例如如何选择深度强化学习算法?MuZero/SAC/PPO/TD3/DDPG/DQN/等。可能最近会更新MuZero 和 QR-DQN。特别要指出我们还没有足够的经验去挑选出优秀的多智能体算法(MARL),希望读者能够向我们推荐如 QMix、MAPPO这类坚实的工作。
  • Pull Request机制不成熟:在完成多GPU的开源工作后,我们会逐步建立Pull Request机制。只要按照 agent.py 中的 AgentBase 类编写新算法,我们就能让它支持多GPU训练。后续我们还会推出更多自动化测试的代码。

在ElegantRL的完善过程中,我们收到了许多用户、同行等的建议,对此我们十分感谢。我们将会针对我们的不足和合理的建议,逐步完善ElegantRL。另外,我们也会陆续发布一些新算法、新架构到这里ElegantRL/elegant/AgentZoo

经过一段时间的使用后,才会转移到正式版中。

希望ElegantRL能为强化学习领域带来一点微小的共享。如果github能给个星星,我们会利用更多空余时间尽快更新把其他DRL算法以及分布式,有推荐的算法可以在写评论区,特别是MARL算法,谢谢。

来源:深度强化学习实验室
作者: AI4Finance

推荐阅读

专注深度强化学习前沿技术干货,论文,框架,学习路线等,欢迎关注微信公众号。
深度强化学习实验室.png
更多深度强化学习精选知识请关注深度强化学习实验室专栏,投稿请联系微信 1946738842.
推荐阅读
关注数
2945
内容数
56
专注深度强化学习前沿技术,欢迎关注
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息