• 文档 >
  • TorchRL 模块入门
快捷方式

TorchRL 模块入门

作者: Vincent Moens

注意

要在 notebook 中运行此教程,请在开头添加一个包含以下内容的安装单元格:

!pip install tensordict
!pip install torchrl

强化学习旨在创建能够有效解决特定任务的策略。策略可以采取各种形式,从可微分的映射(将观测空间映射到动作空间),到更临时的方法(例如对每个可能动作计算的值列表执行 argmax)。策略可以是确定性的或随机的,并且可能包含复杂元素,例如循环神经网络 (RNN) 或 Transformer。

适应所有这些场景可能相当复杂。在这个简洁的教程中,我们将深入研究 TorchRL 在策略构建方面的核心功能。我们将主要关注两种常见场景下的随机策略和 Q 值策略:使用多层感知机 (MLP) 或卷积神经网络 (CNN) 作为骨干网络。

TensorDict模块(TensorDictModules)

与环境如何与 TensorDict 实例交互类似,用于表示策略和值函数的模块也执行相同的操作。核心思想很简单:将一个标准的 Module(或任何其他函数)封装在一个类中,该类知道哪些条目需要被读取并传递给模块,然后将结果记录到指定的条目中。为了说明这一点,我们将使用最简单的策略:从观测空间到动作空间的确定性映射。为了最大限度地提高通用性,我们将使用一个 LazyLinear 模块和我们在上一个教程中实例化的 Pendulum 环境。

import torch

from tensordict.nn import TensorDictModule
from torchrl.envs import GymEnv

env = GymEnv("Pendulum-v1")
module = torch.nn.LazyLinear(out_features=env.action_spec.shape[-1])
policy = TensorDictModule(
    module,
    in_keys=["observation"],
    out_keys=["action"],
)

这就是执行我们策略所需的全部内容!使用惰性模块使我们能够绕过获取观测空间形状的需求,因为模块会自动确定它。这个策略现在可以在环境中运行了。

rollout = env.rollout(max_steps=10, policy=policy)
print(rollout)

专用包装器(Specialized wrappers)

为了简化 Actor、# ProbabilisticActor、# ActorValueOperator 或 # ActorCriticOperator 的集成。例如,Actorin_keysout_keys 提供了默认值,使得与许多常见环境的集成变得直接。

from torchrl.modules import Actor

policy = Actor(module)
rollout = env.rollout(max_steps=10, policy=policy)
print(rollout)

可用的专用 TensorDictModules 列表可在API 参考中找到。

网络(Networks)

TorchRL 还提供可以使用而无需依赖 TensorDict 功能的常规模块。您会遇到的两个最常见的网络是 MLPConvNet (CNN) 模块。我们可以用其中一个替换我们的策略模块。

from torchrl.modules import MLP

module = MLP(
    out_features=env.action_spec.shape[-1],
    num_cells=[32, 64],
    activation_class=torch.nn.Tanh,
)
policy = Actor(module)
rollout = env.rollout(max_steps=10, policy=policy)

TorchRL 还支持基于 RNN 的策略。由于这是一个更技术性的主题,因此在单独的教程中进行了处理。

概率策略(Probabilistic policies)

PPO 这样的策略优化算法要求策略是随机的:与上述示例不同,模块现在编码从观测空间到参数空间的映射,该参数空间编码了对可能动作的分布。TorchRL 通过将各种操作(例如从参数构建分布、从该分布采样以及检索对数概率)分组到一个单一类中来促进此类模块的设计。在这里,我们将构建一个依赖于正则正态分布的 actor,使用三个组件:

  • 一个 MLP 骨干网络,读取大小为 [3] 的观测值,并输出一个大小为 [2] 的单一张量;

  • 一个 NormalParamExtractor 模块,它将此输出分成两块,一个均值(mean)和一个标准差(standard deviation),大小均为 [1]

  • 一个 ProbabilisticActor,它将这些参数作为 in_keys 读取,用它们创建一个分布,并使用样本和对数概率填充我们的 TensorDict。

from tensordict.nn.distributions import NormalParamExtractor
from torch.distributions import Normal
from torchrl.modules import ProbabilisticActor

backbone = MLP(in_features=3, out_features=2)
extractor = NormalParamExtractor()
module = torch.nn.Sequential(backbone, extractor)
td_module = TensorDictModule(module, in_keys=["observation"], out_keys=["loc", "scale"])
policy = ProbabilisticActor(
    td_module,
    in_keys=["loc", "scale"],
    out_keys=["action"],
    distribution_class=Normal,
    return_log_prob=True,
)

rollout = env.rollout(max_steps=10, policy=policy)
print(rollout)

关于这次 roll out 有几点需要注意:

  • 正如我们在构建 actor 时所要求的那样,当时给定分布下动作的对数概率也已写入。这对于像 PPO 这样的算法是必需的。

  • 分布的参数也作为 "loc""scale" 条目返回到输出 TensorDict 中。

