深度强化学习 Spinning Up 项目中文版¶

介绍¶
这个项目是什么¶
欢迎来到深度强化学习(Deep Reinforement Learning)的Spinning Up项目! 这是一份由OpenAI提供的教育资源,旨在让深度强化学习的学习变得更加简单。
强化学习 ,是一种通过教会智能体反复试验(trial and error)从而完成任务的机器学习方法。 深度强化学习指的是强化学习和 深度学习 的结合。
这个模块包含一系列有用的资源,包括:
为什么创建这个项目¶
我们最常听到的问题是:
如果我想为AI安全做贡献,我应该如何开始?
在OpenAI,我们相信一般的深度学习,特别是深度强化学习将在强大的AI技术的发展中发挥核心作用。 为了确保AI是安全的,我们必须提出与该范例兼容的安全策略和算法。因此我们鼓励每一个提出这个问题的人研究这些领域。
尽管深度学习现在有很多帮助人们快速入门的资源,相比之下,深度强化学习显得门槛高很多。 首先,深度强化学习的学生要有数学、编程和常规深度学习的背景。 除此之外,他们需要对于这一领域有高水准的理解:都有哪些研究课题?这些课题为什么重要?哪些东西已经做出来了? 他们也需要认真的指导,从而了解如何将算法理论和代码结合起来。
这个领域还很新,所以一时很难有高层次的看法。现在深度强化学习领域还没有标准的教材,所以很多知识都被藏在了论文和讲座中,需要很长时间理解吸收。 深度强化学习算法的实现学习也很痛苦,因为:
- 很多算法论文或有意或无意地掩盖了关键设计细节,
- 一些广泛公开的算法实现代码很难读懂,难以把代码和算法联系在一起。
虽然类似 garage,Baselines 和 rllib 这样很棒的项目让那些已经在这个领域的研究者更加容易做出成果, 但他们将算法构建到框架中的方式涉及许多非显而易见的选择和折衷,这使它们很难学习。 所以说,不管是对于学者还是从业者、业余爱好者来说,深度强化学习领域的门槛都很高。
我们的软件包就是为了填上中间缺失的这一部分,服务于那些希望了解深度强化学习或者希望做出自己的贡献, 但是对于要学习什么内容以及如果把算法变成代码不清楚的学生。我们努力把这个项目变成一个助推器。
也就是说,从业者并不是唯一可以(或应该)从这些材料中受益的人。 解决AI安全,不仅需要具有广泛专业知识和观点的人员,而且许多相关专业根本与工程或计算机科学无关。 但是,每个参与人员都需要对技术有足够的了解,以便做出明智的决策,并且Spinning Up 项目的很多地方都提到了这一点。
这个项目如何服务我们的使命¶
OpenAI 的 使命 是确保通用人工智能的安全发展以及让人工智能带来的收益分配更加广泛。 Spinning Up这样的教学工具可帮助我们在这两个目标上取得进步。
只要我们能帮助更多人了解人工智能究竟是什么以及它是怎么工作的,我们就能更接近广泛的利益分配。 这使人们能够批判性地思考随着人工智能在我们生活中变得越来越复杂和重要,我们预期会出现的许多问题。
同时,至关重要的是,我们需要人们帮助 共同确保通用人工智能是安全的。 由于这一领域还很新,所以拥有这项技能的人才目前供不应求。我们知道很多人有兴趣帮助我们,但不知道怎么做,这里是你应该学习的内容! 如果你能通过这个项目成为专家,那你一定能在我们的人工智能安全上发挥作用。
代码设计的原则¶
Spinning Up项目仓库的算法实现旨在:
- 尽量简单,同时还要足够好,
- 不同算法实现之间高度一致,以揭示它们之间的基本相似之处。
这些算法基本上都是相互独立的,没有相互依赖的代码(除了日志打印、保存、载入和 MPI 等工具模块), 所以感兴趣的你可以分别学习每一个算法而不用去管那些繁琐的依赖关系。对实现模式化,以便尽可能做到和伪代码一致,最大程度地减少理论与代码之间的差距。
重要的是,他们的结构都很相似,所以如果你清楚地理解了一个算法,再看剩下的就很简单。
我们尽量减少算法实现时候的技巧和相似算法之间的区别。 这里我们展示一些移除的技巧,我们把原始 Soft-Actor Critic 代码中的 正则 术语,以及所有算法中的 观测归一化。 例如,我们消除了算法之间的差异:我们在 DDPG,TD3 和 SAC 的实现中都遵循了 原始 TD3 代码 的约定, 所有的梯度更新都是在每一个回合的最后执行的(而不是整个回合都在执行)。
从某种意义上说,所有的算法都做到“足够好”,它们都能达到预期的性能,但不一定与文献中关于每个任务的最佳报告结果相匹配。 因此,如果将这些实现中的任何一种用于科研基准比较时应小心。有关每个实现的特定性能级别的详细信息,请参见我们的 基准 页面。
支持计划¶
我们计划支持 Spinning Up 项目来确保他能够作为学习深度强化学习的实用资料。这个项目的长期支持(数年内)还没有确定,但是短期内我们可以承诺:
发布后的前三周会大力支持(2018年11月8日至2018年11月29日)。
- 我们将快速修复错误,解答问题以及对文档进行修改,以消除歧义。
- 我们将努力简化用户体验,以便尽可能轻松地使用Spinning Up进行自学。
发布后大约六个月(2019年4月),我们将根据从社区获得的反馈对软件包的状态进行认真审查,并宣布任何未来的修改计划,包括长期路线图。
此外,正如博客文章讨论的,我们也会在即将到来的 Scholars 和 Fellows 课程中使用 Spinning Up。任何更改和更新都会实时同步公开。
安装¶
Spinning Up 要求 Python3, OpenAI Gym, and OpenMPI.
Spinning Up 现在只支持 Linux 和 OSX。尽管尚未经过广泛测试,但可以在Windows上安装。[1]
你应该知道
Spinning Up中的许多示例和基准都是针对使用 MuJoCo 物理引擎的RL环境。MuJoCo是需要许可证的专有软件,该许可证可免费试用,对学生免费,其它则收费。 安装它是可选的,但是由于它对研究界很重要,它是在连续控制中对深度强化学习算法进行基准测试的事实上的标准,因此,建议安装。
不过,如果你决定不安装MuJoCo,请不要担心。你绝对可以通过在Gym的 Classic Control 和 Box2d 环境上运行算法来完全开始学习强化学习,这是完全免费的。
[1] | 似乎至少有一个人找出了一种 在Windows上运行的解决方法。 如果您尝试其他方法并成功,请告诉我们你的做法! |
安装 Python¶
我们建议通过 Anaconda 安装 Python。 Anaconda是一个包含Python和许多有用的Python软件包的库,以及一个名为conda的环境管理器,它使软件包管理变得简单。
此处按照Anaconda的 安装说明 进行操作。下载并安装Anaconda3(撰写本文时,Anaconda3-5.3.0)。 然后创建一个conda Python 3.6 环境来组织Spinning Up中使用的软件包:
conda create -n spinningup python=3.6
要在刚创建的环境中使用Python,请使用以下方法激活环境:
conda activate spinningup
你应该知道
如果你是python环境和软件包管理的新手,那么这些内容可能会很快变得令人困惑或不知所措,并且一路上你可能会遇到一些麻烦。 (特别是,你应该会遇到诸如“我刚刚安装了此东西,但是它说它在我尝试使用时找不到的问题!”之类的问题。) 你可能需要通读一些干净的解释,有关什么是软件包管理,为什么这样做是个好主意以及通常必须执行哪些命令才能正确使用它。
FreeCodeCamp 有一个很好的解释,值得一读。 在 Towards Data Science 上有一个简短的描述,该描述也很有帮助且内容丰富。 最后,如果你是一个非常有耐心的人,则可能需要阅读 Conda的文档页面 (枯燥但非常有用的)。
安装 Spinning Up¶
git clone https://github.com/openai/spinningup.git
cd spinningup
pip install -e .
你应该知道
Spinning Up默认情况下会安装Gym的所有内容,除了 MuJoCo环境。如果你在安装Gym时遇到任何麻烦,请查看`Gym`_ github页面以获取帮助。 如果要使用MuJoCo环境,请参见下面的可选安装部分。
检查你的安装¶
要查看是否已成功安装Spinning Up,请尝试在 LunarLander-v2 环境中使用以下命令运行PPO:
python -m spinup.run ppo --hid "[32,32]" --env LunarLander-v2 --exp_name installtest --gamma 0.999
该过程可能会持续10分钟左右,你可以在继续阅读文档的同时将其保留在后台。 这不会训练智能完成任务,但是会运行足够长的时间,以至于结果出现时你可以看到 一些 学习进度。
训练结束后,观看有关训练过的策略的视频
python -m spinup.run test_policy data/installtest/installtest_s0
并绘制结果
python -m spinup.run plot data/installtest/installtest_s0
安装 MuJoCo (可选)¶
首先,转到 mujoco-py github页面。请遵循 README 文件中的安装说明, 该说明描述了如何安装MuJoCo物理引擎和mujoco-py软件包(允许在Python中使用MuJoCo)。
你应该知道
为了使用MuJoCo仿真器,您将需要获得`MuJoCo许可证`_。任何人均可享受30天免费许可证,全日制学生可享受1年免费许可证。
安装MuJoCo后,请使用以下命令安装相应的Gym环境
pip install gym[mujoco,robotics]
然后通过在Walker2d-v2环境中运行PPO来检查一切是否正常
python -m spinup.run ppo --hid "[32,32]" --env Walker2d-v2 --exp_name mujocotest
算法¶
包括哪些算法¶
下面的算法已经在 Spinning Up 包中实现:
- Vanilla Policy Gradient (VPG)
- Trust Region Policy Optimization (TRPO)
- Proximal Policy Optimization (PPO)
- Deep Deterministic Policy Gradient (DDPG)
- Twin Delayed DDPG (TD3)
- Soft Actor-Critic (SAC)
这些算法全部以 多层感知机 (非递归)actor-critics 的方式实现, 从而适用于全观察、基于非图像的强化学习环境,例如 Gym Mujoco 环境。
为什么使用这些算法?¶
我们在这个项目中选取了能够呈现强化学习近些年思想发展的核心深度强化学习算法。 特别是两种算法 PPO 和 SAC,在策略学习算法中,它们在可靠性采样效率方面都非常先进。 它们还揭示了在深度强化学习中设计和使用算法时要做出的一些权衡。
同轨策略(On-Policy)算法¶
Vanilla Policy Gradient(VPG) 是深度强化学习领域最基础也是入门级的算法,发表时间远早于深度强化学习。 VPG 算法的核心思想可以追溯到上世纪80年代末90年代初。在那之后,TRPO和PPO等更强大的算法才相继诞生。
上述系列工作都是基于不使用历史数据的 同轨策略,也就是说,它们不使用旧数据,因此在采样效率上表现相对较差。 但这也是有原因的:这些算法直接优化我们关心的目标──策略表现,并且从数学上计算出需要同轨策略数据来计算更新。 因此,这一系列算法在权衡采样效率的同时,还考虑了稳定性,但你会看到技术的进步(从VPG到TRPO到PPO)弥补了采样效率的不足。
异轨策略(Off-Policy)算法¶
DDPG是类似于VPG的基础算法,尽管它的提出时间较晚,导致DDPG产生的确定性策略梯度理论直到2014年才发布。 DDPG与Q-learning算法紧密相关,都是同时学习Q函数和策略并通过更新相互改进。
诸如DDPG和Q-Learning之类的算法是 异轨策略,因此它们能够非常有效地重用旧数据。 他们通过利用贝尔曼方程获得最优性而获得了这一好处,Q函数可以通过训练满足使用 任何 环境交互数据(只要有来自环境中高回报区域的足够经验)。
但问题是,满足贝尔曼方程并不能保证一定有很好的策略性能。 根据经验,满足贝尔曼方程可以有不错的性能以及很好的采样效率,但是缺少保证会使此类算法变得脆弱而不稳定。 基于DDPG的后续工作 TD3 和 SAC 提出了很多新的方案来缓解这些问题。
代码格式¶
Spinning Up 项目的算法都按照标准的模板来实现。每个算法由两个文件组成:算法文件,主要是算法的核心逻辑,以及核心文件,包括各种运行算法所需的工具类。
算法文件¶
算法文件始终以经验缓存对象的类定义开头,该类定义用于存储智能体与环境之间的交互信息。
接下来有一个函数可以运行算法,并执行以下任务(按此顺序):
- Logger 设定
- 随机种子的设定
- 环境实例化
- 为计算图创建 placeholder
- 通过
actor_critic
函数传递算法函数作为参数构建actor-critic计算图- 实例化经验缓存
- 为算法特定的损失函数和诊断建立计算图
- 配置训练参数
- 构建 TF Session 并初始化参数
- 通过 logger 设置模型保存
- 定义运行算法主循环需要的函数(例如核心更新函数,获取动作函数,测试智能体函数等,取决于具体的算法)
- 运行算法主循环
- 让智能体在环境中开始运行
- 根据算法的主要方程式,周期性更新参数
- 记录核心性能指标并保存智能体
最后,是可以从命令行在Gym环境中直接运行该算法的支持。
运行试验¶
体验深度强化的最佳方法之一是运行算法,并查看它们在不同任务上的执行情况。 Spinning Up代码库使小规模(本地)实验更容易实现,在本节中,我们将讨论两种运行方式:从命令行运行,或者通过脚本中的函数调用。
从命令行启动¶
Spinning Up提供了 spinup/run.py
,这是一个方便的工具,可让你从命令行轻松启动任何算法(可以选择任何超参数)。
它也充当工具的精简包装,用于观看训练过的策略和绘图,尽管我们不会在此页上讨论该功能
(有关这些详细信息,请参见 试验输出 和 绘制结果)。
从命令行运行Spinning Up算法的标准方法是
python -m spinup.run [algo name] [experiment flags]
例如:
python -m spinup.run ppo --env Walker2d-v2 --exp_name walker
你应该知道
如果使用ZShell:ZShell会将方括号解释为特殊字符。Spinning Up在命令行参数中以几种方式使用方括号。 请确保对其进行转义,或者如果你希望默认情况下对其进行转义,请尝试 此处 推荐的解决方案。
详细快速开始指南
python -m spinup.run ppo --exp_name ppo_ant --env Ant-v2 --clip_ratio 0.1 0.2
--hid[h] [32,32] [64,32] --act tf.nn.tanh --seed 0 10 20 --dt
--data_dir path/to/data
在 Ant-v2
Gym 环境中运行 PPO,可以使用多种配置。
clip_ratio
, hid
和 act
用于设置算法超参数。你可以为超参数提供多个值以运行多个实验。
检查文档以查看可以设置的超参数(单击此处获取 PPO文档)。
hid
和 act
是 特殊快捷标志 用于为算法训练的神经网络设置隐藏层大小和激活函数。
seed
标志设置随机数生成器的种子。强化学习算法具有较高的方差,因此请尝试多个种子以了解性能如何变化。
dt
标志可确保保存目录名称中包含时间戳
(否则,则不会包含时间戳,除非你在 spinup/user_config.py
的``FORCE_DATESTAMP=True`` 设置)。
data_dir
标志允许你设置保存结果的路径。
默认值由 spinup/user_config.py
中的 DEFAULT_DATA_DIR
设置,
它将是 spinningup
文件夹中的 data
子文件夹(除非你进行更改)。
保存文件夹名称 基于 exp_name
和具有多个值的所有标志。在目录名称中会出现一个简写,而不是完整的标志。
用户可以在标志后的方括号中提供简写方式,例如 --hid[h]
。否则,快捷是标志的子字符串(clip_ratio
变为 cli
)。
为了说明这一点,以 clip_ratio=0.1
,hid=[32,32]
和 seed=10
运行的保存目录将是:
path/to/data/YY-MM-DD_ppo_ant_cli0-1_h32-32/YY-MM-DD_HH-MM-SS-ppo_ant_cli0-1_h32-32_seed10
从命令行设置超参数¶
每种算法中的每个超参数都可以直接从命令行进行控制。
如果 kwarg
是算法函数调用的有效关键字参数,则可以使用标志 --kwarg
为其设置值。
要找出可用的关键字参数,请参见文档页面中的算法,或尝试
python -m spinup.run [algo name] --help
查看文档字符串的输出。
你应该知道
值在使用前先通过 eval()
,因此你可以直接从命令行描述一些函数和对象。例如:
python -m spinup.run ppo --env Walker2d-v2 --exp_name walker --act tf.nn.elu
设置 tf.nn.elu
为激活函数。
你应该知道
对于采用dict值的参数,有一些不错的处理方法。无需提供
--key dict(v1=value_1, v2=value_2)
你可以使用
--key:v1 value_1 --key:v2 value_2
来获得同样的结果。
一次启动多个实验¶
您可以通过简单地为给定参数提供多个值来启动要 串联 执行的多个实验。(将针对每种可能的值组合进行实验。)
例如,要启动具有不同随机种子(0、10和20)的等效运行,请执行以下操作:
python -m spinup.run ppo --env Walker2d-v2 --exp_name walker --seed 0 10 20
实验无法并行启动,因为它们会占用足够的资源,因此无法同时执行多个实验,因此无法加快速度。
特殊标志¶
一些标志受到特殊对待。
环境标志¶
-
--env
,
--env_name
¶
string. The name of an environment in the OpenAI Gym. All Spinning Up algorithms are implemented as functions that accept
env_fn
as an argument, whereenv_fn
must be a callable function that builds a copy of the RL environment. Since the most common use case is Gym environments, though, all of which are built throughgym.make(env_name)
, we allow you to just specifyenv_name
(orenv
for short) at the command line, which gets converted to a lambda-function that builds the correct gym environment.
快捷标志¶
一些算法参数相对较长,我们为它们启用了快捷方式:
-
--hid
,
--ac_kwargs
:hidden_sizes
¶ list of ints. Sets the sizes of the hidden layers in the neural networks (policies and value functions).
-
--act
,
--ac_kwargs
:activation
¶ tf op. The activation function for the neural networks in the actor and critic.
这些标志对于所有当前的Spinning Up算法均有效。
配置标志¶
这些标志不是任何算法的超参数,而是以某种方式更改实验配置。
-
--cpu
,
--num_cpu
¶
int. If this flag is set, the experiment is launched with this many processes, one per cpu, connected by MPI. Some algorithms are amenable to this sort of parallelization but not all. An error will be raised if you try setting
num_cpu
> 1 for an incompatible algorithm. You can also set--num_cpu auto
, which will automatically use as many CPUs as are available on the machine.
-
--exp_name
¶
string. The experiment name. This is used in naming the save directory for each experiment. The default is “cmd” + [algo name].
-
--data_dir
¶
path. Set the base save directory for this experiment or set of experiments. If none is given, the
DEFAULT_DATA_DIR
inspinup/user_config.py
will be used.
-
--datestamp
¶
bool. Include date and time in the name for the save directory of the experiment.
保存结果的位置¶
特定实验的结果(单次运行的超参数配置)存储在
data_dir/[outer_prefix]exp_name[suffix]/[inner_prefix]exp_name[suffix]_s[seed]
其中
data_dir
是标志--data_dir
的值(如果--data_dir
没有设置, 默认为spinup/user_config.py
中的DEFAULT_DATA_DIR
),- 如果设置了
--datestamp
标志,outer_prefix
是YY-MM-DD_
格式的时间戳,否则为空, - 如果设置了
--datestamp
标志,inner_prefix
是YY-MM-DD_HH-MM-SS-
格式的时间戳, 否则为空, suffix
是基于实验超参数的特殊字符串。
后缀如何确定?¶
仅当您一次运行多个实验时才包含后缀,并且后缀仅包含对跨实验而不同的超参数的引用,随机种子除外。 目的是确保相似实验的结果(共享除种子外的所有参数的实验)被分组在同一文件夹中。
后缀是通过将超参数的 简写 及其值组合在一起来构造的,其中简写可以是1)根据超参数名称自动构建,也可以是2)用户提供。 用户可以通过在kwarg标志后的方括号中书写来提供速记。
例如,考虑:
python -m spinup.run ddpg --env Hopper-v2 --hid[h] [300] [128,128] --act tf.nn.tanh tf.nn.relu
在此,--hid
标志具有 用户提供的简写 h
。 用户未提供 --act
标志的简写,因此将自动为其构造一个标志。
在这种情况下产生的后缀是:
_h128-128_ac-actrelu
_h128-128_ac-acttanh
_h300_ac-actrelu
_h300_ac-acttanh
注意,h
是由用户给定的。ac-act
简写由 ac_kwargs:activation``(``act
标志的真实名称)构造而成。
从脚本启动¶
每种算法都实现为python函数,可以直接从 spinup
包中导入,例如
>>> from spinup import ppo
有关每种算法的完整说明,请参见文档页面。 这些方法可用于建立专门的自定义实验,例如:
from spinup import ppo
import tensorflow as tf
import gym
env_fn = lambda : gym.make('LunarLander-v2')
ac_kwargs = dict(hidden_sizes=[64,64], activation=tf.nn.relu)
logger_kwargs = dict(output_dir='path/to/output_dir', exp_name='experiment_name')
ppo(env_fn=env_fn, ac_kwargs=ac_kwargs, steps_per_epoch=5000, epochs=250, logger_kwargs=logger_kwargs)
使用ExperimentGrid¶
在机器学习研究中运行具有许多可能的超参数的相同算法通常很有用。 Spinning Up附带了一个用于简化此过程的简单工具,称为 ExperimentGrid。
考虑 spinup/examples/bench_ppo_cartpole.py
中的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from spinup.utils.run_utils import ExperimentGrid
from spinup import ppo
import tensorflow as tf
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--cpu', type=int, default=4)
parser.add_argument('--num_runs', type=int, default=3)
args = parser.parse_args()
eg = ExperimentGrid(name='ppo-bench')
eg.add('env_name', 'CartPole-v0', '', True)
eg.add('seed', [10*i for i in range(args.num_runs)])
eg.add('epochs', 10)
eg.add('steps_per_epoch', 4000)
eg.add('ac_kwargs:hidden_sizes', [(32,), (64,64)], 'hid')
eg.add('ac_kwargs:activation', [tf.tanh, tf.nn.relu], '')
eg.run(ppo, num_cpu=args.cpu)
|
创建了ExperimentGrid对象后,将参数添加到其中
eg.add(param_name, values, shorthand, in_name)
其中,in_name
会强制参数显示在实验名称中,即使该参数在所有实验中都具有相同的值。
添加所有参数后,
eg.run(thunk, **run_kwargs)
通过将配置作为函数 thunk
的kwarg提供,在网格中运行所有实验(每个有效配置对应一个实验)。
ExperimentGrid.run
使用名为 call_experiment 的函数来启动 thunk
,
**run_kwargs
指定 call_experiment
的行为。有关详细信息,请参见 文档页面。
除了没有快捷键kwargs(在 ExperimentGrid
中不能对 ac_kwargs:hidden_sizes
使用 hid
)
之外,ExperimentGrid
的基本行为与从命令行运行事物相同。
(实际上,spinup.run
在后台使用了 ExperimentGrid
。)
试验输出¶
在本节中,我们将介绍
- Spinning Up算法实现的输出是什么,
- 它们以什么格式存储以及如何组织,
- 它们的存储位置以及如何更改它们,
- 以及如何加载和运行经过训练的策略。
你应该知道
Spinning Up实现目前无法恢复对部分受训练智能体的训练。如果你认为此功能很重要,请告诉我们──或将其视为黑客项目!
算法输出¶
每种算法都设置为保存训练运行的超参数配置,学习进度,训练过的智能体和值函数,并在可能的情况下保存环境的副本(以便轻松地同时加载智能体和环境)。 输出目录包含以下内容:
+--------------------------------------------------------------------------------+
| **输出目录结构** |
+----------------+---------------------------------------------------------------+
|``simple_save/``| | 该目录包含恢复训练的智能体和值函数所需的所有内容。 |
| | | (`详细信息如下`_) |
+----------------+---------------------------------------------------------------+
|``config.json`` | | 一个字典,其中包含你用来启动训练功能的args和kwargs的尽可能完整的描述。|
| | | 如果你传入了无法序列化为JSON的内容,则日志记录程序应妥善处理它, |
| | | 并且配置文件将使用字符串来表示它。 |
| | | 注意:这仅用于保存记录。当前不支持从配置文件启动实验。 |
+----------------+---------------------------------------------------------------+
|``progress.txt``| | 制表符分隔的值文件,其中包含日志记录器在整个训练过程中记录的指标记录。 |
| | | 比如 ``Epoch``,``AverageEpRet`` 等 |
+----------------+---------------------------------------------------------------+
|``vars.pkl`` | | 包含有关算法状态的任何内容的应保存的 pickle 文件。 |
| | | 当前,所有算法仅使用此方法来保存环境的副本。 |
+----------------+---------------------------------------------------------------+
你应该知道
有时,由于无法 pickled 环境而导致环境保存失败,并且 vars.pkl
为空。
对于旧版Gym中的Gym Box2D环境,这是一个已知问题,无法以这种方式保存。
simple_save
目录包含:
+----------------------------------------------------------------------------------+
| **Simple_Save 文件结构** |
+------------------+---------------------------------------------------------------+
|``variables/`` | | 一个包含Tensorflow Saver的输出的目录。 |
| | | 请参阅 `Tensorflow SavedModel`_ 的文档。 |
+------------------+---------------------------------------------------------------+
|``model_info.pkl``| | 包含信息(从键到张量名称的映射)的字典, |
| | | 可帮助我们在加载后解压缩保存的模型。 |
+------------------+---------------------------------------------------------------+
|``saved_model.pb``| | `Tensorflow SavedModel`_ 所需的 protocol buffer。 |
+------------------+---------------------------------------------------------------+
你应该知道
您唯一必须“手动”使用的文件是 config.json
文件。
我们的智能体程序测试工具将从 simple_save/
目录和 vars.pkl
文件中加载内容,
并且我们的绘图将解释 progress.txt
的内容,而这些是用于与这些输出接口的正确工具。
但是没有用于 config.json
的工具,它只是存在,因此,如果你忘记了要进行实验的超参数,你可以再次检查。
保存目录位置¶
默认情况下,实验结果将与Spinning Up软件包保存在同一目录下的名为 data
的文件夹中:
spinningup/ data/ ... docs/ ... spinup/ ... LICENSE setup.py
你可以通过 spinup/user_config.py
中的 DEFAULT_DATA_DIR
修改默认结果目录。
加载并运行经过训练的策略¶
如果环境成功保存¶
对于成功将环境与智能体一起保存的情况,请注意使用以下方法查看训练的智能体在环境中的行为:
python -m spinup.run test_policy path/to/output_directory
选项有一些标志:
-
-l
L
,
--len
=L
,
default
=0
¶ int. Maximum length of test episode / trajectory / rollout. The default of 0 means no maximum episode length—episodes only end when the agent has reached a terminal state in the environment. (Note: setting L=0 will not prevent Gym envs wrapped by TimeLimit wrappers from ending when they reach their pre-set maximum episode length.)
-
-n
N
,
--episodes
=N
,
default
=100
¶ int. Number of test episodes to run the agent for.
-
-nr
,
--norender
¶
Do not render the test episodes to the screen. In this case,
test_policy
will only print the episode returns and lengths. (Use case: the renderer slows down the testing process, and you just want to get a fast sense of how the agent is performing, so you don’t particularly care to watch it.)
-
-i
I
,
--itr
=I
,
default
=-1
¶ int. This is an option for a special case which is not supported by algorithms in this package as-shipped, but which they are easily modified to do. Use case: Sometimes it’s nice to watch trained agents from many different points in training (eg watch at iteration 50, 100, 150, etc.). The logger can do this—save snapshots of the agent from those different points, so they can be run and watched later. In this case, you use this flag to specify which iteration to run. But again: spinup algorithms by default only save snapshots of the most recent agent, overwriting the old snapshots.
The default value of this flag means “use the latest snapshot.”
To modify an algo so it does produce multiple snapshots, find the following lines (which are present in all of the algorithms):
if (epoch % save_freq == 0) or (epoch == epochs-1): logger.save_state({'env': env}, None)
and tweak them to
if (epoch % save_freq == 0) or (epoch == epochs-1): logger.save_state({'env': env}, epoch)
Make sure to then also set
save_freq
to something reasonable (because if it defaults to 1, for instance, you’ll flood your output directory with onesimple_save
folder for each snapshot—which adds up fast).
-
-d
,
--deterministic
¶
Another special case, which is only used for SAC. The Spinning Up SAC implementation trains a stochastic policy, but is evaluated using the deterministic mean of the action distribution.
test_policy
will default to using the stochastic policy trained by SAC, but you should set the deterministic flag to watch the deterministic mean policy (the correct evaluation policy for SAC). This flag is not used for any other algorithms.
找不到环境错误¶
如果未成功保存环境,则可能导致 test_policy.py
崩溃
Traceback (most recent call last):
File "spinup/utils/test_policy.py", line 88, in <module>
run_policy(env, get_action, args.len, args.episodes, not(args.norender))
File "spinup/utils/test_policy.py", line 50, in run_policy
"page on Experiment Outputs for how to handle this situation."
AssertionError: Environment not found!
It looks like the environment wasn't saved, and we can't run the agent in it. :(
Check out the readthedocs page on Experiment Outputs for how to handle this situation.
在这种情况下,只要你可以地重新创建环境,就可以观察智能体的执行情况。在IPython中尝试以下操作:
>>> from spinup.utils.test_policy import load_policy, run_policy
>>> import your_env
>>> _, get_action = load_policy('/path/to/output_directory')
>>> env = your_env.make()
>>> run_policy(env, get_action)
Logging data to /tmp/experiments/1536150702/progress.txt
Episode 0 EpRet -163.830 EpLen 93
Episode 1 EpRet -346.164 EpLen 99
...
使用经过训练的值函数¶
test_policy.py
工具无法帮助你查看经过训练的值函数,如果要使用这些函数,则必须手工进行一些挖掘。
有关详细信息,请查看 restore_tf_graph 函数的文档。
绘制结果¶
Spinning Up附带了一个用于解释结果的简单绘图工具。 使用以下命令运行它:
python -m spinup.run plot [path/to/output_directory ...] [--legend [LEGEND ...]]
[--xaxis XAXIS] [--value [VALUE ...]] [--count] [--smooth S]
[--select [SEL ...]] [--exclude [EXC ...]]
位置参数:
-
logdir
¶
strings. As many log directories (or prefixes to log directories, which the plotter will autocomplete internally) as you’d like to plot from. Logdirs will be searched recursively for experiment outputs.
你应该知道
The internal autocompleting is really handy! Suppose you have run several experiments, with the aim of comparing performance between different algorithms, resulting in a log directory structure of:
data/ bench_algo1/ bench_algo1-seed0/ bench_algo1-seed10/ bench_algo2/ bench_algo2-seed0/ bench_algo2-seed10/
You can easily produce a graph comparing algo1 and algo2 with:
python spinup/utils/plot.py data/bench_algo
relying on the autocomplete to find both
data/bench_algo1
anddata/bench_algo2
.
Optional Arguments:
-
-l
,
--legend
=[LEGEND ...]
¶ strings. Optional way to specify legend for the plot. The plotter legend will automatically use the
exp_name
from theconfig.json
file, unless you tell it otherwise through this flag. This only works if you provide a name for each directory that will get plotted. (Note: this may not be the same as the number of logdir args you provide! Recall that the plotter looks for autocompletes of the logdir args: there may be more than one match for a given logdir prefix, and you will need to provide a legend string for each one of those matches—unless you have removed some of them as candidates via selection or exclusion rules (below).)
-
-x
,
--xaxis
=XAXIS
,
default
='TotalEnvInteracts'
¶ string. Pick what column from data is used for the x-axis.
-
-y
,
--value
=[VALUE ...]
,
default
='Performance'
¶ strings. Pick what columns from data to graph on the y-axis. Submitting multiple values will produce multiple graphs. Defaults to
Performance
, which is not an actual output of any algorithm. Instead,Performance
refers to eitherAverageEpRet
, the correct performance measure for the on-policy algorithms, orAverageTestEpRet
, the correct performance measure for the off-policy algorithms. The plotter will automatically figure out which ofAverageEpRet
orAverageTestEpRet
to report for each separate logdir.
-
--count
¶
Optional flag. By default, the plotter shows y-values which are averaged across all results that share an
exp_name
, which is typically a set of identical experiments that only vary in random seed. But if you’d like to see all of those curves separately, use the--count
flag.
-
-s
,
--smooth
=S
,
default
=1
¶ int. Smooth data by averaging it over a fixed window. This parameter says how wide the averaging window will be.
-
--select
=[SEL ...]
¶ strings. Optional selection rule: the plotter will only show curves from logdirs that contain all of these substrings.
-
--exclude
=[EXC ...]
¶ strings. Optional exclusion rule: plotter will only show curves from logdirs that do not contain these substrings.
第一部分:强化学习中的核心概念¶
欢迎来到强化学习的介绍部分!我们希望你能了解以下内容:
- 用于讨论该主题的语言和符号,
- 高层次的理解:关于强化学习算法做什么(我们会尽量避免 如何做 这个话题),
- 少量算法背后的核心数学知识。
总的来说,强化学习是关于智能体以及它们如何通过试错来学习的研究。 它确定了通过奖励或惩罚智能体的动作从而使它未来更容易重复或者放弃某一动作的思想。
强化学习能做什么?¶
强化学习的方法最近已经在很多地方取得了成功。例如,它被用来教电脑在仿真环境下控制机器人:
以及在现实世界中:
强化学习因为被用在复杂策略游戏创造出突破性的 AI 中而名声大噪, 最著名的要数 围棋 、Dota、教计算机从原始像素 玩Atari游戏 以及训练模拟机器人 听从人类的指令。
核心概念和术语¶

智能体和环境的交互循环。
强化学习的主要角色是 智能体 和 环境,环境是智能体存在和交互的世界。 智能体在每一步的交互中,都会获得对于所处环境状态的观测(有可能只是一部分),然后决定下一步要执行的动作。 环境会因为智能体对它的动作而改变,也可能自己改变。
智能体也会从环境中感知到 奖励 信号,一个表明当前状态好坏的数字。 智能体的目标是最大化累计奖励,也就是 回报。强化学习就是智能体通过学习行为来实现目标的方法。
为了更具体地讨论强化的作用,我们需要引入其他术语。我们会讨论:
- 状态和观测,
- 动作空间,
- 策略,
- 轨迹,
- 不同的回报公式,
- 强化学习优化问题,
- 值函数。
状态和观测¶
一个 状态 是一个关于这个世界状态的完整描述。这个世界除了状态以外没有别的信息。
观测
是对于一个状态的部分描述,可能会漏掉一些信息。
在深度强化学习中,我们一般用 实数向量、矩阵或者更高阶的张量 表示状态和观测。 比如说,视觉上的观测可以用用其像素值的RGB矩阵表示;机器人的状态可以通过关节角度和速度来表示。
如果智能体观测到环境的全部状态,我们通常说环境是被 全面观测 的。如果智能体只能观测到一部分,我们称之为被 部分观测。
你应该知道
强化学习有时候用符号 代表状态,有些地方也会写作观测符号
。
尤其是,当智能体在决定采取什么动作的时候,符号上的表示按理动作是基于状态的,
但实际上,动作是基于观测的,因为智能体并不能知道状态(只能通过观测了解状态)。
在我们的教程中,我们会按照标准的方式使用这些符号,不过你一般能从上下文中看出来具体表示什么。 如果你觉得有些内容不够清楚,请提出issue!我们的目的是教会大家,不是让大家混淆。
动作空间¶
不同的环境允许不同的动作。所有给定环境中有效动作的集合称之为 动作空间。 有些环境,比如说 Atari 游戏和围棋,属于 离散动作空间,这种情况下智能体只能采取有限的动作。 其他的一些环境,比如智能体在物理世界中控制机器人,属于 连续动作空间。在连续动作空间中,动作是实数向量。
这种区别对于深度强化学习来说,影响深远。有些种类的算法只能一种情况下直接使用,而在另一种情况下则必须进行大量修改。
策略¶
策略 是智能体用于决定下一步执行什么动作的规则。可以是确定性的,一般表示为 :
也可以是随机的,一般表示为 :
因为策略本质上就是智能体的大脑,所以很多时候“策略”和“智能体”这两个名词经常互换,例如我们会说:“策略的目的是最大化奖励”。
在深度强化学习中,我们处理的是 参数化的策略:策略的输出依赖于一系列计算函数, 而这些函数又依赖于参数(例如神经网络的权重和偏差),所以我们可以通过一些优化算法改变智能体的的行为。
我们经常把这些策略的参数写作 或者
,然后把它写在策略的下标上来强调两者的联系。
确定性策略¶
例子:确定性策略。这是一个基于 TensorFlow 在连续动作空间上构建确定性策略的简单例子:
obs = tf.placeholder(shape=(None, obs_dim), dtype=tf.float32)
net = mlp(obs, hidden_dims=(64,64), activation=tf.tanh)
actions = tf.layers.dense(net, units=act_dim, activation=None)
其中,mlp
是把多个给定大小和激活函数的 dense
相互堆积在一起的函数。
随机策略¶
深度强化学习中最常见的两种随机策略是 类别策略 (Categorical Policies) 和 对角高斯策略 (Diagonal Gaussian Policies)。
类别 策略适用于离散动作空间,而 高斯 策略一般用在连续动作空间。
对于使用和训练随机策略,两个关键计算至关重要:
- 从策略中采样动作,
- 计算特定行为的对数似然
。
接下来,我们将描述针对类别策略和对角高斯策略如何执行这些操作。
类别策略
类别策略就像是一个离散空间的分类器。对于分类器和确定策略来说,建立神经网络的方式一模一样: 输入是观测,接着是若干层(可能是卷积或全连接层,具体取决于输入的类型), 最后是一个线性层给出每个动作的 logit 值,后面跟一个 softmax 层把 logit 值转换为概率。
采样。给定每个动作的概率,TensorFlow之类的框架有内置采样工具。 具体可查阅 tf.distributions.Categorical 或者 tf.multinomial 文档.
对数似然:表示最后一层的概率 。
它是一个有很多值的向量,我们可以把动作当做向量的索引。
所以向量的对数似然值
可以通过索引向量得到:
对角高斯策略
多元高斯分布(或者多元正态分布),可以用一个均值向量 和协方差
来描述。
对角高斯分布就是协方差矩阵只在对角线上有值的特殊情况,所以我们可以用一个向量来表示它。
对角高斯策略总会有一个神经网络,表示观测到平均动作 通常有两种不同的方式表示协方差矩阵。
第一种方法:有一个对数标准差的单独的向量 ,它不是关于状态的函数:
是单独的参数。
(你应该知道,我们对 VPG, TRPO 和 PPO 都是用这种方式实现的。)
第二种方法:有一个神经网络,从状态映射到对数标准差 。
它可以选择与均值网络共享某些层。
要注意这两种情况下我们都没有直接计算标准差而是计算对数标准差。
这是因为对数标准差能够接受 之间的任何值,而标准差必须要求参数非负。
要知道,限制条件越少,训练就越简单。而标准差可以通过取幂快速从对数标准差中计算得到,所以这种表示方法也不会丢失信息。
采样。给定平均动作 和标准差
,
以及一个服从球形高斯分布(
)的噪声向量
,动作样本可以这样计算:
其中 表示两个向量按元素相乘。标准框架都有内置噪声向量实现,例如 tf.random_normal。
你也可以直接用 tf.distributions.Normal 以均值和标准差的方式来采样。
对数似然。一个基于均值为 ,
标准差为
的对角高斯的
维动作 action
的对数似然为:
轨迹(Trajectories)¶
轨迹 指的是状态和动作的序列,
第一个状态 是从 开始状态分布 中随机采样的,有时候表示为
:
转态转换(从某一时间 的状态
到
另一时间
的状态
会发生什么),
是由环境的自然法则确定的,并且只依赖于最近的动作
。它们可以是确定性的:
也可以是随机的:
智能体的动作由策略确定。
你应该知道
轨迹常常也被称作 回合(episodes) 或者 rollouts。
奖励和回报¶
强化学习中,奖励函数 非常重要。它由当前状态、已经执行的动作和下一步的状态共同决定。
有时候这个公式会被改成只依赖当前的状态 ,或者状态动作对
。
智能体的目标是最大化轨迹的累积奖励,这实际上意味着很多事情。我们会把所有的情况表示为 ,
至于具体表示什么,要么可以很清楚的从上下文看出来,要么并不重要。(因为相同的方程式适用于所有情况。)
一种回报是 有限视野无折扣回报 (finite-horizon undiscounted return),指的是在一个固定窗口步数内获得的奖励之和:
另一种回报是 无限视野折扣回报 (infinite-horizon discounted return),指的是智能体 曾经 获得的全部奖励之和,
但是奖励会因为获得的时间不同而衰减。这个公式包含折扣因子 :
这里为什么要加上一个折扣因子呢?为什么不直接把 所有 奖励加在一起?这么做,但是折扣因子在直观上和数学上都很方便。
直观上讲,现在的奖励比未来的奖励要好;数学角度上,无限多个奖励的和 可能不能收敛 到有限值,并且很难用方程来处理。 有了折扣因子和适当的约束条件,无穷和收敛。
你应该知道
这两个公式在强化学习公式中看起来差距很大,但深度强化学习上经常会混用。 比如说,我们经常使用算法以优化无折扣回报收益,但是用折扣因子估计 值函数。
强化学习问题¶
无论选择哪种方式衡量收益(有限视野无折扣回报或者无限视野折扣回报),无论选择哪种策略, 强化学习的目标都是选择一种策略从而最大化 期望回报。
讨论期望回报之前,我们先讨论下轨迹的概率分布。
我们假设环境转换和策略都是随机的。这种情况下, 步的轨迹是:
期望回报(无论哪种方式衡量):math:J(pi) 是:
强化学习中的核心优化问题可以表示为:
是 最优策略。
值函数¶
知道一个状态的 值 或者状态动作对很有用。这里的值指的是,如果你从某一个状态或者状态动作对开始, 一直按照某个策略运行下去最终获得的期望回报。几乎是所有的强化学习算法,都在使用一种或另一种形式的 值函数。
这里介绍四种主要函数:
1. 同轨策略值函数:,从某一个状态
开始,
之后每一步动作都按照策略
执行的期望回报:
2. 同轨策略动作值函数:,从某一个状态
开始,
先随便执行一个动作
(有可能不是按照策略走的),之后每一步都按照策略
执行的期望回报:
最优值函数:
,从某一个状态
开始,之后每一步都按照 最优 策略执行的期望回报:
4. 最优动作值函数:,从某一个状态
开始,
先随便执行一个动作
,之后每一步都按照 最优 策略执行的期望回报:
你应该知道
当我们讨论值函数的时候,如果我们没有提到时间依赖问题,我们仅指预期的 无限视野折扣回报。 有限视野无折扣回报的值函数需要传入时间作为参数,你知道为什么吗? 提示:时间到了会发生什么?
你应该知道
值函数和动作值函数之间经常会出现两个关键联系:
以及
这些关系直接来自刚刚给出的定义,你能尝试给出证明吗?
最优 Q 函数和最优动作¶
最优动作值函数 和被最优策略选中的动作之间有重要的联系。
从定义上讲,
指的是从一个状态
开始,执行(任意)一个行动
,
然后一直按照最优策略执行下去所获得的期望回报。
状态 的最优策略会选择从状态
开始能够最大化期望回报的行动。
所以如果我们有了
,就可以通过下面的公式直接获得最优动作
:
注意:可能会有多个动作能够最大化 ,这种情况下,它们都是最优动作,最优策略可能会从中随机选择一个。
但是总会存在一个最优策略每一步选择动作的时候都是确定的。
贝尔曼方程¶
所有四个值函数都遵循称为 贝尔曼方程 的特殊自洽方程。贝尔曼方程背后的基本思想是:
起始点的值等于当前点预期值和下一个点的值之和。
同轨策略值函数的贝尔曼方程是
其中 是
的简写,
表明下一个状态
是按照转移规则从环境中采样得到的;
是
的简写;
是
的简写。
最优值函数的贝尔曼方程是
同轨策略值函数和最优值函数的贝尔曼方程的最大区别是在动作上是否 。
这表明智能体在选择下动作时,为了采取最优动作,他必须选择能获得最大值的动作。
你应该知道
贝尔曼算子(Bellman backup)在强化学习中经常出现。 一个状态或一个状态动作对的贝尔曼算子在贝尔曼方程的右边:奖励加下一个价值。
优势函数¶
强化学习中,有些时候我们不需要描述一个行动的绝对好坏,而只需要知道它相对于平均水平的有多好。 也就是说,我们只想知道一个行动的相对 优势 。这就是 优势函数 的概念。
一个服从策略 的优势函数
,
描述的是它在状态
下采取动作
比
根据
随机选择一个动作好多少(假设之后一直服从策略
)。
数学上,优势函数的定义为:
你应该知道
我们之后会继续谈论优势函数,它对于策略梯度方法非常重要。
第二部分:强化学习算法¶
我们已经介绍了强化学习的基础术语和符号,现在可以讨论一些更丰富的内容: 现代强化学习中算法的整体发展和算法设计时候要考虑的各种因素之间的权衡。
强化学习算法分类¶
一个不是很详细但是十分有用的现代强化学习算法分类。参见底部链接。
要先声明的是:很难准确全面的把所有现代强化学习算法都列举出来,因为这些内容本身不适合用树形结构展示。 同时,把这么多内容放在一篇文章里,还要便于理解,必须省略掉一些更加前沿的内容, 例如探索(exploration),迁移学习(transfer learning),元学习(meta learning)等。 这篇文章的目标是:
- 只强调深度强化学习中关于学习什么以及如何学习的最基本的设计选择,
- 揭示这些选择中的利弊权衡,
- 把其中部分优秀的现代算法介绍给大家。
免模型强化学习(Model-Free) vs 有模型强化学习(Model-Based)¶
不同强化学习算法最重要的区分点之一就是 智能体是否能完整了解(或学习)到所在环境的模型。 环境的模型是指一个预测状态转换和奖励的函数。
有模型学习最大的优势在于 允许智能体 提前考虑来进行 规划, 走到每一步的时候,都提前尝试未来可能的选择,然后明确地从这些候选项中进行选择。 智能体可以把预先规划的结果提取为学习策略。这其中最著名的例子就是 AlphaZero。 相对于那些没有模型的方法,这个方法起作用的时候,可以大幅度提升采样效率。
有模型学习最大的缺点就是 智能体往往不能获得环境的真实模型。 如果智能体想在一个场景下使用模型,那它必须完全从经验中学习,这会带来很多挑战。 最大的挑战就是,智能体探索出来的模型和真实模型之间存在偏差, 而这种偏差会导致智能体在学习到的模型中表现很好,但在真实的环境中表现得不好(甚至很差)。 模型学习从根本上讲是非常困难的,即使你愿意花费大量的时间和计算力,最终的结果也可能达不到预期的效果。
使用模型的算法叫做 有模型 学习,不基于模型的叫做 免模型 学习。 虽然免模型学习放弃了有模型学习在样本效率方面的潜在收益,但是他们往往更加易于实现和调整。 截止到目前(2018年9月),相对于有模型学习,免模型学习方法更受欢迎,得到更加广泛的开发和测试。
要学习什么¶
强化学习算法另一个重要的区分点是 要学习什么。常提到的主题包括:
- 策略,不管是随机的还是确定性的,
- 动作值函数(Q 函数),
- 值函数,
- 以及/或者环境模型。
免模型强化学习中要学习什么¶
有两种用来表示和训练免模型强化学习的主要方式:
策略优化:这个系列的方法将策略显示表示为 。
它们直接对性能目标
进行梯度下降来优化参数
,
或者间接地,通过最大化性能目标
的局部近似来优化。
优化基本都是基于 同轨策略 的,也就是说每一步更新只会用最新的策略执行时采集到的数据。
策略优化通常还包括学习同轨值函数
的近似器
,
该近似器用于确定如何更新策略。
基于策略优化的方法举例:
Q-Learning:这个系列的算法学习最优动作值函数 的近似函数
。
它们通常使用基于 贝尔曼方程 的目标函数。优化过程属于 异轨策略,
这意味着每次更新可以使用任意时间点的训练数据,不管获取数据时智能体选择如何探索环境。
对应的策略是通过
和
之间的联系得到的:Q-learning 智能体的动作由下面的式子给出:
基于 Q-Learning 的方法举例:
策略优化和 Q-Learning 的权衡:策略优化的主要优势在于这类方法是合理的,
某种意义上讲,你在直接在优化你想要的东西。这倾向于使它们稳定和可靠。
与此相反,Q-learning 方法通过训练 以满足自洽方程,间接地 优化智能体的表现。
这种方法有很多失败的模型,所以相对来说稳定性较差。[1]
但是,Q-learning 有效的时候能获得更好的采样效率,因为它们能够比策略优化更加有效地重用数据。
策略优化和 Q-learning 的融合 意外的是,策略优化和 Q-learning 并不是不能兼容的(在某些场景下,它们两者是 等价的), 并且存在很多介于这两种极端之间的算法。这个范围的算法能够很好的平衡好两者之间的优点和缺点,比如说:
- DDPG,是一种使用一方提高另一方的,同时学习确定性策略和 Q 函数的算法,
- 以及 SAC,是一种变体,它使用随机策略、熵正则化和一些其它技巧来稳定学习,同时在标准基准上获得比 DDPG 更高的分数。
[1] | 关于更多 Q-learning 可能会表现不好的情况,参见:1) 经典论文 Tsitsiklis and van Roy, 2) 最近的文章 review by Szepesvari (在 4.3.2 节),3) `Sutton and Barto`_的第11章节, 尤其是 11.3(函数近似,自举和异轨数据的“致命三要素”,共同导致值学习算法的不稳定)。 |
有模型强化学习要学习什么¶
不同于免模型学习,有模型强化学习方法不是很好分类:很多方法之间都会有交叉。 我们会给出一些例子,当然肯定不够详尽,覆盖不到全部。在这些例子里面,模型要么已知,要么是可学习的。
背景:纯规划 这种最基础的方法,从来 不 显式地表示策略,而是单纯使用规划技术来选择动作,例如 模型预测控制 (MPC)。
在模型预测控制中,智能体每次观察环境的时候,都会计算得到一个对于当前模型最优的规划, 这里的规划指的是未来一个固定时间段内,智能体会采取的所有行动(通过学习值函数,规划算法可能会考虑到超出范围的未来奖励)。 智能体然后执行规划的第一个行动,然后立即舍弃规划的剩余部分。 每次准备和环境进行互动时,它会计算出一个新的规划,从而避免执行规划范围短于预期范围的规划给出的行动。
- MBMF 在一些深度强化学习的标准基准任务上,基于学习到的环境模型进行模型预测控制。
专家迭代 纯规划的后来之作,使用和学习策略的显式表示形式:。
智能体在模型中应用了一种规划算法,类似蒙特卡洛树搜索(Monte Carlo Tree Search),通过对当前策略进行采样生成规划的候选动作。
这种算法得到的动作比策略本身生成的要好,所以相对于策略来说,它是“专家”。随后策略更新以产生更类似于规划算法输出的动作。
免模型方法的数据增强 使用免模型算法来训练策略或者 Q 函数, 要么 1)更新智能体的时候,用构造出的数据来增强真实经验,2)更新的时候 仅 使用构造的假经验。
- MBVE 用构造出的数据来增强真实经验。
- World Models 全部用假数据来训练智能体,所以被称为:“在梦里训练”。
将规划循环嵌入到策略中 另一种方法直接把规划程序作为策略的子程序,这样在基于任何免模型算法训练策略输出的时候,整个规划就变成了策略的附属信息。 这个框架最核心的概念就是,策略可以学习到如何以及何时使用规划。 这使得模型偏差不再是问题,因为如果模型在某些状态下不利于规划,那么策略可以简单地学会忽略它。
- I2A 智能体被赋予这种形式的想象的例子。
分类中提到的算法链接¶
[2] | A2C / A3C (Asynchronous Advantage Actor-Critic): Mnih et al, 2016 |
[3] | PPO (Proximal Policy Optimization): Schulman et al, 2017 |
[4] | TRPO (Trust Region Policy Optimization): Schulman et al, 2015 |
[5] | DDPG (Deep Deterministic Policy Gradient): Lillicrap et al, 2015 |
[6] | TD3 (Twin Delayed DDPG): Fujimoto et al, 2018 |
[7] | SAC (Soft Actor-Critic): Haarnoja et al, 2018 |
[8] | DQN (Deep Q-Networks): Mnih et al, 2013 |
[9] | C51 (Categorical 51-Atom DQN): Bellemare et al, 2017 |
[10] | QR-DQN (Quantile Regression DQN): Dabney et al, 2017 |
[11] | HER (Hindsight Experience Replay): Andrychowicz et al, 2017 |
[12] | World Models: Ha and Schmidhuber, 2018 |
[13] | I2A (Imagination-Augmented Agents): Weber et al, 2017 |
[14] | MBMF (Model-Based RL with Model-Free Fine-Tuning): Nagabandi et al, 2017 |
[15] | MBVE (Model-Based Value Expansion): Feinberg et al, 2018 |
[16] | AlphaZero: Silver et al, 2017 |
第三部分:策略优化介绍¶
在这个部分,我们会讨论策略优化算法的数学基础,同时提供样例代码。我们会包括 策略梯度 理论的三个关键结果:
最后,我们会把结果放在一起,然后描述策略梯度基于优势函数的版本:我们在 Vanilla Policy Gradient 实现中使用的版本。
推导最简单的策略梯度¶
我们考虑一种随机的参数化策略 。
我们的目标是最大化期望回报
。
出于方便推导,我们假定
是 有限视野无折扣回报,对于无限视野折扣回报的推导几乎是相同。
我们将通过梯度下降来优化策略,例如
策略性能的梯度 称为 策略梯度,
而以这种方式优化策略的算法称为 策略梯度算法。
(例如Vanilla Policy Gradient和TRPO。PPO通常称为策略梯度算法,尽管这有点不准确。)
要实际使用此算法,我们需要一个可以通过数值计算的策略梯度表达式。这涉及两个步骤: 1)得出策略性能的解析梯度,证明其具有期望值的形式, 2)形成该期望值的样本估计,可以使用有限数量的智能体与环境相互作用的步骤数据计算得出。
在本小节中,我们将找到该表达式的最简形式。 在后面的小节中,我们将展示如何以最简的形式进行改进,以得到我们在标准策略梯度实现中实际使用的版本。
我们将首先列出一些事实,这些事实对于推导解析梯度非常有用。
1. 轨迹的概率。由 给出的动作的轨迹
的概率为:
2. 对数导数技巧。对数导数技巧基于微积分的一条简单规则: 相对于
的导数为
。
重新排列并与链式规则结合后,我们得到:
3. 轨迹的对数概率。 轨迹的对数概率为
4. 环境方程的梯度。环境不依赖于 ,
所以
,
和
的梯度为零。
5. 轨迹对数概率的梯度。轨迹对数概率的梯度为:
综上所述,我们得出以下结论:
基本策略梯度的推导
这是一个期望,这意味着我们可以使用样本均值对其进行估计。
如果我们收集一组轨迹 ,
其中每一个轨迹通过让智能体在环境中使用策略
执行操作得到,则策略梯度可以使用以下式子进行估计:
其中 是
中轨迹的数量(在这里为
)。
最后一个表达式是我们想要的可计算表达式的最简单版本。
假设我们以允许我们计算 的方式表示我们的策略,
并且如果我们能够在环境中运行该策略以收集轨迹数据,则我们可以计算策略梯度并采取更新步骤。
实现最简单的策略梯度¶
我们在 spinup/examples/pg_math/1_simple_pg.py
中给出了此简单版本的策略梯度算法的简短Tensorflow实现。
(也可以 在github上 查看。)
只有122行,因此我们强烈建议你深入阅读。虽然我们不会在这里介绍全部代码,但我们将重点介绍一些重要的部分。
1. 建立策略网络。
25 26 27 28 29 30 | # make core of policy network
obs_ph = tf.placeholder(shape=(None, obs_dim), dtype=tf.float32)
logits = mlp(obs_ph, sizes=hidden_sizes+[n_acts])
# make action selection op (outputs int actions, sampled from policy)
actions = tf.squeeze(tf.multinomial(logits=logits,num_samples=1), axis=1)
|
该代码快构建了前馈神经网络分类策略。(新手请参见第一部分 随机策略 一节。)
logits
张量可用于构造对数概率和动作概率,actions
张量根据 logits
所隐含的概率对动作进行采样。
2. 构造损失函数。
32 33 34 35 36 37 | # make loss function whose gradient, for the right data, is policy gradient
weights_ph = tf.placeholder(shape=(None,), dtype=tf.float32)
act_ph = tf.placeholder(shape=(None,), dtype=tf.int32)
action_masks = tf.one_hot(act_ph, n_acts)
log_probs = tf.reduce_sum(action_masks * tf.nn.log_softmax(logits), axis=1)
loss = -tf.reduce_mean(weights_ph * log_probs)
|
在此块中,我们为策略梯度算法构建“损失”函数。当插入正确的数据时,此损失的梯度等于策略梯度。 正确的数据表示根据当前策略执行操作时收集的一组(状态,动作,权重)元组,其中状态-动作对的权重是它所属episode的回报。 (你可以插入其他权重数据来使其正常工作,我们将在后面的小节中展示。)
你应该知道
经管我们将其描述为损失函数,但从监督学习的角度来看,它并 不是 典型的损失函数。与标准损失函数有两个主要区别。
1. 数据分布取决于参数。损失函数通常在固定的数据分布上定义,该分布与我们要优化的参数无关。 这里不是这样,必须在最新策略上对数据进行采样。
2.它无法衡量效果。损失函数通常会评估我们关注的性能指标。
在这里,我们关心期望收益 ,但即使在期望中,我们的“损失”函数也根本不近似。
此“损失”函数仅对我们有用,因为当在当前参数下进行评估时,使用当前参数生成的数据,它的性能会呈现负梯度。
但是,在梯度下降的第一步之后,它就不再与性能相关。这意味着,对于给定的一批数据,最小化此“损失”函数无法保证提高期望收益。
你可以将这一损失设为 ,而策略性能可能下降。实际上,通常会这样。
有时,资深强化学习研究人员可能将此结果描述为对大量数据“过度拟合”的策略。这是描述性的,但不应从字面上理解,因为它没有涉及泛化误差。
之所以提出这一点,是因为机器学习练习者通常会在训练过程中将损失函数解释为有用的信号──“如果损失减少了,一切都会好起来的。” 在政策梯度中,这种直觉是错误的,您应该只关心平均回报率。损失函数没有任何意义。
你应该知道
此处用于生成 log_probs
张量的方法(创建操作掩码,并使用它来选择特定的对数概率) 仅 适用于分类策略。通常它不起作用。
3. 进行一个轮次的训练。
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | # for training policy
def train_one_epoch():
# make some empty lists for logging.
batch_obs = [] # for observations
batch_acts = [] # for actions
batch_weights = [] # for R(tau) weighting in policy gradient
batch_rets = [] # for measuring episode returns
batch_lens = [] # for measuring episode lengths
# reset episode-specific variables
obs = env.reset() # first obs comes from starting distribution
done = False # signal from environment that episode is over
ep_rews = [] # list for rewards accrued throughout ep
# render first episode of each epoch
finished_rendering_this_epoch = False
# collect experience by acting in the environment with current policy
while True:
# rendering
if not(finished_rendering_this_epoch):
env.render()
# save obs
batch_obs.append(obs.copy())
# act in the environment
act = sess.run(actions, {obs_ph: obs.reshape(1,-1)})[0]
obs, rew, done, _ = env.step(act)
# save action, reward
batch_acts.append(act)
ep_rews.append(rew)
if done:
# if episode is over, record info about episode
ep_ret, ep_len = sum(ep_rews), len(ep_rews)
batch_rets.append(ep_ret)
batch_lens.append(ep_len)
# the weight for each logprob(a|s) is R(tau)
batch_weights += [ep_ret] * ep_len
# reset episode-specific variables
obs, done, ep_rews = env.reset(), False, []
# won't render again this epoch
finished_rendering_this_epoch = True
# end experience loop if we have enough of it
if len(batch_obs) > batch_size:
break
# take a single policy gradient update step
batch_loss, _ = sess.run([loss, train_op],
feed_dict={
obs_ph: np.array(batch_obs),
act_ph: np.array(batch_acts),
weights_ph: np.array(batch_weights)
})
return batch_loss, batch_rets, batch_lens
|
train_one_epoch()
函数运行一个策略梯度的“轮次”,我们定义为
- 经验收集步骤(L62-97),其中智能体使用最新策略在环境中执行一定数量的episodes,然后是
- 单个策略梯度更新步骤(L99-105)。
算法的主循环只是反复调用 train_one_epoch()
。
期望梯度对数概率引理¶
在本小节中,我们将得出一个中间结果,该结果在整个策略梯度理论中得到了广泛使用。我们将其称为“期望梯度对数概率(EGLP)”引理。 [1]
EGLP 引理 假设 是随机变量
上的参数化概率分布,则:
证明
我们知道所有概率分布均已归一化:
取标归一形式的两侧的梯度:
使用对数导数技巧可以得到:
[1] | 本文的作者不知道是否在文献中的任何地方给该引理指定了标准名称。但是考虑到它出现的频率,似乎很值得给它起一个名字以便于参考。 |
不要让过去使你分心¶
回顾我们对策略梯度的最新表达:
沿着这个梯度迈出一步,将每个动作的对数概率与 成正比,
是 曾经获得的所有奖励 之和。 但这没有多大意义。
智能体实际上仅应根据其 结果 强化动作。采取动作之前获得的奖励与该动作的效果无关:只有 获得的 奖励。
事实证明,这种直觉体现在数学上,我们可以证明策略梯度也可以表示为
在这种形式中,仅根据采取动作后获得的奖励来强化动作。
我们将这种形式称为“reward-to-go策略梯度”,因为轨迹上某点之后的奖励总和,
被称为从那点起的 reward-to-go行的奖励,而这种策略梯度表达式取决于状态动作对的reward-to-go。
你应该知道
但这如何更好? 策略梯度的关键问题是需要多少个样本轨迹才能获得它们的低方差样本估计。 我们从公式开始就包括了与过去的奖励成比例的强化动作的项, 所有这些均值为零,但方差不为零:结果,它们只会给政策梯度的样本估计值增加噪音。 通过删除它们,我们减少了所需的样本轨迹数量。
可以在 此处 找到该声明的(可选)证明,当然它基于EGLP引理。
实现 Reward-to-Go 策略梯度¶
我们在 spinup/examples/pg_math/2_rtg_pg.py
中给出了 reward-to-go 策略梯度算法的简短Tensorflow实现。
(也可以 在 github 上 查看。)
与 1_simple_pg.py
唯一不同的是,我们现在在损失函数中使用了不同的权重。
代码修改非常小:我们添加了一个新函数,并更改了另外两行。新函数是:
12 13 14 15 16 17 | def reward_to_go(rews):
n = len(rews)
rtgs = np.zeros_like(rews)
for i in reversed(range(n)):
rtgs[i] = rews[i] + (rtgs[i+1] if i+1 < n else 0)
return rtgs
|
然后我们从以下方法调整旧的L86-87:
86 87 | # the weight for each logprob(a|s) is R(tau)
batch_weights += [ep_ret] * ep_len
|
为:
93 94 | # the weight for each logprob(a_t|s_t) is reward-to-go from t
batch_weights += list(reward_to_go(ep_rews))
|
策略梯度基准¶
EGLP引理的直接结果是,对于仅依赖状态的任何函数 ,
这使我们能够从我们的策略梯度表达式中加上或减去任何数量的这样的项,而无需更改它:
这种方式使用的任何函数 称为 基准。
基线的最常见选择是 同轨策略值函数 。
回想一下,这是智能体从状态
开始并在其余下的时间里按照策略
执行动作所获得的平均回报。
根据经验,选择 具有减少策略梯度样本估计中的方差的理想效果。
这样可以更快,更稳定地学习策略。从概念的角度来看,它也很有吸引力:它编码了一种直觉,即如果一个智能体获得了它预期的,它将“感觉”到中立。
你应该知道
实际上,无法精确计算 因此必须将其近似。
通常,这是通过神经网络
来完成的,该神经网络会与策略同时进行更新(以便价值网络始终近似于最新策略的值函数)。
大多数策略优化算法(包括VPG,TRPO,PPO和A2C)的实现中使用的最简单的学习 的方法是最小化均方误差:
其他形式的策略梯度¶
到目前为止,我们看到的是策略梯度具有一般形式
其中 可以是
或者
或者
尽管有不同的差异,所有这些选择都导致相同的策略梯度期望值。事实证明,有两个权重 有效选择非常重要。
1. 同轨动作值函数。选择
也有效。有关此声明的(可选)证明,请参见 此页面。
2. 优势函数。
回想一下 动作的优势,定义为 ,
描述相对于其他动作,平均而言(相对于当前策略)的好坏。这个选择
也是有效的。证明是,它等同于使用 然后使用值函数基线,
我们始终可以这么做。
你应该知道
具有优势函数的策略梯度的公式极为普遍,并且有许多不同的方法来估算不同算法使用的优势函数。
你应该知道
要对此主题进行更详细的处理,您应该阅读有关 广义优势估计 (Generalized Advantage Estimation,GAE)的文章,
该文章深入介绍了背景部分中 的不同选择。
然后,该论文继续描述GAE,GAE是一种在策略优化算法中具有广泛用途的近似优势函数的方法。 例如,Spinning Up的VPG,TRPO和PPO的实现都利用了它。因此,我们强烈建议你进行研究。
概括¶
在本章中,我们描述了策略梯度方法的基本理论,并将一些早期结果与代码示例相关联。 有兴趣的学生应该从这里继续研究以后的结果(价值函数基准和策略梯度的优势公式) 如何转化为Spinning Up的 Vanilla Policy Gradient 的实现。
深度强化学习研究者资料¶
By Joshua Achiam, October 13th, 2018
如果你是一位深度强化学习的研究者,你现在可能已经对深度强化学习有了很多的了解。 你知道 它很难不总是有效 。即便是严格按照步骤来,可重现性 依然是 一大挑战。 如果你准备从头开始,学习的曲线非常陡峭 。 虽然已经有 很多 很棒的 学习 资源,但是因为很多资料都很新,以至于还没有一条清晰明确的捷径。 这个项目的目的就是帮助你克服这些一开始的障碍,并且让你清楚的知道,如何成为一名深度强化学习研究员。 在这个项目里,我们会介绍一些有用的课程,作为基础知识,同时把一些可能适合研究的方向结合进来。
正确的背景¶
建立良好的数学背景。从概率和统计学的角度,要对于随机变量、贝叶斯定理、链式法则、期望、标准差和重要性抽样等要有很好的理解。 从多重积分的角度,要了解梯度和泰勒展开(可选,但是会很有用)。
对于深度学习要有基础的了解。你不用知道每一个技巧和结构,但是了解基础的知识很有帮助。 要了解 多层感知机、vanilla RNN,LSTM (同时看这篇博客)、GRU、卷积、 层、残差网络、注意力 机制,常见的正则手段(weight decay,dropout), 归一化方式(batch norm,layer norm,weight norm) 和优化方式(SGD, momentum SGD,Adam,以及其它)。 要了解什么是 reparameterization trick 。
至少熟悉一种深度学习框架。 Tensorflow 或者 PyTorch 非常适合练手。 你不用知道所有东西,但是你要能非常自信地实现一种监督学习算法。
对于强化学习中的主要概念和术语很了解。知道什么是状态、动作、轨迹、策略、奖励、值函数和动作值函数。 如果你对这些不了解,去读一读项目里面 介绍 部分的材料。 OpenAI Hackthon 的 强化学习介绍 也很值得看,或者是 Lilian Weng 的综述。 如果你对于数学理论很感兴趣,可以学习 单调提升理论 (高级策略梯度算法的的基础)或者 经典强化学习算法 (尽管被深度强化学习所替代,但还是有很多能推动新的研究的洞见)。
在动手中学习¶
自己实现算法。你应该尽可能地从头开始编写尽可能多的深度强化学习的核心算法,同时要保证自己的实现尽量简单、正确。这是了解这些算法如何工作、培养特定性能特征的直觉的最佳方法。
简单是最重要的。你要对自己的工作有合理的规划,从最简单的算法开始,然后慢慢引入复杂性。 如果你一开始就构建很多复杂的部分,有可能会耗费你接下来几周的时间来尝试调试。 对于刚刚接触强化学习的人来说,这是很常见的问题。如果你发现自己被困在其中, 不要气馁,尝试回到最开始然后换一种更简单的算法。
哪些算法?你可以大概按照 vanilla policy gradient(也被称为 REINFORCE )、DQN, A2C ( A3C 的同步版本),PPO (具有 clipped objective 特性的变体), DDPG 的顺序来学习。 这些算法的最简版本可以用几百行代码编写(大约250-300行),有些更少,比如 简洁版本的VPG 只需要 80 行的代码。 在写并行版本代码之前,先尝试写单线程版本的。(至少实现一种并行的算法)
注重理解。编写有效的强化学习代码需要对于算法有明确的理解,同时注重细节。 因为 错误的代码总是悄无声息:看起来运行的很正常,但实际上智能体什么也没有学到。 这种情况通常是因为有些公式写错了,或者分布不对,又或者数据传输到了错误的地方。 有时候找到这些错误的唯一办法,就是批判性地阅读代码,明确知道它应该做什么,找到它偏离正确行为的地方。 这就需要你一方面了解学术文献,另一方面参考已有的实现,所以你要花很多时间在这些上面。
看论文的时候要注意什么:当基于论文实现算法的时候,要彻读论文,尤其是消融分析和补充材料(如果有)。 这些消减将使你直观地了解哪些参数或子例程对使事情正常运行具有最大的影响,这将帮助你诊断错误。 补充材料通常会提供有关特定细节的信息,例如网络体系结构和优化超参数,并且你应当尝试使实现与这些细节保持一致,以增加使它起作用的机会。
但是不要过分解读论文的细节。有时,论文使用了比严格必要更多的技巧,因此请对此有所警惕,并在可能的情况下尝试简化。 例如,原始DDPG论文提出了一种复杂的神经网络架构和初始化方案,以及批标准化。 这些并非绝对必要,并且DDPG的一些最佳报告结果都使用更简单的网络。 再举一个例子,原始的A3C论文使用了来自不同参与者学习者的异步更新,但是事实证明,同步更新也能正常工作。
也不要过度解读现有的实现。研究 现有的 实现 以获取灵感,但请注意不要过度解读这些实现的工程细节。 强化学习库通常会做出抽象选择,这些选择有利于算法之间的代码重用,但是如果你仅编写单个算法或支持单个用例,则不必要。
在简单的环境中快速迭代。要调试你的实现,请在需要快速学习的简单环境中尝试它们,例如在 OpenAI Gym 的 CartPole-v0,InvertedPendulum-v0,FrozenLake-v0和HalfCheetah-v2上 (具有较短的时间范围──仅100或250步,而不是完整的1000步))。 如果你尚未首先验证算法可以在最简单的玩具任务上工作,请不要尝试在Atari或复杂的类人动物环境中运行算法。 在调试阶段,理想的实验周转时间小于5分钟(在本地计算机上),或者稍长一些,但不多。 这些小规模的实验不需要任何特殊的硬件,并且可以在CPU上运行而不会造成太多麻烦。
如果不起作用,请假设存在错误。在调整超参数之前,请花费大量精力查找错误:通常是错误。 错误的超参数可能会严重降低强化学习性能,但是如果你使用与论文和标准实施中的超参数相似的超参数,则可能不会成为问题。 还要牢记:有时即使在遇到严重错误的情况下,程序也可以在一种环境中运行,因此一旦结果令人满意,请确保在多个环境中进行测试。
测量一切。做很多测试以了解引擎盖下的情况。你在每次迭代中读取的学习过程的统计数据越多,调试起来就越容易──毕竟,如果看不到中断,就无法断定。 我个人希望查看累积奖励,剧集长度和价值函数估计值的均值/标准差/最小值/最大值,以及目标的损失以及任何探索参数的详细信息 (例如用于随机策略优化的均值熵,或当前的epsilon(如DQN中的epsilon-greedy)。 另外,不时观看有关智能体表现的视频;这将为你提供一些其他方面无法获得的见解。
在工作正常时扩展实验规模。在实现了强化学习算法,并且似乎可以在最简单的环境中正常运行的算法之后,请在较复杂的环境中对其进行测试。 此阶段的实验需要更长的时间,具体取决于几个小时到几天之间的某个时间。 此时,专用硬件(例如功能强大的GPU或32核机器)可能会有用,并且你应考虑研究AWS或GCE等云计算资源。
保持这些习惯!这些习惯值得你保持,不仅是在学习深度强化学习的阶段,它们将加速你的研究!
开展一个研究项目¶
一旦你对深度强化学习的基础知识感到相当满意,就应该开始突破界限并进行研究。要到达那里,你需要一个项目构想。
从探索文献开始,以了解该领域的主题。你可能会发现很多有趣的主题: 采样效率,探索,迁移学习,层次结构,内存,基于模型的强化学习,元学习和多智能体,仅举几例。 如果你正在寻找灵感,或者只是想大致了解其中的内容, 请查看Spinning Up的 关键论文列表。 找到你喜欢的其中一个主题的论文(启发你的东西)并仔细阅读。 使用相关的工作部分和引用来查找密切相关的论文,并深入研究文献。 你将开始找出未解决的问题以及可以在何处你可以产生影响。
产生想法的方法。有很多不同的方法可以开始考虑项目的想法,并且你选择的框架会影响项目的发展方式以及面临的风险。这里有一些例子:
方法1:改进现有方法。这是增量主义的角度,你可以通过调整现有算法来尝试在已建立的问题设置中获得性能提升。 在这里重新实现先前的工作非常有帮助,因为它使你了解现有算法脆弱且可以改进的方式。 新手会发现这是最容易使用的方法,但是对于任何有经验的研究人员来说,它也是值得的。 尽管一些研究人员发现增量主义并不那么令人兴奋,但机器学习中一些最令人印象深刻的成就却来自这种性质的工作。
由于此类项目与现有方法相关,因此它们的范围很窄,可以很快(几个月)结束,这可能是理想的(特别是作为研究人员起步时)。 但这也带来了风险:你可能对算法进行的调整可能无法改善它,在这种情况下,除非你提出更多的调整,否则项目就结束了,并且你还没有明确的信号接下来做什么。
.**方法2:关注未解决的基准**。而不是考虑如何改进现有方法,你的目标是成功完成一项以前没有人解决过的任务。 例如:在Sonic领域或Gym Retro中实现从训练水平到测试水平的完美泛化。 当你完成一项尚未解决的任务时,你可能会尝试多种方法,包括先前的方法和为该项目发明的新方法。 新手可以解决此类问题,但学习曲线会更加陡峭。
此方法中的项目范围很广,可以持续一段时间(几个月到一年以上)。 主要风险在于,如果没有重大突破,基准是无法解决的,这意味着很容易花费大量时间而没有取得任何进展。 但是,即使像这样的项目失败了,它也通常会导致研究人员获得许多新见解,这些见解将成为下一个项目的沃土。
方法3:创建新的问题设定。与其考虑现有方法或当前面临的巨大挑战,不如考虑一个尚未研究的完全不同的概念性问题。 然后,找出如何取得进展。对于遵循这些思路的项目,可能尚不存在标准基准,因此你必须设计一个基准。 这可能是一个巨大的挑战,但值得拥抱──出色的基准可以使整个领域向前发展。
问题出现时就会出现此框架中的问题──很难去寻找它们。
避免重新发明轮子。当你想到要开始测试的好主意时,那就太好了! 但是,尽管你仍处于初期阶段,但请进行最彻底的检查,以确保尚未完成。 半途而废地完成一个项目,然后才发现已经有关于你的想法的论文可能会令人沮丧。 当工作同时进行时,这尤其令人沮丧,这不时发生! 但是,不要让那吓到你──绝对不要让它激励你以尚未完成的研究来打下烙印,并夸大了部分工作的优点。 做一个好的研究,并通过彻底而彻底的调查来完成你的项目,因为从长远来看,这才是最重要的。
做严谨的强化学习研究¶
The claim you’ll make in your work is that those design decisions collectively help, but this is really a bundle of several claims in disguise: one for each such design element.
现在你想出了一个主意,并且可以肯定它还没有完成。你将使用开发的技能来实施它,然后开始在标准域上对其进行测试。看起来可行! 但是,这意味着什么?它必须发挥多大的作用才能变得重要?这是深度强化学习研究中最难的部分之一。 为了验证你的建议是有意义的贡献,你必须严格证明它实际上比最强大的基准算法(在当前在测试域上达到SOTA(最新技术水平))取得了性能上的好处。 如果你发明了一个新的测试域,那么就没有以前的SOTA了,你仍然需要尝试一下文献中最可靠的算法,该算法在新的测试域中可能表现良好,然后就必须击败它。
进行公平比较。如果你是从头开始实施基准线(而不是直接与另一张纸的数字进行比较),那么花在调整基准线上的时间与调整自己的算法所花的时间一样重要。 这将确保比较是公平的。此外,即使算法与基准之间存在实质性差异,也应尽力保持“其他条件不变”。 例如,如果你要研究架构变体,则使模型参数的数量在模型和基准之间大致相等。在任何情况下均不得妨碍基线! 事实证明,强化学习中的基准非常强大,要想获得更大,持续的胜利可能会很棘手,或者需要对算法设计有一定的了解。
消除作为混杂因素的随机性。当心随机种子会使事情看起来比实际更强或更弱,因此请为许多随机种子运行所有命令(至少3个,但如果要透彻,则执行10个或更多)。 这确实很重要,值得重点关注:在许多常见的用例中,深度强化学习相对于随机种子而言似乎很脆弱。 可能存在足够的方差,两组不同的随机种子可以产生差异很大的学习曲线,以至于它们看起来根本不是来自同一分布(请参见 此处的图10)。
运行高完整性实验。不要仅仅从最佳或最有趣的运行中获取结果以用于你的论文中。 相反,针对你打算比较的所有方法(如果要与自己的基准实现进行比较)启动新的最终实验,并预先承诺报告其中的结果。 这是为了强制执行一种较弱的 预注册形式:你使用调整阶段来得出你的假设,然后使用最终运行来得出你的结论。
分别检查每个设计选择。做研究的另一个关键方面是进行消融分析。 你提出的任何方法都可能具有多个关键设计决策,例如体系结构选择或正则化技术,每个决策都可能分别影响性能。 你将在工作中提出的主张是这些设计选择可以共同帮助,但这实际上是一堆变相的声明:每个这样的设计元素。 通过系统地评估如果将其替换为其他设计选择或将其完全删除会发生什么,你可以弄清楚如何正确地归功于你的方法所带来的好处。 这样一来,你就可以对每个单独的设计选择充满信心,并提高工作的整体实力。
以及:其他资源¶
考虑阅读以下其他有关在该领域成为研究人员或工程师的内容丰富的文章:
短期机器学习研究项目的建议,Tim Rocktäschel,Jakob Foerster 和 Greg Farquhar。
用于AI安全性和健壮性的机器学习工程化:《来自谷歌大脑工程师的指南》,Catherine Olsson 和 80,000 小时。
参考¶
[1] | Deep Reinforcement Learning Doesn’t Work Yet, Alex Irpan, 2018 |
[2] | Reproducibility of Benchmarked Deep Reinforcement Learning Tasks for Continuous Control, Islam et al, 2017 |
[3] | Deep Reinforcement Learning that Matters, Henderson et al, 2017 |
[4] | Lessons Learned Reproducing a Deep Reinforcement Learning Paper, Matthew Rahtz, 2018 |
[5] | UCL Course on RL |
[6] | Berkeley Deep RL Course |
[7] | Deep RL Bootcamp |
[8] | Nuts and Bolts of Deep RL, John Schulman |
[9] | Stanford Deep Learning Tutorial: Multi-Layer Neural Network |
[10] | The Unreasonable Effectiveness of Recurrent Neural Networks, Andrej Karpathy, 2015 |
[11] | LSTM: A Search Space Odyssey, Greff et al, 2015 |
[12] | Understanding LSTM Networks, Chris Olah, 2015 |
[13] | Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling, Chung et al, 2014 (GRU paper) |
[14] | Conv Nets: A Modular Perspective, Chris Olah, 2014 |
[15] | Stanford CS231n, Convolutional Neural Networks for Visual Recognition |
[16] | Deep Residual Learning for Image Recognition, He et al, 2015 (ResNets) |
[17] | Neural Machine Translation by Jointly Learning to Align and Translate, Bahdanau et al, 2014 (Attention mechanisms) |
[18] | Attention Is All You Need, Vaswani et al, 2017 |
[19] | A Simple Weight Decay Can Improve Generalization, Krogh and Hertz, 1992 |
[20] | Dropout: A Simple Way to Prevent Neural Networks from Overfitting, Srivastava et al, 2014 |
[21] | Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift, Ioffe and Szegedy, 2015 |
[22] | Layer Normalization, Ba et al, 2016 |
[23] | Weight Normalization: A Simple Reparameterization to Accelerate Training of Deep Neural Networks, Salimans and Kingma, 2016 |
[24] | Stanford Deep Learning Tutorial: Stochastic Gradient Descent |
[25] | Adam: A Method for Stochastic Optimization, Kingma and Ba, 2014 |
[26] | An overview of gradient descent optimization algorithms, Sebastian Ruder, 2016 |
[27] | Auto-Encoding Variational Bayes, Kingma and Welling, 2013 (Reparameterization trick) |
[28] | Tensorflow |
[29] | PyTorch |
[30] | Spinning Up强化学习,第一部分:强化学习中的核心概念 |
[31] | 强化学习介绍 Slides from OpenAI Hackathon, Josh Achiam, 2018 |
[32] | A (Long) Peek into Reinforcement Learning, Lilian Weng, 2018 |
[33] | Optimizing Expectations, John Schulman, 2016 (Monotonic improvement theory) |
[34] | Algorithms for Reinforcement Learning, Csaba Szepesvari, 2009 (Classic RL Algorithms) |
[35] | Benchmarking Deep Reinforcement Learning for Continuous Control, Duan et al, 2016 |
[36] | Playing Atari with Deep Reinforcement Learning, Mnih et al, 2013 (DQN) |
[37] | OpenAI Baselines: ACKTR & A2C |
[38] | Asynchronous Methods for Deep Reinforcement Learning, Mnih et al, 2016 (A3C) |
[39] | Proximal Policy Optimization Algorithms, Schulman et al, 2017 (PPO) |
[40] | Continuous Control with Deep Reinforcement Learning, Lillicrap et al, 2015 (DDPG) |
[41] | RL-Intro Policy Gradient Sample Code, Josh Achiam, 2018 |
[42] | OpenAI Baselines |
[43] | rllab |
[44] | OpenAI Gym |
[45] | OpenAI Retro Contest |
[46] | OpenAI Gym Retro |
[47] | Center for Open Science, explaining what preregistration means in the context of scientific experiments. |
深度强化学习的核心论文¶
以下是深度强化中值得阅读的论文列表。这距离全面还 很 远,但是应该为希望在该领域进行研究的人提供有用的起点。
目录
1. 免模型强化学习¶
a. 深度 Q-Learning¶
[1] | Playing Atari with Deep Reinforcement Learning, Mnih et al, 2013. Algorithm: DQN. |
[2] | Deep Recurrent Q-Learning for Partially Observable MDPs, Hausknecht and Stone, 2015. Algorithm: Deep Recurrent Q-Learning. |
[3] | Dueling Network Architectures for Deep Reinforcement Learning, Wang et al, 2015. Algorithm: Dueling DQN. |
[4] | Deep Reinforcement Learning with Double Q-learning, Hasselt et al 2015. Algorithm: Double DQN. |
[5] | Prioritized Experience Replay, Schaul et al, 2015. Algorithm: Prioritized Experience Replay (PER). |
[6] | Rainbow: Combining Improvements in Deep Reinforcement Learning, Hessel et al, 2017. Algorithm: Rainbow DQN. |
b. 策略梯度¶
[7] | Asynchronous Methods for Deep Reinforcement Learning, Mnih et al, 2016. Algorithm: A3C. |
[8] | Trust Region Policy Optimization, Schulman et al, 2015. Algorithm: TRPO. |
[9] | High-Dimensional Continuous Control Using Generalized Advantage Estimation, Schulman et al, 2015. Algorithm: GAE. |
[10] | Proximal Policy Optimization Algorithms, Schulman et al, 2017. Algorithm: PPO-Clip, PPO-Penalty. |
[11] | Emergence of Locomotion Behaviours in Rich Environments, Heess et al, 2017. Algorithm: PPO-Penalty. |
[12] | Scalable trust-region method for deep reinforcement learning using Kronecker-factored approximation, Wu et al, 2017. Algorithm: ACKTR. |
[13] | Sample Efficient Actor-Critic with Experience Replay, Wang et al, 2016. Algorithm: ACER. |
[14] | Soft Actor-Critic: Off-Policy Maximum Entropy Deep Reinforcement Learning with a Stochastic Actor, Haarnoja et al, 2018. Algorithm: SAC. |
c. 确定性策略梯度¶
[15] | Deterministic Policy Gradient Algorithms, Silver et al, 2014. Algorithm: DPG. |
[16] | Continuous Control With Deep Reinforcement Learning, Lillicrap et al, 2015. Algorithm: DDPG. |
[17] | Addressing Function Approximation Error in Actor-Critic Methods, Fujimoto et al, 2018. Algorithm: TD3. |
d. 分布式强化学习¶
[18] | A Distributional Perspective on Reinforcement Learning, Bellemare et al, 2017. Algorithm: C51. |
[19] | Distributional Reinforcement Learning with Quantile Regression, Dabney et al, 2017. Algorithm: QR-DQN. |
[20] | Implicit Quantile Networks for Distributional Reinforcement Learning, Dabney et al, 2018. Algorithm: IQN. |
[21] | Dopamine: A Research Framework for Deep Reinforcement Learning, Anonymous, 2018. Contribution: Introduces Dopamine, a code repository containing implementations of DQN, C51, IQN, and Rainbow. Code link. |
e. 带有 Action-Dependent Baselines 的策略梯度¶
[22] | Q-Prop: Sample-Efficient Policy Gradient with An Off-Policy Critic, Gu et al, 2016. Algorithm: Q-Prop. |
[23] | Action-depedent Control Variates for Policy Optimization via Stein’s Identity, Liu et al, 2017. Algorithm: Stein Control Variates. |
[24] | The Mirage of Action-Dependent Baselines in Reinforcement Learning, Tucker et al, 2018. Contribution: interestingly, critiques and reevaluates claims from earlier papers (including Q-Prop and stein control variates) and finds important methodological errors in them. |
f. 路径一致性学习(Path-Consistency Learning)¶
[25] | Bridging the Gap Between Value and Policy Based Reinforcement Learning, Nachum et al, 2017. Algorithm: PCL. |
[26] | Trust-PCL: An Off-Policy Trust Region Method for Continuous Control, Nachum et al, 2017. Algorithm: Trust-PCL. |
g. 其他结合策略梯度和Q-Learning的方向¶
[27] | Combining Policy Gradient and Q-learning, O’Donoghue et al, 2016. Algorithm: PGQL. |
[28] | The Reactor: A Fast and Sample-Efficient Actor-Critic Agent for Reinforcement Learning, Gruslys et al, 2017. Algorithm: Reactor. |
[29] | Interpolated Policy Gradient: Merging On-Policy and Off-Policy Gradient Estimation for Deep Reinforcement Learning, Gu et al, 2017. Algorithm: IPG. |
[30] | Equivalence Between Policy Gradients and Soft Q-Learning, Schulman et al, 2017. Contribution: Reveals a theoretical link between these two families of RL algorithms. |
h. 进化算法¶
[31] | Evolution Strategies as a Scalable Alternative to Reinforcement Learning, Salimans et al, 2017. Algorithm: ES. |
2. 探索¶
a. 内在激励(Intrinsic Motivation)¶
[32] | VIME: Variational Information Maximizing Exploration, Houthooft et al, 2016. Algorithm: VIME. |
[33] | Unifying Count-Based Exploration and Intrinsic Motivation, Bellemare et al, 2016. Algorithm: CTS-based Pseudocounts. |
[34] | Count-Based Exploration with Neural Density Models, Ostrovski et al, 2017. Algorithm: PixelCNN-based Pseudocounts. |
[35] | #Exploration: A Study of Count-Based Exploration for Deep Reinforcement Learning, Tang et al, 2016. Algorithm: Hash-based Counts. |
[36] | EX2: Exploration with Exemplar Models for Deep Reinforcement Learning, Fu et al, 2017. Algorithm: EX2. |
[37] | Curiosity-driven Exploration by Self-supervised Prediction, Pathak et al, 2017. Algorithm: Intrinsic Curiosity Module (ICM). |
[38] | Large-Scale Study of Curiosity-Driven Learning, Burda et al, 2018. Contribution: Systematic analysis of how surprisal-based intrinsic motivation performs in a wide variety of environments. |
[39] | Exploration by Random Network Distillation, Burda et al, 2018. Algorithm: RND. |
b. 非监督强化学习¶
[40] | Variational Intrinsic Control, Gregor et al, 2016. Algorithm: VIC. |
[41] | Diversity is All You Need: Learning Skills without a Reward Function, Eysenbach et al, 2018. Algorithm: DIAYN. |
[42] | Variational Option Discovery Algorithms, Achiam et al, 2018. Algorithm: VALOR. |
3. 迁移和多任务强化学习¶
[43] | Progressive Neural Networks, Rusu et al, 2016. Algorithm: Progressive Networks. |
[44] | Universal Value Function Approximators, Schaul et al, 2015. Algorithm: UVFA. |
[45] | Reinforcement Learning with Unsupervised Auxiliary Tasks, Jaderberg et al, 2016. Algorithm: UNREAL. |
[46] | The Intentional Unintentional Agent: Learning to Solve Many Continuous Control Tasks Simultaneously, Cabi et al, 2017. Algorithm: IU Agent. |
[47] | PathNet: Evolution Channels Gradient Descent in Super Neural Networks, Fernando et al, 2017. Algorithm: PathNet. |
[48] | Mutual Alignment Transfer Learning, Wulfmeier et al, 2017. Algorithm: MATL. |
[49] | Learning an Embedding Space for Transferable Robot Skills, Hausman et al, 2018. |
[50] | Hindsight Experience Replay, Andrychowicz et al, 2017. Algorithm: Hindsight Experience Replay (HER). |
4. 层次(Hierarchy)¶
[51] | Strategic Attentive Writer for Learning Macro-Actions, Vezhnevets et al, 2016. Algorithm: STRAW. |
[52] | FeUdal Networks for Hierarchical Reinforcement Learning, Vezhnevets et al, 2017. Algorithm: Feudal Networks |
[53] | Data-Efficient Hierarchical Reinforcement Learning, Nachum et al, 2018. Algorithm: HIRO. |
5. 记忆(Memory)¶
[54] | Model-Free Episodic Control, Blundell et al, 2016. Algorithm: MFEC. |
[55] | Neural Episodic Control, Pritzel et al, 2017. Algorithm: NEC. |
[56] | Neural Map: Structured Memory for Deep Reinforcement Learning, Parisotto and Salakhutdinov, 2017. Algorithm: Neural Map. |
[57] | Unsupervised Predictive Memory in a Goal-Directed Agent, Wayne et al, 2018. Algorithm: MERLIN. |
[58] | Relational Recurrent Neural Networks, Santoro et al, 2018. Algorithm: RMC. |
6. 有模型强化学习¶
a. 模型可被学习¶
[59] | Imagination-Augmented Agents for Deep Reinforcement Learning, Weber et al, 2017. Algorithm: I2A. |
[60] | Neural Network Dynamics for Model-Based Deep Reinforcement Learning with Model-Free Fine-Tuning, Nagabandi et al, 2017. Algorithm: MBMF. |
[61] | Model-Based Value Expansion for Efficient Model-Free Reinforcement Learning, Feinberg et al, 2018. Algorithm: MVE. |
[62] | Sample-Efficient Reinforcement Learning with Stochastic Ensemble Value Expansion, Buckman et al, 2018. Algorithm: STEVE. |
[63] | Model-Ensemble Trust-Region Policy Optimization, Kurutach et al, 2018. Algorithm: ME-TRPO. |
[64] | Model-Based Reinforcement Learning via Meta-Policy Optimization, Clavera et al, 2018. Algorithm: MB-MPO. |
[65] | Recurrent World Models Facilitate Policy Evolution, Ha and Schmidhuber, 2018. |
b. 模型已知¶
[66] | Mastering Chess and Shogi by Self-Play with a General Reinforcement Learning Algorithm, Silver et al, 2017. Algorithm: AlphaZero. |
[67] | Thinking Fast and Slow with Deep Learning and Tree Search, Anthony et al, 2017. Algorithm: ExIt. |
7. 元学习(Meta-RL)¶
[68] | RL^2: Fast Reinforcement Learning via Slow Reinforcement Learning, Duan et al, 2016. Algorithm: RL^2. |
[69] | Learning to Reinforcement Learn, Wang et al, 2016. |
[70] | Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks, Finn et al, 2017. Algorithm: MAML. |
[71] | A Simple Neural Attentive Meta-Learner, Mishra et al, 2018. Algorithm: SNAIL. |
8. 扩展强化学习¶
[72] | Accelerated Methods for Deep Reinforcement Learning, Stooke and Abbeel, 2018. Contribution: Systematic analysis of parallelization in deep RL across algorithms. |
[73] | IMPALA: Scalable Distributed Deep-RL with Importance Weighted Actor-Learner Architectures, Espeholt et al, 2018. Algorithm: IMPALA. |
[74] | Distributed Prioritized Experience Replay, Horgan et al, 2018. Algorithm: Ape-X. |
[75] | Recurrent Experience Replay in Distributed Reinforcement Learning, Anonymous, 2018. Algorithm: R2D2. |
[76] | RLlib: Abstractions for Distributed Reinforcement Learning, Liang et al, 2017. Contribution: A scalable library of RL algorithm implementations. Documentation link. |
9. 现实世界的强化学习¶
[77] | Benchmarking Reinforcement Learning Algorithms on Real-World Robots, Mahmood et al, 2018. |
[78] | Learning Dexterous In-Hand Manipulation, OpenAI, 2018. |
[79] | QT-Opt: Scalable Deep Reinforcement Learning for Vision-Based Robotic Manipulation, Kalashnikov et al, 2018. Algorithm: QT-Opt. |
[80] | Horizon: Facebook’s Open Source Applied Reinforcement Learning Platform, Gauci et al, 2018. |
10. 安全性¶
[81] | Concrete Problems in AI Safety, Amodei et al, 2016. Contribution: establishes a taxonomy of safety problems, serving as an important jumping-off point for future research. We need to solve these! |
[82] | Deep Reinforcement Learning From Human Preferences, Christiano et al, 2017. Algorithm: LFP. |
[83] | Constrained Policy Optimization, Achiam et al, 2017. Algorithm: CPO. |
[84] | Safe Exploration in Continuous Action Spaces, Dalal et al, 2018. Algorithm: DDPG+Safety Layer. |
[85] | Trial without Error: Towards Safe Reinforcement Learning via Human Intervention, Saunders et al, 2017. Algorithm: HIRL. |
[86] | Leave No Trace: Learning to Reset for Safe and Autonomous Reinforcement Learning, Eysenbach et al, 2017. Algorithm: Leave No Trace. |
11. 模仿学习和逆强化学习¶
[87] | Modeling Purposeful Adaptive Behavior with the Principle of Maximum Causal Entropy, Ziebart 2010. Contributions: Crisp formulation of maximum entropy IRL. |
[88] | Guided Cost Learning: Deep Inverse Optimal Control via Policy Optimization, Finn et al, 2016. Algorithm: GCL. |
[89] | Generative Adversarial Imitation Learning, Ho and Ermon, 2016. Algorithm: GAIL. |
[90] | DeepMimic: Example-Guided Deep Reinforcement Learning of Physics-Based Character Skills, Peng et al, 2018. Algorithm: DeepMimic. |
[91] | Variational Discriminator Bottleneck: Improving Imitation Learning, Inverse RL, and GANs by Constraining Information Flow, Peng et al, 2018. Algorithm: VAIL. |
[92] | One-Shot High-Fidelity Imitation: Training Large-Scale Deep Nets with RL, Le Paine et al, 2018. Algorithm: MetaMimic. |
12. 可复现、分析和评价¶
[93] | Benchmarking Deep Reinforcement Learning for Continuous Control, Duan et al, 2016. Contribution: rllab. |
[94] | Reproducibility of Benchmarked Deep Reinforcement Learning Tasks for Continuous Control, Islam et al, 2017. |
[95] | Deep Reinforcement Learning that Matters, Henderson et al, 2017. |
[96] | Where Did My Optimum Go?: An Empirical Analysis of Gradient Descent Optimization in Policy Gradient Methods, Henderson et al, 2018. |
[97] | Are Deep Policy Gradient Algorithms Truly Policy Gradient Algorithms?, Ilyas et al, 2018. |
[98] | Simple Random Search Provides a Competitive Approach to Reinforcement Learning, Mania et al, 2018. |
[99] | Benchmarking Model-Based Reinforcement Learning, Wang et al, 2019. |
13. 额外奖励:强化学习理论的经典论文¶
[100] | Policy Gradient Methods for Reinforcement Learning with Function Approximation, Sutton et al, 2000. Contributions: Established policy gradient theorem and showed convergence of policy gradient algorithm for arbitrary policy classes. |
[101] | An Analysis of Temporal-Difference Learning with Function Approximation, Tsitsiklis and Van Roy, 1997. Contributions: Variety of convergence results and counter-examples for value-learning methods in RL. |
[102] | Reinforcement Learning of Motor Skills with Policy Gradients, Peters and Schaal, 2008. Contributions: Thorough review of policy gradient methods at the time, many of which are still serviceable descriptions of deep RL methods. |
[103] | Approximately Optimal Approximate Reinforcement Learning, Kakade and Langford, 2002. Contributions: Early roots for monotonic improvement theory, later leading to theoretical justification for TRPO and other algorithms. |
[104] | A Natural Policy Gradient, Kakade, 2002. Contributions: Brought natural gradients into RL, later leading to TRPO, ACKTR, and several other methods in deep RL. |
[105] | Algorithms for Reinforcement Learning, Szepesvari, 2009. Contributions: Unbeatable reference on RL before deep RL, containing foundations and theoretical background. |
练习¶
目录
问题集1:基础实现¶
练习 1.1:高斯对数似然
练习路径 spinup/exercises/problem_set_1/exercise1_1.py
解答路径 spinup/exercises/problem_set_1_solutions/exercise1_1_soln.py
指示 编写一个函数,该函数将Tensorflow符号用于一批对角高斯分布的均值和对数标准, 以及一个Tensorflow占位符用于从这些分布中生成(先前生成的)样本, 并返回一个Tensorflow符号以计算那些样品的对数似然。
你可能会发现复习 强化学习简介 部分中给出的公式很有用。
在 exercise1_1.py
中完成你的实现,并运行该文件以自动检查你的工作。
评价标准 通过使用一批随机输入将输出与已知良好的实现进行比较,来检查你的解决方案。
练习 1.2:PPO的策略
练习路径 spinup/exercises/problem_set_1/exercise1_2.py
解答路径 spinup/exercises/problem_set_1_solutions/exercise1_2_soln.py
指示 为PPO实现MLP对角高斯策略。
在 exercise1_2.py
中实现你的解决方案,然后运行该文件以自动检查你的工作。
评价标准 你的解决方案将通过在InvertedPendulum-v2 Gym环境中运行20个轮次来进行评估, 这将花费3-5分钟的时间(取决于你的计算机以及在后台运行的其他进程)。 成功的标准是最近5个轮次的平均分数超过500,或者最近5个轮次的达到1000(最大可能分数)。
练习 1.3:TD3的计算图
练习路径 spinup/exercises/problem_set_1/exercise1_3.py
解答路径 spinup/algos/td3/td3.py
指示 实现TD3算法的核心计算图。
作为入门代码,除了计算图外,我们还提供了完整的TD3算法。找到“YOUR CODE HERE”并开始。
你可能会发现在 TD3的页面 中查看伪代码很有用。
在 exercise1_3.py
中实现你的解决方案,然后运行该文件以查看工作结果。此练习没有自动检查。
评价标准 通过使用HalfCheetah-v2,InvertedPendulum-v2和其他所选的Gym MuJoCo环境
(通过 --env
标志设置)运行 exercise1_3.py
来评估代码。
它被设置为使用比TD3典型的较小的神经网络(隐藏的大小为[128,128]),最大剧集长度为150,并且仅运行10个轮次。
目标是要看到相对较快的学习进度(就挂钟时间而言)。实验可能需要约10分钟的时间。
使用 --use_soln
标志来运行Spinning Up的TD3,而不是你的实现。
有趣的是,在10个轮次内,HalfCheetah中的得分应超过300,而InvertedPendulum中的得分应达到150。
问题集2:算法失败模型¶
练习 2.1:值函数在TRPO中的拟合
练习路径 (不适用,没有代码。)
解答路径 解答在这里
许多因素会影响策略梯度算法的性能,但远不及用于优势估计的学习值函数的质量严重。
在本练习中,你将比较TRPO运行之间的结果,投入了大量精力来拟合值函数(train_v_iters=80
)
对比投入很少的精力来拟合值函数(train_v_iters=0
)。
指示 运行以下命令:
python -m spinup.run trpo --env Hopper-v2 --train_v_iters[v] 0 80 --exp_name ex2-1 --epochs 250 --steps_per_epoch 4000 --seed 0 10 20 --dt
并绘制结果。(这些实验每个可能需要10分钟左右的时间,而此命令将运行其中的6个。)你发现了什么?
练习 2.2:DDPG中的静默错误
练习路径 spinup/exercises/problem_set_2/exercise2_2.py
解答路径 解答在这里
编写强化学习代码最困难的部分是处理错误,因为故障通常是静默的。 该代码似乎可以正确运行,但是与无错误的实现相比,该代理的性能将降低,有时甚至永远无法学习任何内容。
在本练习中,你将观察到一个体内的错误,并将结果与正确的代码进行比较。
指示 运行 exercise2_2.py
,这将启动带或不带错误的DDPG实验。
非调试版本运行DDPG的默认Spinning Up实现,并使用默认方法来创建参与者和评论者网络。
除了使用错误的方法创建网络之外,错误的版本运行相同的DDPG代码。
总共将进行六个实验(每种情况下三个随机种子),每个实验都需要10分钟。 完成后,绘制结果。有无bug的性能有何区别?
在没有引用正确的actor-critic代码的情况下(也就是说,不要在DDPG的 core.py
文件中查找),请尝试找出错误所在并解释它是如何破坏的。
提示 要找出问题所在,请考虑DDPG代码如何实现DDPG计算图。具体来说,请看以下片段:
# Bellman backup for Q function
backup = tf.stop_gradient(r_ph + gamma*(1-d_ph)*q_pi_targ)
# DDPG losses
pi_loss = -tf.reduce_mean(q_pi)
q_loss = tf.reduce_mean((q-backup)**2)
actor-critic 代码中的错误如何在这里产生影响?
奖励 是否有任何超参数选择会隐藏该错误的影响?
Spinning Up 算法实现的基准¶
我们在 MuJoCo Gym任务套件中的五个环境中对Spinning Up算法实现进行了基准测试: HalfCheetah,Hopper,Walker2d,Swimmer和Ant。
每个环境中的性能¶
HalfCheetah¶
HalfCheetah-2 环境的 3M 时步性能。
实验细节¶
随机种子 分别对3个随机种子每个运行同轨策略算法(VPG,TPRO,PPO), 对随机10个种子每个运行异策略算法(DDPG,TD3,SAC)。 图表显示了训练过程中随机种子的平均(实线)和标准发展(阴影)。
性能指标 同轨策略算法的性能是通过每个回合收集的批次中的平均轨迹回报来衡量的。 通过在十条轨迹上运行没有动作噪声的确定性策略(或者在SAC的情况下为均值策略), 并报告这些测试轨迹的平均回报,每10,000步就对异轨策略算法的性能进行一次测量。
网络结构 同轨策略算法使用大小为(64,32),带有tanh单元的网络同时用于策略和值函数。 异轨策略算法使用大小为(400,300),具有relu单元的网络。
批次大小 同轨策略上的算法每批更新收集了4000步智能体与环境的交互。异轨策略算法在每个梯度下降步骤使用大小为100的微型批次。
所有其他超参数均保留为Spinning Up实现的默认设置。有关详细信息,请参见算法页面。
Vanilla Policy Gradient¶
背景¶
(前一节:强化学习介绍:第三部分)
策略梯度背后的关键思想是提高导致更高回报的动作的概率,并降低导致更低回报的动作的概率,直到你获得最佳策略。
关键方程¶
令 表示参数为
的策略,
而
表示有限视野无折扣的策略回报期望。
的梯度为
其中 是轨迹,
是当前策略的优势函数。
策略梯度算法的工作原理是通过随机梯度提升策略性能来更新策略参数:
策略梯度实现通常基于无限视野折扣回报来计算优势函数估计,尽管其他情况下使用有限视野无折扣策略梯度公式。
文档¶
-
spinup.
vpg
(env_fn, actor_critic=<function mlp_actor_critic>, ac_kwargs={}, seed=0, steps_per_epoch=4000, epochs=50, gamma=0.99, pi_lr=0.0003, vf_lr=0.001, train_v_iters=80, lam=0.97, max_ep_len=1000, logger_kwargs={}, save_freq=10)[源代码]¶ 参数: - env_fn – A function which creates a copy of the environment. The environment must satisfy the OpenAI Gym API.
- actor_critic –
A function which takes in placeholder symbols for state,
x_ph
, and action,a_ph
, and returns the main outputs from the agent’s Tensorflow computation graph:Symbol Shape Description pi
(batch, act_dim) Samples actions from policy givenstates.logp
(batch,) Gives log probability, according tothe policy, of taking actionsa_ph
in statesx_ph
.logp_pi
(batch,) Gives log probability, according tothe policy, of the action sampled bypi
.v
(batch,) Gives the value estimate for statesinx_ph
. (Critical: make sureto flatten this!) - ac_kwargs (dict) – Any kwargs appropriate for the actor_critic function you provided to VPG.
- seed (int) – Seed for random number generators.
- steps_per_epoch (int) – Number of steps of interaction (state-action pairs) for the agent and the environment in each epoch.
- epochs (int) – Number of epochs of interaction (equivalent to number of policy updates) to perform.
- gamma (float) – Discount factor. (Always between 0 and 1.)
- pi_lr (float) – Learning rate for policy optimizer.
- vf_lr (float) – Learning rate for value function optimizer.
- train_v_iters (int) – Number of gradient descent steps to take on value function per epoch.
- lam (float) – Lambda for GAE-Lambda. (Always between 0 and 1, close to 1.)
- max_ep_len (int) – Maximum length of trajectory / episode / rollout.
- logger_kwargs (dict) – Keyword args for EpochLogger.
- save_freq (int) – How often (in terms of gap between epochs) to save the current policy and value function.
保存的模型的内容¶
记录的计算图包括:
键 | 值 |
---|---|
x |
Tensorflow placeholder for state input. |
pi |
Samples an action from the agent, conditioned on states in x . |
v |
Gives value estimate for states in x . |
可以通过以下方式访问此保存的模型
- 使用 test_policy.py 工具运行经过训练的策略,
- 或使用 restore_tf_graph 将整个保存的图形加载到程序中。
参考¶
相关论文¶
- Policy Gradient Methods for Reinforcement Learning with Function Approximation, Sutton et al. 2000
- Optimizing Expectations: From Deep Reinforcement Learning to Stochastic Computation Graphs, Schulman 2016(a)
- Benchmarking Deep Reinforcement Learning for Continuous Control, Duan et al. 2016
- High Dimensional Continuous Control Using Generalized Advantage Estimation, Schulman et al. 2016(b)
为什么是这些论文?¶
包含Sutton 2000是因为它是强化学习理论的永恒经典,并且包含了导致现代策略梯度的早期工作的参考。 之所以包括Schulman 2016(a),是因为第2章对策略梯度算法(包括伪代码)的理论进行了清晰的介绍。 Duan 2016是一份清晰的,最新的基准论文,显示了深度强化学习设置 (例如,以神经网络策略和Adam为优化器)中的vanilla policy gradient与其他深度强化算法的比较。 之所以包含Schulman 2016(b),是因为我们在VPG的实现中利用了 通用优势估计(Generalized Advantage Estimation)来计算策略梯度。
Trust Region Policy Optimization¶
背景¶
(前一节: VPG背景)
TRPO通过采取最大的可以改进策略的步骤来更新策略,同时满足关于允许新旧策略接近的特殊约束。 约束用 KL散度 表示,KL散度是对概率分布之间的距离(但不完全相同)的一种度量。
这与常规策略梯度不同,后者使新策略和旧策略在参数空间中保持紧密联系。 但是,即使参数空间上看似很小的差异也可能在性能上产生很大的差异──因此,一个糟糕的步骤可能会使策略性能崩溃。 这使得使用大步长的vanilla policy gradients变得危险,从而损害了其采样效率。 TRPO很好地避免了这种崩溃,并且倾向于快速单调地提高性能。
关键方程¶
令 表示参数为
的策略,理论上的TRPO更新为:
其中 是 替代优势,
它使用旧策略中的数据来衡量策略
与旧策略
的相对性能:
是旧策略访问的各状态之间的策略之间的平均散度差异:
你应该知道
当 时,目标和约束都为零。
此外,当
时,约束相对于
的梯度为零。
要证明这些事实,需要对相关数学有一些微妙的掌握──每当您准备就绪时,这都是值得做的练习!
理论上的TRPO更新不是最容易使用的,因此TRPO做出了一些近似以快速获得答案。
我们使用泰勒展开将目标和约束扩展到 周围的首阶指数(leading order):
结果产生一个近似的优化问题,
你应该知道
巧合的是,以 评估的替代优势函数相对于
的梯度
恰好等于策略梯度
!
如果您愿意精通数学,请尝试证明这一点。
这个近似问题可以通过拉格朗日对偶 [1] 的方法来解析地解决,得出的结果是:
如果我们到此为止,并仅使用此最终结果,该算法将准确地计算 自然策略梯度 (Natural Policy Gradient)。 一个问题是,由于泰勒展开式引入的近似误差,这可能无法满足KL约束,或实际上提高了替代优势。 TRPO对此更新规则进行了修改:回溯行搜索,
其中 是回溯系数,
是
满足KL约束并产生正的替代优势的最小非负整数。
Lastly: computing and storing the matrix inverse, , is painfully expensive when dealing with neural network policies with thousands or millions of parameters.
TRPO sidesteps the issue by using the `conjugate gradient`_ algorithm to solve
for
,
requiring only a function which can compute the matrix-vector product
instead of computing and storing the whole matrix
directly.
This is not too hard to do: we set up a symbolic operation to calculate
最后:处理带有成千上万个参数的神经网络策略时,矩阵逆 的计算和存储非常昂贵。
TRPO通过使用 共轭梯度 算法对
求解
来回避问题,
仅需要一个可以计算矩阵矢量乘积
的函数,而不是直接计算和存储整个矩阵
。
这并不难:我们设置了一个符号运算来计算
这样就可以在不计算整个矩阵的情况下提供正确的输出。
[1] | 参见Boyd和Vandenberghe的 凸优化,特别是第2至第5章。 |
探索与利用¶
TRPO trains a stochastic policy in an on-policy way. This means that it explores by sampling actions according to the latest version of its stochastic policy. The amount of randomness in action selection depends on both initial conditions and the training procedure. Over the course of training, the policy typically becomes progressively less random, as the update rule encourages it to exploit rewards that it has already found. This may cause the policy to get trapped in local optima.
TRPO以一种在轨策略方式训练随机策略。这意味着它会根据其随机策略的最新版本通过采样操作来进行探索。 动作选择的随机性取决于初始条件和训练程序。 在训练过程中,由于更新规则鼓励该策略利用已经发现的奖励,因此该策略通常变得越来越少随机性。 这可能会导致策略陷入局部最优状态。
文档¶
-
spinup.
trpo
(env_fn, actor_critic=<function mlp_actor_critic>, ac_kwargs={}, seed=0, steps_per_epoch=4000, epochs=50, gamma=0.99, delta=0.01, vf_lr=0.001, train_v_iters=80, damping_coeff=0.1, cg_iters=10, backtrack_iters=10, backtrack_coeff=0.8, lam=0.97, max_ep_len=1000, logger_kwargs={}, save_freq=10, algo='trpo')[源代码]¶ 参数: - env_fn – A function which creates a copy of the environment. The environment must satisfy the OpenAI Gym API.
- actor_critic –
A function which takes in placeholder symbols for state,
x_ph
, and action,a_ph
, and returns the main outputs from the agent’s Tensorflow computation graph:Symbol Shape Description pi
(batch, act_dim) Samples actions from policy givenstates.logp
(batch,) Gives log probability, according tothe policy, of taking actionsa_ph
in statesx_ph
.logp_pi
(batch,) Gives log probability, according tothe policy, of the action sampled bypi
.info
N/A A dict of any intermediate quantities(from calculating the policy or logprobabilities) which are needed foranalytically computing KL divergence.(eg sufficient statistics of thedistributions)info_phs
N/A A dict of placeholders for old valuesof the entries ininfo
.d_kl
() A symbol for computing the mean KLdivergence between the current policy(pi
) and the old policy (asspecified by the inputs toinfo_phs
) over the batch ofstates given inx_ph
.v
(batch,) Gives the value estimate for statesinx_ph
. (Critical: make sureto flatten this!) - ac_kwargs (dict) – Any kwargs appropriate for the actor_critic function you provided to TRPO.
- seed (int) – Seed for random number generators.
- steps_per_epoch (int) – Number of steps of interaction (state-action pairs) for the agent and the environment in each epoch.
- epochs (int) – Number of epochs of interaction (equivalent to number of policy updates) to perform.
- gamma (float) – Discount factor. (Always between 0 and 1.)
- delta (float) – KL-divergence limit for TRPO / NPG update. (Should be small for stability. Values like 0.01, 0.05.)
- vf_lr (float) – Learning rate for value function optimizer.
- train_v_iters (int) – Number of gradient descent steps to take on value function per epoch.
- damping_coeff (float) –
Artifact for numerical stability, should be smallish. Adjusts Hessian-vector product calculation:
where
is the damping coefficient. Probably don’t play with this hyperparameter.
- cg_iters (int) –
Number of iterations of conjugate gradient to perform. Increasing this will lead to a more accurate approximation to
, and possibly slightly-improved performance, but at the cost of slowing things down.
Also probably don’t play with this hyperparameter.
- backtrack_iters (int) – Maximum number of steps allowed in the backtracking line search. Since the line search usually doesn’t backtrack, and usually only steps back once when it does, this hyperparameter doesn’t often matter.
- backtrack_coeff (float) – How far back to step during backtracking line search. (Always between 0 and 1, usually above 0.5.)
- lam (float) – Lambda for GAE-Lambda. (Always between 0 and 1, close to 1.)
- max_ep_len (int) – Maximum length of trajectory / episode / rollout.
- logger_kwargs (dict) – Keyword args for EpochLogger.
- save_freq (int) – How often (in terms of gap between epochs) to save the current policy and value function.
- algo – Either ‘trpo’ or ‘npg’: this code supports both, since they are almost the same.
保存的模型的内容¶
记录的计算图包括:
键 | 值 |
---|---|
x |
Tensorflow placeholder for state input. |
pi |
Samples an action from the agent, conditioned on states in x . |
v |
Gives value estimate for states in x . |
可以通过以下方式访问此保存的模型
- 使用 test_policy.py 工具运行经过训练的策略,
- 或使用 restore_tf_graph 将整个保存的图形加载到程序中。
参考¶
相关论文¶
- Trust Region Policy Optimization, Schulman et al. 2015
- High Dimensional Continuous Control Using Generalized Advantage Estimation, Schulman et al. 2016
- Approximately Optimal Approximate Reinforcement Learning, Kakade and Langford 2002
Proximal Policy Optimization¶
Table of Contents
背景¶
(前一节: TRPO背景)
PPO受到与TRPO相同的问题的激励:我们如何才能使用当前拥有的数据在策略上采取最大可能的改进步骤, 而又不会走得太远而导致意外使性能下降?在TRPO尝试使用复杂的二阶方法解决此问题的地方, PPO是一阶方法的族,它们使用其他一些技巧来使新策略接近于旧策略。 PPO方法明显更易于实现,并且从经验上看,其性能至少与TRPO相同。
PPO有两种主要变体:PPO-Penalty和PPO-Clip。
PPO-Penalty 近似解决了TRPO之类的受KL约束的更新,但是惩罚了目标函数中的KL背离而不是使其成为硬约束, 并且在训练过程中自动调整了惩罚系数,以便适当地缩放。
PPO-Clip 在目标中没有KL散度项,也没有任何约束。取而代之的是依靠对目标函数的专门削减来消除新策略远离旧策略的动机。
在这里,我们仅关注PPO-Clip(OpenAI使用的主要变体)。
关键方程¶
PPO-clip 通过以下更新策略
通常采取多个步骤(通常是小批量)SGD来最大化目标。这里 是由
其中 是一个(小)超参数,它粗略地说出了新策略与旧策略的距离。
这是一个非常复杂的表述,很难一眼就知道它在做什么,或者它如何帮助使新策略接近旧策略。 事实证明,此目标有一个相当简化的版本 [1],它易于处理(也是我们在代码中实现的版本):
其中
为了弄清楚从中得到的直觉,让我们看一个状态对 ,并分情况考虑。
优势是正的:假设该状态-动作对的优势是正的,在这种情况下,它对目标的贡献减少为
因为优势是正的,所以如果采取行动的可能性更大,也就是说,如果 增加,则目标也会增加。
但是此术语中的最小值限制了目标可以增加的 程度。
一旦
,最小值就会增加,
此项达到
的上限 。
因此:远离旧策略不会使新政策受益。
优势是负的:假设该状态-动作对的优势是负的,在这种情况下,它对目标的贡献减少为
因为优势是负的,所以如果行动变得不太可能(即 减小),则目标将增加。
但是此术语中的最大值限制了可以增加的 程度。
一旦
,最大值就会增加,
此项达到
的上限。
因此,再次:新政策不会因远离旧政策而受益。
到目前为止,我们已经看到剪裁通过消除策略急剧变化的诱因而成为一种调节器,
而超参数 对应于新策略与旧策略的距离的远近,同时仍然有利于实现目标。
你应该知道
尽管这种削减对确保合理的策略更新大有帮助,但仍然有可能最终产生与旧策略相距太远的新策略, 并且不同的PPO实现使用很多技巧来避免这种情况。在此处的实现中,我们使用一种特别简单的方法:提前停止。 如果新策略与旧策略的平均KL散度差距超出阈值,我们将停止采取梯度步骤。
如果你对基本的数学知识和实施细节感到良好,则有必要查看其他实施以了解它们如何处理此问题!
[1] | 请参阅 此说明,以简化PPO-Clip目标的形式。 |
文档¶
-
spinup.
ppo
(env_fn, actor_critic=<function mlp_actor_critic>, ac_kwargs={}, seed=0, steps_per_epoch=4000, epochs=50, gamma=0.99, clip_ratio=0.2, pi_lr=0.0003, vf_lr=0.001, train_pi_iters=80, train_v_iters=80, lam=0.97, max_ep_len=1000, target_kl=0.01, logger_kwargs={}, save_freq=10)[源代码]¶ 参数: - env_fn – A function which creates a copy of the environment. The environment must satisfy the OpenAI Gym API.
- actor_critic –
A function which takes in placeholder symbols for state,
x_ph
, and action,a_ph
, and returns the main outputs from the agent’s Tensorflow computation graph:Symbol Shape Description pi
(batch, act_dim) Samples actions from policy givenstates.logp
(batch,) Gives log probability, according tothe policy, of taking actionsa_ph
in statesx_ph
.logp_pi
(batch,) Gives log probability, according tothe policy, of the action sampled bypi
.v
(batch,) Gives the value estimate for statesinx_ph
. (Critical: make sureto flatten this!) - ac_kwargs (dict) – Any kwargs appropriate for the actor_critic function you provided to PPO.
- seed (int) – Seed for random number generators.
- steps_per_epoch (int) – Number of steps of interaction (state-action pairs) for the agent and the environment in each epoch.
- epochs (int) – Number of epochs of interaction (equivalent to number of policy updates) to perform.
- gamma (float) – Discount factor. (Always between 0 and 1.)
- clip_ratio (float) – Hyperparameter for clipping in the policy objective. Roughly: how far can the new policy go from the old policy while still profiting (improving the objective function)? The new policy can still go farther than the clip_ratio says, but it doesn’t help on the objective anymore. (Usually small, 0.1 to 0.3.)
- pi_lr (float) – Learning rate for policy optimizer.
- vf_lr (float) – Learning rate for value function optimizer.
- train_pi_iters (int) – Maximum number of gradient descent steps to take on policy loss per epoch. (Early stopping may cause optimizer to take fewer than this.)
- train_v_iters (int) – Number of gradient descent steps to take on value function per epoch.
- lam (float) – Lambda for GAE-Lambda. (Always between 0 and 1, close to 1.)
- max_ep_len (int) – Maximum length of trajectory / episode / rollout.
- target_kl (float) – Roughly what KL divergence we think is appropriate between new and old policies after an update. This will get used for early stopping. (Usually small, 0.01 or 0.05.)
- logger_kwargs (dict) – Keyword args for EpochLogger.
- save_freq (int) – How often (in terms of gap between epochs) to save the current policy and value function.
保存的模型的内容¶
记录的计算图包括:
键 | 值 |
---|---|
x |
Tensorflow placeholder for state input. |
pi |
Samples an action from the agent, conditioned on states in x . |
v |
Gives value estimate for states in x . |
可以通过以下方式访问此保存的模型
- 使用 test_policy.py 工具运行经过训练的策略,
- 或使用 restore_tf_graph 将整个保存的图形加载到程序中。
参考¶
相关论文¶
- Proximal Policy Optimization Algorithms, Schulman et al. 2017
- High Dimensional Continuous Control Using Generalized Advantage Estimation, Schulman et al. 2016
- Emergence of Locomotion Behaviours in Rich Environments, Heess et al. 2017
Deep Deterministic Policy Gradient¶
Table of Contents
背景¶
(前一节 Introduction to RL Part 1: The Optimal Q-Function and the Optimal Action)
Deep Deterministic Policy Gradient (DDPG) is an algorithm which concurrently learns a Q-function and a policy. It uses off-policy data and the Bellman equation to learn the Q-function, and uses the Q-function to learn the policy.
This approach is closely connected to Q-learning, and is motivated the same way: if you know the optimal action-value function , then in any given state, the optimal action
can be found by solving
DDPG interleaves learning an approximator to with learning an approximator to
, and it does so in a way which is specifically adapted for environments with continuous action spaces. But what does it mean that DDPG is adapted specifically for environments with continuous action spaces? It relates to how we compute the max over actions in
.
When there are a finite number of discrete actions, the max poses no problem, because we can just compute the Q-values for each action separately and directly compare them. (This also immediately gives us the action which maximizes the Q-value.) But when the action space is continuous, we can’t exhaustively evaluate the space, and solving the optimization problem is highly non-trivial. Using a normal optimization algorithm would make calculating a painfully expensive subroutine. And since it would need to be run every time the agent wants to take an action in the environment, this is unacceptable.
Because the action space is continuous, the function is presumed to be differentiable with respect to the action argument. This allows us to set up an efficient, gradient-based learning rule for a policy
which exploits that fact. Then, instead of running an expensive optimization subroutine each time we wish to compute
, we can approximate it with
. See the 关键方程 section details.
速览¶
- DDPG is an off-policy algorithm.
- DDPG can only be used for environments with continuous action spaces.
- DDPG can be thought of as being deep Q-learning for continuous action spaces.
- The Spinning Up implementation of DDPG does not support parallelization.
关键方程¶
Here, we’ll explain the math behind the two parts of DDPG: learning a Q function, and learning a policy.
The Q-Learning Side of DDPG¶
First, let’s recap the Bellman equation describing the optimal action-value function, . It’s given by
where is shorthand for saying that the next state,
, is sampled by the environment from a distribution
.
This Bellman equation is the starting point for learning an approximator to . Suppose the approximator is a neural network
, with parameters
, and that we have collected a set
of transitions
(where
indicates whether state
is terminal). We can set up a mean-squared Bellman error (MSBE) function, which tells us roughly how closely
comes to satisfying the Bellman equation:
Here, in evaluating , we’ve used a Python convention of evaluating
True
to 1 and False
to zero. Thus, when d==True
—which is to say, when is a terminal state—the Q-function should show that the agent gets no additional rewards after the current state. (This choice of notation corresponds to what we later implement in code.)
Q-learning algorithms for function approximators, such as DQN (and all its variants) and DDPG, are largely based on minimizing this MSBE loss function. There are two main tricks employed by all of them which are worth describing, and then a specific detail for DDPG.
Trick One: Replay Buffers. All standard algorithms for training a deep neural network to approximate make use of an experience replay buffer. This is the set
of previous experiences. In order for the algorithm to have stable behavior, the replay buffer should be large enough to contain a wide range of experiences, but it may not always be good to keep everything. If you only use the very-most recent data, you will overfit to that and things will break; if you use too much experience, you may slow down your learning. This may take some tuning to get right.
你应该知道
We’ve mentioned that DDPG is an off-policy algorithm: this is as good a point as any to highlight why and how. Observe that the replay buffer should contain old experiences, even though they might have been obtained using an outdated policy. Why are we able to use these at all? The reason is that the Bellman equation doesn’t care which transition tuples are used, or how the actions were selected, or what happens after a given transition, because the optimal Q-function should satisfy the Bellman equation for all possible transitions. So any transitions that we’ve ever experienced are fair game when trying to fit a Q-function approximator via MSBE minimization.
Trick Two: Target Networks. Q-learning algorithms make use of target networks. The term
is called the target, because when we minimize the MSBE loss, we are trying to make the Q-function be more like this target. Problematically, the target depends on the same parameters we are trying to train: . This makes MSBE minimization unstable. The solution is to use a set of parameters which comes close to
, but with a time delay—that is to say, a second network, called the target network, which lags the first. The parameters of the target network are denoted
.
In DQN-based algorithms, the target network is just copied over from the main network every some-fixed-number of steps. In DDPG-style algorithms, the target network is updated once per main network update by polyak averaging:
where is a hyperparameter between 0 and 1 (usually close to 1). (This hyperparameter is called
polyak
in our code).
DDPG Detail: Calculating the Max Over Actions in the Target. As mentioned earlier: computing the maximum over actions in the target is a challenge in continuous action spaces. DDPG deals with this by using a target policy network to compute an action which approximately maximizes . The target policy network is found the same way as the target Q-function: by polyak averaging the policy parameters over the course of training.
Putting it all together, Q-learning in DDPG is performed by minimizing the following MSBE loss with stochastic gradient descent:
where is the target policy.
The Policy Learning Side of DDPG¶
Policy learning in DDPG is fairly simple. We want to learn a deterministic policy which gives the action that maximizes
. Because the action space is continuous, and we assume the Q-function is differentiable with respect to action, we can just perform gradient ascent (with respect to policy parameters only) to solve
Note that the Q-function parameters are treated as constants here.
探索与利用¶
DDPG trains a deterministic policy in an off-policy way. Because the policy is deterministic, if the agent were to explore on-policy, in the beginning it would probably not try a wide enough variety of actions to find useful learning signals. To make DDPG policies explore better, we add noise to their actions at training time. The authors of the original DDPG paper recommended time-correlated OU noise, but more recent results suggest that uncorrelated, mean-zero Gaussian noise works perfectly well. Since the latter is simpler, it is preferred. To facilitate getting higher-quality training data, you may reduce the scale of the noise over the course of training. (We do not do this in our implementation, and keep noise scale fixed throughout.)
At test time, to see how well the policy exploits what it has learned, we do not add noise to the actions.
你应该知道
Our DDPG implementation uses a trick to improve exploration at the start of training. For a fixed number of steps at the beginning (set with the start_steps
keyword argument), the agent takes actions which are sampled from a uniform random distribution over valid actions. After that, it returns to normal DDPG exploration.
文档¶
-
spinup.
ddpg
(env_fn, actor_critic=<function mlp_actor_critic>, ac_kwargs={}, seed=0, steps_per_epoch=5000, epochs=100, replay_size=1000000, gamma=0.99, polyak=0.995, pi_lr=0.001, q_lr=0.001, batch_size=100, start_steps=10000, act_noise=0.1, max_ep_len=1000, logger_kwargs={}, save_freq=1)[源代码]¶ 参数: - env_fn – A function which creates a copy of the environment. The environment must satisfy the OpenAI Gym API.
- actor_critic –
A function which takes in placeholder symbols for state,
x_ph
, and action,a_ph
, and returns the main outputs from the agent’s Tensorflow computation graph:Symbol Shape Description pi
(batch, act_dim) Deterministically computes actionsfrom policy given states.q
(batch,) Gives the current estimate of Q* forstates inx_ph
and actions ina_ph
.q_pi
(batch,) Gives the composition ofq
andpi
for states inx_ph
:q(x, pi(x)). - ac_kwargs (dict) – Any kwargs appropriate for the actor_critic function you provided to DDPG.
- seed (int) – Seed for random number generators.
- steps_per_epoch (int) – Number of steps of interaction (state-action pairs) for the agent and the environment in each epoch.
- epochs (int) – Number of epochs to run and train agent.
- replay_size (int) – Maximum length of replay buffer.
- gamma (float) – Discount factor. (Always between 0 and 1.)
- polyak (float) –
Interpolation factor in polyak averaging for target networks. Target networks are updated towards main networks according to:
where
is polyak. (Always between 0 and 1, usually close to 1.)
- pi_lr (float) – Learning rate for policy.
- q_lr (float) – Learning rate for Q-networks.
- batch_size (int) – Minibatch size for SGD.
- start_steps (int) – Number of steps for uniform-random action selection, before running real policy. Helps exploration.
- act_noise (float) – Stddev for Gaussian exploration noise added to policy at training time. (At test time, no noise is added.)
- max_ep_len (int) – Maximum length of trajectory / episode / rollout.
- logger_kwargs (dict) – Keyword args for EpochLogger.
- save_freq (int) – How often (in terms of gap between epochs) to save the current policy and value function.
保存的模型的内容¶
记录的计算图包括:
Key | Value |
---|---|
x |
Tensorflow placeholder for state input. |
a |
Tensorflow placeholder for action input. |
pi |
Deterministically computes an action from the agent, conditioned
on states in
x . |
q |
Gives action-value estimate for states in x and actions in a . |
可以通过以下方式访问此保存的模型
- 使用 test_policy.py 工具运行经过训练的策略,
- 或使用 restore_tf_graph 将整个保存的图形加载到程序中。
参考¶
相关论文¶
- Deterministic Policy Gradient Algorithms, Silver et al. 2014
- Continuous Control With Deep Reinforcement Learning, Lillicrap et al. 2016
Twin Delayed DDPG¶
背景¶
(前一节 背景 for DDPG)
While DDPG can achieve great performance sometimes, it is frequently brittle with respect to hyperparameters and other kinds of tuning. A common failure mode for DDPG is that the learned Q-function begins to dramatically overestimate Q-values, which then leads to the policy breaking, because it exploits the errors in the Q-function. Twin Delayed DDPG (TD3) is an algorithm which addresses this issue by introducing three critical tricks:
Trick One: Clipped Double-Q Learning. TD3 learns two Q-functions instead of one (hence “twin”), and uses the smaller of the two Q-values to form the targets in the Bellman error loss functions.
Trick Two: “Delayed” Policy Updates. TD3 updates the policy (and target networks) less frequently than the Q-function. The paper recommends one policy update for every two Q-function updates.
Trick Three: Target Policy Smoothing. TD3 adds noise to the target action, to make it harder for the policy to exploit Q-function errors by smoothing out Q along changes in action.
Together, these three tricks result in substantially improved performance over baseline DDPG.
速览¶
- TD3 is an off-policy algorithm.
- TD3 can only be used for environments with continuous action spaces.
- The Spinning Up implementation of TD3 does not support parallelization.
关键方程¶
TD3 concurrently learns two Q-functions, and
, by mean square Bellman error minimization, in almost the same way that DDPG learns its single Q-function. To show exactly how TD3 does this and how it differs from normal DDPG, we’ll work from the innermost part of the loss function outwards.
First: target policy smoothing. Actions used to form the Q-learning target are based on the target policy, , but with clipped noise added on each dimension of the action. After adding the clipped noise, the target action is then clipped to lie in the valid action range (all valid actions,
, satisfy
). The target actions are thus:
Target policy smoothing essentially serves as a regularizer for the algorithm. It addresses a particular failure mode that can happen in DDPG: if the Q-function approximator develops an incorrect sharp peak for some actions, the policy will quickly exploit that peak and then have brittle or incorrect behavior. This can be averted by smoothing out the Q-function over similar actions, which target policy smoothing is designed to do.
Next: clipped double-Q learning. Both Q-functions use a single target, calculated using whichever of the two Q-functions gives a smaller target value:
and then both are learned by regressing to this target:
Using the smaller Q-value for the target, and regressing towards that, helps fend off overestimation in the Q-function.
Lastly: the policy is learned just by maximizing :
which is pretty much unchanged from DDPG. However, in TD3, the policy is updated less frequently than the Q-functions are. This helps damp the volatility that normally arises in DDPG because of how a policy update changes the target.
探索与利用¶
TD3 trains a deterministic policy in an off-policy way. Because the policy is deterministic, if the agent were to explore on-policy, in the beginning it would probably not try a wide enough variety of actions to find useful learning signals. To make TD3 policies explore better, we add noise to their actions at training time, typically uncorrelated mean-zero Gaussian noise. To facilitate getting higher-quality training data, you may reduce the scale of the noise over the course of training. (We do not do this in our implementation, and keep noise scale fixed throughout.)
At test time, to see how well the policy exploits what it has learned, we do not add noise to the actions.
你应该知道
Our TD3 implementation uses a trick to improve exploration at the start of training. For a fixed number of steps at the beginning (set with the start_steps
keyword argument), the agent takes actions which are sampled from a uniform random distribution over valid actions. After that, it returns to normal TD3 exploration.
文档¶
-
spinup.
td3
(env_fn, actor_critic=<function mlp_actor_critic>, ac_kwargs={}, seed=0, steps_per_epoch=5000, epochs=100, replay_size=1000000, gamma=0.99, polyak=0.995, pi_lr=0.001, q_lr=0.001, batch_size=100, start_steps=10000, act_noise=0.1, target_noise=0.2, noise_clip=0.5, policy_delay=2, max_ep_len=1000, logger_kwargs={}, save_freq=1)[源代码]¶ 参数: - env_fn – A function which creates a copy of the environment. The environment must satisfy the OpenAI Gym API.
- actor_critic –
A function which takes in placeholder symbols for state,
x_ph
, and action,a_ph
, and returns the main outputs from the agent’s Tensorflow computation graph:Symbol Shape Description pi
(batch, act_dim) Deterministically computes actionsfrom policy given states.q1
(batch,) Gives one estimate of Q* forstates inx_ph
and actions ina_ph
.q2
(batch,) Gives another estimate of Q* forstates inx_ph
and actions ina_ph
.q1_pi
(batch,) Gives the composition ofq1
andpi
for states inx_ph
:q1(x, pi(x)). - ac_kwargs (dict) – Any kwargs appropriate for the actor_critic function you provided to TD3.
- seed (int) – Seed for random number generators.
- steps_per_epoch (int) – Number of steps of interaction (state-action pairs) for the agent and the environment in each epoch.
- epochs (int) – Number of epochs to run and train agent.
- replay_size (int) – Maximum length of replay buffer.
- gamma (float) – Discount factor. (Always between 0 and 1.)
- polyak (float) –
Interpolation factor in polyak averaging for target networks. Target networks are updated towards main networks according to:
where
is polyak. (Always between 0 and 1, usually close to 1.)
- pi_lr (float) – Learning rate for policy.
- q_lr (float) – Learning rate for Q-networks.
- batch_size (int) – Minibatch size for SGD.
- start_steps (int) – Number of steps for uniform-random action selection, before running real policy. Helps exploration.
- act_noise (float) – Stddev for Gaussian exploration noise added to policy at training time. (At test time, no noise is added.)
- target_noise (float) – Stddev for smoothing noise added to target policy.
- noise_clip (float) – Limit for absolute value of target policy smoothing noise.
- policy_delay (int) – Policy will only be updated once every policy_delay times for each update of the Q-networks.
- max_ep_len (int) – Maximum length of trajectory / episode / rollout.
- logger_kwargs (dict) – Keyword args for EpochLogger.
- save_freq (int) – How often (in terms of gap between epochs) to save the current policy and value function.
保存的模型的内容¶
记录的计算图包括:
键 | 值 |
---|---|
x |
Tensorflow placeholder for state input. |
a |
Tensorflow placeholder for action input. |
pi |
Deterministically computes an action from the agent, conditioned
on states in
x . |
q1 |
Gives one action-value estimate for states in x and actions in a . |
q2 |
Gives the other action-value estimate for states in x and actions in a . |
可以通过以下方式访问此保存的模型
- 使用 test_policy.py 工具运行经过训练的策略,
- 或使用 restore_tf_graph 将整个保存的图形加载到程序中。
参考¶
相关论文¶
- Addressing Function Approximation Error in Actor-Critic Methods, Fujimoto et al, 2018
Soft Actor-Critic¶
Table of Contents
背景¶
(前一节 背景 for TD3)
Soft Actor Critic (SAC) is an algorithm which optimizes a stochastic policy in an off-policy way, forming a bridge between stochastic policy optimization and DDPG-style approaches. It isn’t a direct successor to TD3 (having been published roughly concurrently), but it incorporates the clipped double-Q trick, and due to the inherent stochasticity of the policy in SAC, it also winds up benefiting from something like target policy smoothing.
A central feature of SAC is entropy regularization. The policy is trained to maximize a trade-off between expected return and entropy, a measure of randomness in the policy. This has a close connection to the exploration-exploitation trade-off: increasing entropy results in more exploration, which can accelerate learning later on. It can also prevent the policy from prematurely converging to a bad local optimum.
速览¶
- SAC is an off-policy algorithm.
- The version of SAC implemented here can only be used for environments with continuous action spaces.
- An alternate version of SAC, which slightly changes the policy update rule, can be implemented to handle discrete action spaces.
- The Spinning Up implementation of SAC does not support parallelization.
关键方程¶
To explain Soft Actor Critic, we first have to introduce the entropy-regularized reinforcement learning setting. In entropy-regularized RL, there are slightly-different equations for value functions.
Entropy-Regularized Reinforcement Learning¶
Entropy is a quantity which, roughly speaking, says how random a random variable is. If a coin is weighted so that it almost always comes up heads, it has low entropy; if it’s evenly weighted and has a half chance of either outcome, it has high entropy.
Let be a random variable with probability mass or density function
. The entropy
of
is computed from its distribution
according to
In entropy-regularized reinforcement learning, the agent gets a bonus reward at each time step proportional to the entropy of the policy at that timestep. This changes the RL problem to:
where is the trade-off coefficient. (Note: we’re assuming an infinite-horizon discounted setting here, and we’ll do the same for the rest of this page.) We can now define the slightly-different value functions in this setting.
is changed to include the entropy bonuses from every timestep:
is changed to include the entropy bonuses from every timestep except the first:
With these definitions, and
are connected by:
and the Bellman equation for is
你应该知道
The way we’ve set up the value functions in the entropy-regularized setting is a little bit arbitrary, and actually we could have done it differently (eg make include the entropy bonus at the first timestep). The choice of definition may vary slightly across papers on the subject.
Soft Actor-Critic¶
SAC concurrently learns a policy , two Q-functions
, and a value function
.
Learning Q. The Q-functions are learned by MSBE minimization, using a target value network to form the Bellman backups. They both use the same target, like in TD3, and have loss functions:
The target value network, like the target networks in DDPG and TD3, is obtained by polyak averaging the value network parameters over the course of training.
Learning V. The value function is learned by exploiting (a sample-based approximation of) the connection between and
. Before we go into the learning rule, let’s first rewrite the connection equation by using the definition of entropy to obtain:
The RHS is an expectation over actions, so we can approximate it by sampling from the policy:
SAC sets up a mean-squared-error loss for based on this approximation. But what Q-value do we use? SAC uses clipped double-Q like TD3 for learning the value function, and takes the minimum Q-value between the two approximators. So the SAC loss for value function parameters is:
Importantly, we do not use actions from the replay buffer here: these actions are sampled fresh from the current version of the policy.
Learning the Policy. The policy should, in each state, act to maximize the expected future return plus expected future entropy. That is, it should maximize , which we expand out (as before) into
The way we optimize the policy makes use of the reparameterization trick, in which a sample from is drawn by computing a deterministic function of state, policy parameters, and independent noise. To illustrate: following the authors of the SAC paper, we use a squashed Gaussian policy, which means that samples are obtained according to
你应该知道
This policy has two key differences from the policies we use in the other policy optimization algorithms:
1. The squashing function. The in the SAC policy ensures that actions are bounded to a finite range. This is absent in the VPG, TRPO, and PPO policies. It also changes the distribution: before the
the SAC policy is a factored Gaussian like the other algorithms’ policies, but after the
it is not. (You can still compute the log-probabilities of actions in closed form, though: see the paper appendix for details.)
2. The way standard deviations are parameterized. In VPG, TRPO, and PPO, we represent the log std devs with state-independent parameter vectors. In SAC, we represent the log std devs as outputs from the neural network, meaning that they depend on state in a complex way. SAC with state-independent log std devs, in our experience, did not work. (Can you think of why? Or better yet: run an experiment to verify?)
The reparameterization trick allows us to rewrite the expectation over actions (which contains a pain point: the distribution depends on the policy parameters) into an expectation over noise (which removes the pain point: the distribution now has no dependence on parameters):
To get the policy loss, the final step is that we need to substitute with one of our function approximators. The same as in TD3, we use
. The policy is thus optimized according to
which is almost the same as the DDPG and TD3 policy optimization, except for the stochasticity and entropy term.
探索与利用¶
SAC trains a stochastic policy with entropy regularization, and explores in an on-policy way. The entropy regularization coefficient explicitly controls the explore-exploit tradeoff, with higher
corresponding to more exploration, and lower
corresponding to more exploitation. The right coefficient (the one which leads to the stablest / highest-reward learning) may vary from environment to environment, and could require careful tuning.
At test time, to see how well the policy exploits what it has learned, we remove stochasticity and use the mean action instead of a sample from the distribution. This tends to improve performance over the original stochastic policy.
你应该知道
Our SAC implementation uses a trick to improve exploration at the start of training. For a fixed number of steps at the beginning (set with the start_steps
keyword argument), the agent takes actions which are sampled from a uniform random distribution over valid actions. After that, it returns to normal SAC exploration.
文档¶
-
spinup.
sac
(env_fn, actor_critic=<function mlp_actor_critic>, ac_kwargs={}, seed=0, steps_per_epoch=5000, epochs=100, replay_size=1000000, gamma=0.99, polyak=0.995, lr=0.001, alpha=0.2, batch_size=100, start_steps=10000, max_ep_len=1000, logger_kwargs={}, save_freq=1)[源代码]¶ 参数: - env_fn – A function which creates a copy of the environment. The environment must satisfy the OpenAI Gym API.
- actor_critic –
A function which takes in placeholder symbols for state,
x_ph
, and action,a_ph
, and returns the main outputs from the agent’s Tensorflow computation graph:Symbol Shape Description mu
(batch, act_dim) Computes mean actions from policygiven states.pi
(batch, act_dim) Samples actions from policy givenstates.logp_pi
(batch,) Gives log probability, according tothe policy, of the action sampled bypi
. Critical: must be differentiablewith respect to policy parameters allthe way through action sampling.q1
(batch,) Gives one estimate of Q* forstates inx_ph
and actions ina_ph
.q2
(batch,) Gives another estimate of Q* forstates inx_ph
and actions ina_ph
.q1_pi
(batch,) Gives the composition ofq1
andpi
for states inx_ph
:q1(x, pi(x)).q2_pi
(batch,) Gives the composition ofq2
andpi
for states inx_ph
:q2(x, pi(x)).v
(batch,) Gives the value estimate for statesinx_ph
. - ac_kwargs (dict) – Any kwargs appropriate for the actor_critic function you provided to SAC.
- seed (int) – Seed for random number generators.
- steps_per_epoch (int) – Number of steps of interaction (state-action pairs) for the agent and the environment in each epoch.
- epochs (int) – Number of epochs to run and train agent.
- replay_size (int) – Maximum length of replay buffer.
- gamma (float) – Discount factor. (Always between 0 and 1.)
- polyak (float) –
Interpolation factor in polyak averaging for target networks. Target networks are updated towards main networks according to:
where
is polyak. (Always between 0 and 1, usually close to 1.)
- lr (float) – Learning rate (used for both policy and value learning).
- alpha (float) – Entropy regularization coefficient. (Equivalent to inverse of reward scale in the original SAC paper.)
- batch_size (int) – Minibatch size for SGD.
- start_steps (int) – Number of steps for uniform-random action selection, before running real policy. Helps exploration.
- max_ep_len (int) – Maximum length of trajectory / episode / rollout.
- logger_kwargs (dict) – Keyword args for EpochLogger.
- save_freq (int) – How often (in terms of gap between epochs) to save the current policy and value function.
保存的模型的内容¶
记录的计算图包括:
键 | 值 |
---|---|
x |
Tensorflow placeholder for state input. |
a |
Tensorflow placeholder for action input. |
mu |
Deterministically computes mean action from the agent, given states in x . |
pi |
Samples an action from the agent, conditioned on states in x . |
q1 |
Gives one action-value estimate for states in x and actions in a . |
q2 |
Gives the other action-value estimate for states in x and actions in a . |
v |
Gives the value estimate for states in x . |
可以通过以下方式访问此保存的模型
- 使用 test_policy.py 工具运行经过训练的策略,
- 或使用 restore_tf_graph 将整个保存的图形加载到程序中。
注意:对于SAC,正确的评估策略由 mu
而不是 pi
给出。可以将策略 pi
视为探索策略,而将 mu
视为开发策略。
日志记录¶
使用Logger¶
Spinning Up 提供了基本的日志工具,在 Logger 和 EpochLogger 类中实现。 Logger类包含用于保存诊断,超参数配置,训练运行的状态和训练好的模型。 EpochLogger类在其之上添加了一层,以便于在每个轮次和整个MPI工作者之间轻松跟踪诊断的平均值,标准差,最小值和最大值。
你应该知道
所有 Spinning Up 算法实现使用了 EpochLogger。
例子¶
首先,让我们看一个简单的示例,说明EpochLogger如何跟踪诊断值:
>>> from spinup.utils.logx import EpochLogger
>>> epoch_logger = EpochLogger()
>>> for i in range(10):
epoch_logger.store(Test=i)
>>> epoch_logger.log_tabular('Test', with_min_and_max=True)
>>> epoch_logger.dump_tabular()
-------------------------------------
| AverageTest | 4.5 |
| StdTest | 2.87 |
| MaxTest | 9 |
| MinTest | 0 |
-------------------------------------
store
方法用于将所有 Test
值保存到 epoch_logger
的内部状态。
然后,在调用 log_tabular
时,它将计算内部状态下所有值的 Test
的平均值,标准偏差,最小值和最大值。
调用 log_tabular
之后,内部状态会清除干净(以防止在下一个轮次泄漏到统计信息中)。
最后,调用 dump_tabular
将诊断信息写入文件和标准输出。
接下来,让我们看一下包含日志记录的完整训练过程,以突出显示配置和模型保存以及诊断记录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | import numpy as np
import tensorflow as tf
import time
from spinup.utils.logx import EpochLogger
def mlp(x, hidden_sizes=(32,), activation=tf.tanh, output_activation=None):
for h in hidden_sizes[:-1]:
x = tf.layers.dense(x, units=h, activation=activation)
return tf.layers.dense(x, units=hidden_sizes[-1], activation=output_activation)
# Simple script for training an MLP on MNIST.
def train_mnist(steps_per_epoch=100, epochs=5,
lr=1e-3, layers=2, hidden_size=64,
logger_kwargs=dict(), save_freq=1):
logger = EpochLogger(**logger_kwargs)
logger.save_config(locals())
# Load and preprocess MNIST data
(x_train, y_train), _ = tf.keras.datasets.mnist.load_data()
x_train = x_train.reshape(-1, 28*28) / 255.0
# Define inputs & main outputs from computation graph
x_ph = tf.placeholder(tf.float32, shape=(None, 28*28))
y_ph = tf.placeholder(tf.int32, shape=(None,))
logits = mlp(x_ph, hidden_sizes=[hidden_size]*layers + [10], activation=tf.nn.relu)
predict = tf.argmax(logits, axis=1, output_type=tf.int32)
# Define loss function, accuracy, and training op
y = tf.one_hot(y_ph, 10)
loss = tf.losses.softmax_cross_entropy(y, logits)
acc = tf.reduce_mean(tf.cast(tf.equal(y_ph, predict), tf.float32))
train_op = tf.train.AdamOptimizer().minimize(loss)
# Prepare session
sess = tf.Session()
sess.run(tf.global_variables_initializer())
# Setup model saving
logger.setup_tf_saver(sess, inputs={'x': x_ph},
outputs={'logits': logits, 'predict': predict})
start_time = time.time()
# Run main training loop
for epoch in range(epochs):
for t in range(steps_per_epoch):
idxs = np.random.randint(0, len(x_train), 32)
feed_dict = {x_ph: x_train[idxs],
y_ph: y_train[idxs]}
outs = sess.run([loss, acc, train_op], feed_dict=feed_dict)
logger.store(Loss=outs[0], Acc=outs[1])
# Save model
if (epoch % save_freq == 0) or (epoch == epochs-1):
logger.save_state(state_dict=dict(), itr=None)
# Log info about epoch
logger.log_tabular('Epoch', epoch)
logger.log_tabular('Acc', with_min_and_max=True)
logger.log_tabular('Loss', average_only=True)
logger.log_tabular('TotalGradientSteps', (epoch+1)*steps_per_epoch)
logger.log_tabular('Time', time.time()-start_time)
logger.dump_tabular()
if __name__ == '__main__':
train_mnist()
|
In this example, observe that
- 第19行,logger.save_config 用来将超参数配置保存到JSON文件中。
- 第42和43行,logger.setup_tf_saver 用于准备日志记录以保存计算图的关键元素。
- 第54行,通过`logger.store`_ 将诊断保存到日志记录的内部状态。
- 第58行,计算图每个轮次通过 logger.save_state 保存一次。
- 第61-66行,logger.log_tabular 和 logger.dump_tabular 用于将轮次诊断写入文件。 请注意,传递到 logger.log_tabular 的键与传递到 logger.store 的键相同。
Logger类¶
-
class
spinup.utils.logx.
Logger
(output_dir=None, output_fname='progress.txt', exp_name=None)[源代码]¶ A general-purpose logger.
Makes it easy to save diagnostics, hyperparameter configurations, the state of a training run, and the trained model.
-
__init__
(output_dir=None, output_fname='progress.txt', exp_name=None)[源代码]¶ Initialize a Logger.
参数: - output_dir (string) – A directory for saving results to. If
None
, defaults to a temp directory of the form/tmp/experiments/somerandomnumber
. - output_fname (string) – Name for the tab-separated-value file
containing metrics logged throughout a training run.
Defaults to
progress.txt
. - exp_name (string) – Experiment name. If you run multiple training
runs and give them all the same
exp_name
, the plotter will know to group them. (Use case: if you run the same hyperparameter configuration with multiple random seeds, you should give them all the sameexp_name
.)
- output_dir (string) – A directory for saving results to. If
-
dump_tabular
()[源代码]¶ Write all of the diagnostics from the current iteration.
Writes both to stdout, and to the output file.
-
log_tabular
(key, val)[源代码]¶ Log a value of some diagnostic.
Call this only once for each diagnostic quantity, each iteration. After using
log_tabular
to store values for each diagnostic, make sure to calldump_tabular
to write them out to file and stdout (otherwise they will not get saved anywhere).
-
save_config
(config)[源代码]¶ Log an experiment configuration.
Call this once at the top of your experiment, passing in all important config vars as a dict. This will serialize the config to JSON, while handling anything which can’t be serialized in a graceful way (writing as informative a string as possible).
Example use:
logger = EpochLogger(**logger_kwargs) logger.save_config(locals())
-
save_state
(state_dict, itr=None)[源代码]¶ Saves the state of an experiment.
To be clear: this is about saving state, not logging diagnostics. All diagnostic logging is separate from this function. This function will save whatever is in
state_dict
—usually just a copy of the environment—and the most recent parameters for the model you previously set up saving for withsetup_tf_saver
.Call with any frequency you prefer. If you only want to maintain a single state and overwrite it at each call with the most recent version, leave
itr=None
. If you want to keep all of the states you save, provide unique (increasing) values for ‘itr’.参数: - state_dict (dict) – Dictionary containing essential elements to describe the current state of training.
- itr – An int, or None. Current iteration of training.
-
setup_tf_saver
(sess, inputs, outputs)[源代码]¶ Set up easy model saving for tensorflow.
Call once, after defining your computation graph but before training.
参数: - sess – The Tensorflow session in which you train your computation graph.
- inputs (dict) – A dictionary that maps from keys of your choice to the tensorflow placeholders that serve as inputs to the computation graph. Make sure that all of the placeholders needed for your outputs are included!
- outputs (dict) – A dictionary that maps from keys of your choice to the outputs from your computation graph.
-
-
class
spinup.utils.logx.
EpochLogger
(*args, **kwargs)[源代码]¶ Bases:
spinup.utils.logx.Logger
A variant of Logger tailored for tracking average values over epochs.
Typical use case: there is some quantity which is calculated many times throughout an epoch, and at the end of the epoch, you would like to report the average / std / min / max value of that quantity.
With an EpochLogger, each time the quantity is calculated, you would use
epoch_logger.store(NameOfQuantity=quantity_value)
to load it into the EpochLogger’s state. Then at the end of the epoch, you would use
epoch_logger.log_tabular(NameOfQuantity, **options)
to record the desired values.
-
log_tabular
(key, val=None, with_min_and_max=False, average_only=False)[源代码]¶ Log a value or possibly the mean/std/min/max values of a diagnostic.
参数: - key (string) – The name of the diagnostic. If you are logging a
diagnostic whose state has previously been saved with
store
, the key here has to match the key you used there. - val – A value for the diagnostic. If you have previously saved
values for this key via
store
, do not provide aval
here. - with_min_and_max (bool) – If true, log min and max values of the diagnostic over the epoch.
- average_only (bool) – If true, do not log the standard deviation of the diagnostic over the epoch.
- key (string) – The name of the diagnostic. If you are logging a
diagnostic whose state has previously been saved with
-
加载保存的图¶
-
spinup.utils.logx.
restore_tf_graph
(sess, fpath)[源代码]¶ Loads graphs saved by Logger.
Will output a dictionary whose keys and values are from the ‘inputs’ and ‘outputs’ dict you specified with logger.setup_tf_saver().
参数: - sess – A Tensorflow session.
- fpath – Filepath to save directory.
返回: A dictionary mapping from keys to tensors in the computation graph loaded from
fpath
.
当你使用此方法还原由Spinning Up实现保存的图时,可以最少期望它包括以下内容:
键 | 值 |
---|---|
x |
Tensorflow 状态输入占位符。 |
pi |
以 x 中的状态为条件,从智能体中采样动作。 |
通常还存储算法的相关值函数。 有关给定算法还能保存哪些内容的详细信息,请参见其文档页面。
MPI工具¶
核心MPI工具¶
-
spinup.utils.mpi_tools.
mpi_fork
(n, bind_to_core=False)[源代码]¶ Re-launches the current script with workers linked by MPI.
Also, terminates the original process that launched it.
Taken almost without modification from the Baselines function of the same name.
参数: - n (int) – Number of process to split into.
- bind_to_core (bool) – Bind each MPI process to a core.
-
spinup.utils.mpi_tools.
mpi_statistics_scalar
(x, with_min_and_max=False)[源代码]¶ Get mean/std and optional min/max of scalar x across MPI processes.
参数: - x – An array containing samples of the scalar to produce statistics for.
- with_min_and_max (bool) – If true, return min and max of x in addition to mean and std.
MPI + Tensorflow 工具¶
spinup.utils.mpi_tf
包含一些工具,可以轻松地在许多MPI流程中使用AdamOptimizer。
这有点极客──如果你正在寻找更复杂和通用的东西,请考虑 horovod。
-
class
spinup.utils.mpi_tf.
MpiAdamOptimizer
(**kwargs)[源代码]¶ Adam optimizer that averages gradients across MPI processes.
The compute_gradients method is taken from Baselines MpiAdamOptimizer. For documentation on method arguments, see the Tensorflow docs page for the base AdamOptimizer.
运行工具¶
ExperimentGrid¶
Spinning Up提供了一个叫ExperimentGrid的工具,可简化超参数。 这是基于 rllab工具 的(但比它简单),该工具名为VariantGenerator。
-
class
spinup.utils.run_utils.
ExperimentGrid
(name='')[源代码]¶ Tool for running many experiments given hyperparameter ranges.
-
add
(key, vals, shorthand=None, in_name=False)[源代码]¶ Add a parameter (key) to the grid config, with potential values (vals).
By default, if a shorthand isn’t given, one is automatically generated from the key using the first three letters of each colon-separated term. To disable this behavior, change
DEFAULT_SHORTHAND
in thespinup/user_config.py
file toFalse
.参数: - key (string) – Name of parameter.
- vals (value or list of values) – Allowed values of parameter.
- shorthand (string) – Optional, shortened name of parameter. For
example, maybe the parameter
steps_per_epoch
is shortened tosteps
. - in_name (bool) – When constructing variant names, force the inclusion of this parameter into the name.
-
run
(thunk, num_cpu=1, data_dir=None, datestamp=False)[源代码]¶ Run each variant in the grid with function ‘thunk’.
Note: ‘thunk’ must be either a callable function, or a string. If it is a string, it must be the name of a parameter whose values are all callable functions.
Uses
call_experiment
to actually launch each experiment, and gives each variant a name usingself.variant_name()
.Maintenance note: the args for ExperimentGrid.run should track closely to the args for call_experiment. However,
seed
is omitted because we presume the user may add it as a parameter in the grid.
-
variant_name
(variant)[源代码]¶ Given a variant (dict of valid param/value pairs), make an exp_name.
A variant’s name is constructed as the grid name (if you’ve given it one), plus param names (or shorthands if available) and values separated by underscores.
Note: if
seed
is a parameter, it is not included in the name.
-
variants
()[源代码]¶ Makes a list of dicts, where each dict is a valid config in the grid.
There is special handling for variant parameters whose names take the form
'full:param:name'
.The colons are taken to indicate that these parameters should have a nested dict structure. eg, if there are two params,
Key Val 'base:param:a'
1 'base:param:b'
2 the variant dict will have the structure
variant = { base: { param : { a : 1, b : 2 } } }
-
运行实验¶
-
spinup.utils.run_utils.
call_experiment
(exp_name, thunk, seed=0, num_cpu=1, data_dir=None, datestamp=False, **kwargs)[源代码]¶ Run a function (thunk) with hyperparameters (kwargs), plus configuration.
This wraps a few pieces of functionality which are useful when you want to run many experiments in sequence, including logger configuration and splitting into multiple processes for MPI.
There’s also a SpinningUp-specific convenience added into executing the thunk: if
env_name
is one of the kwargs passed to call_experiment, it’s assumed that the thunk accepts an argument calledenv_fn
, and that theenv_fn
should make a gym environment with the givenenv_name
.The way the experiment is actually executed is slightly complicated: the function is serialized to a string, and then
run_entrypoint.py
is executed in a subprocess call with the serialized string as an argument.run_entrypoint.py
unserializes the function call and executes it. We choose to do it this way—instead of just calling the function directly here—to avoid leaking state between successive experiments.参数: - exp_name (string) – Name for experiment.
- thunk (callable) – A python function.
- seed (int) – Seed for random number generators.
- num_cpu (int) – Number of MPI processes to split into. Also accepts ‘auto’, which will set up as many procs as there are cpus on the machine.
- data_dir (string) – Used in configuring the logger, to decide where
to store experiment results. Note: if left as None, data_dir will
default to
DEFAULT_DATA_DIR
fromspinup/user_config.py
. - **kwargs – All kwargs to pass to thunk.
-
spinup.utils.run_utils.
setup_logger_kwargs
(exp_name, seed=None, data_dir=None, datestamp=False)[源代码]¶ Sets up the output_dir for a logger and returns a dict for logger kwargs.
If no seed is given and datestamp is false,
output_dir = data_dir/exp_name
If a seed is given and datestamp is false,
output_dir = data_dir/exp_name/exp_name_s[seed]
If datestamp is true, amend to
output_dir = data_dir/YY-MM-DD_exp_name/YY-MM-DD_HH-MM-SS_exp_name_s[seed]
You can force datestamp=True by setting
FORCE_DATESTAMP=True
inspinup/user_config.py
.参数: - exp_name (string) – Name for experiment.
- seed (int) – Seed for random number generators used by experiment.
- data_dir (string) – Path to folder where results should be saved.
Default is the
DEFAULT_DATA_DIR
inspinup/user_config.py
. - datestamp (bool) – Whether to include a date and timestamp in the name of the save directory.
返回: logger_kwargs, a dict containing output_dir and exp_name.
致谢¶
我们非常感谢许多帮助使该项目起步的人的贡献,其中包括对软件进行Beta测试,提供了材料反馈, 改进了Spinning Up代码在此版本中的服务依赖性,或者以其他方式支持该项目的人们的贡献。 考虑到涉及不同地点的人员数量,此名称列表可能并不详尽。(如果您认为自己应该在此处列出,请随时与我们联系。)
名单不分先后,感谢 Alex Ray,Amanda Askell,Ben Garfinkel,Christy Dennison,Coline Devin, Daniel Zeigler,Dylan Hadfield-Menell,Ge Yang,Greg Khan,Jack Clark, Jonas Rothfuss,Larissa Schiavo,Leandro Castelao,Lilian Weng ,Maddie Hall, Matthias Plappert,Miles Brundage,Peter Zokhov和Pieter Abbeel。
我们也感谢伯克利的Pieter Abbeel小组和人类相容AI中心(Center for Human-Compatible AI)对有关Spinning Up的演讲提供了反馈。