您可以控制动作的采样,如果您的应用程序需要,可以使用分布的期望值或其他属性,而不是使用随机样本。这可以通过 set_exploration_type() 函数来控制。

from torchrl.envs.utils import ExplorationType, set_exploration_type

with set_exploration_type(ExplorationType.DETERMINISTIC):
    # takes the mean as action
    rollout = env.rollout(max_steps=10, policy=policy)
with set_exploration_type(ExplorationType.RANDOM):
    # Samples actions according to the dist
    rollout = env.rollout(max_steps=10, policy=policy)

请查阅文档字符串中的 default_interaction_type 关键字参数以了解更多信息。

探索(Exploration)

像这样的随机策略在一定程度上自然地权衡了探索和利用,但确定性策略则不会。幸运的是,TorchRL 也可以通过其探索模块来弥补这一点。我们将以 EGreedyModule 探索模块为例(也请查看 AdditiveGaussianModuleOrnsteinUhlenbeckProcessModule)。为了看到这个模块的作用,让我们回到一个确定性策略。

from tensordict.nn import TensorDictSequential
from torchrl.modules import EGreedyModule

policy = Actor(MLP(3, 1, num_cells=[32, 64]))

我们的 \(\epsilon\)-greedy 探索模块通常会通过一些退火帧数和 \(\epsilon\) 参数的初始值进行定制。 \(\epsilon = 1\) 的值意味着采取的每个动作都是随机的,而 \(\epsilon = 0\) 意味着根本没有探索。要对探索因子进行退火(即减小),需要调用 step()(请参阅上一个教程以获取示例)。

exploration_module = EGreedyModule(
    spec=env.action_spec, annealing_num_steps=1000, eps_init=0.5
)

要构建我们的探索性策略,我们只需将确定性策略模块与探索模块串联在 TensorDictSequential 模块中(这相当于 TensorDict 领域中的 Sequential)。

exploration_policy = TensorDictSequential(policy, exploration_module)

with set_exploration_type(ExplorationType.DETERMINISTIC):
    # Turns off exploration
    rollout = env.rollout(max_steps=10, policy=exploration_policy)
with set_exploration_type(ExplorationType.RANDOM):
    # Turns on exploration
    rollout = env.rollout(max_steps=10, policy=exploration_policy)

因为它必须能够在动作空间中采样随机动作,所以 EGreedyModule 必须配备环境的 action_space,以便知道采用何种策略来随机采样动作。

Q 值 actor(Q-Value actors)

在某些设置中,策略不是一个独立的模块,而是构建在另一个模块之上。Q 值 actor 就是这种情况。简而言之,这些 actor 需要对动作值(大多数情况下是离散的)进行估计,并贪婪地选择具有最高值的动作。在某些设置中(有限的离散动作空间和有限的离散状态空间),人们可以直接存储一个状态-动作对的二维表格,并选择具有最高值的动作。DQN 带来的创新是通过利用神经网络来编码 Q(s, a) 值映射,从而将其扩展到连续状态空间。让我们考虑一个具有离散动作空间的另一个环境,以便更清楚地理解。

env = GymEnv("CartPole-v1")
print(env.action_spec)

我们构建一个值网络,当它读取环境中的状态时,为每个动作产生一个值。

num_actions = 2
value_net = TensorDictModule(
    MLP(out_features=num_actions, num_cells=[32, 32]),
    in_keys=["observation"],
    out_keys=["action_value"],
)

通过在我们的值网络之后添加一个 QValueModule,我们可以轻松构建我们的 Q 值 actor。

from torchrl.modules import QValueModule

policy = TensorDictSequential(
    value_net,  # writes action values in our tensordict
    QValueModule(spec=env.action_spec),  # Reads the "action_value" entry by default
)

我们来试一试!我们运行策略几个步骤,并查看输出。我们应该在获得的 roll out 中找到 "action_value""chosen_action_value" 条目。

rollout = env.rollout(max_steps=3, policy=policy)
print(rollout)

因为它依赖于 argmax 运算符,所以这个策略是确定性的。在数据收集期间,我们需要探索环境。为此,我们再次使用 EGreedyModule

policy_explore = TensorDictSequential(policy, EGreedyModule(env.action_spec))

with set_exploration_type(ExplorationType.RANDOM):
    rollout_explore = env.rollout(max_steps=3, policy=policy_explore)

关于使用 TorchRL 构建策略的简短教程就到此为止了!

您可以使用该库做更多事情。一个好的起点是查看模块的 API 参考

下一步

  • 了解当动作为复合(例如,环境需要离散和连续动作)时如何使用 CompositeDistribution

  • 了解如何在策略中使用 RNN(参阅教程);

  • 将其与决策 Transformer 示例中的 Transformer 使用进行比较(请参阅 GitHub 上的 example 目录)。

Gallery 由 Sphinx-Gallery 生成

文档

访问全面的 PyTorch 开发者文档

查看文档

教程

获取面向初学者和高级开发者的深度教程

查看教程

资源

查找开发资源并解答您的疑问

查看资源