注意
转到末尾 下载完整的示例代码。
使用 TorchRL 的多智能体强化学习 (PPO) 教程¶
作者: Matteo Bettini
另请参阅
BenchMARL 库提供了使用 TorchRL 实现的最新 MARL 算法。
本教程演示了如何使用 PyTorch 和 torchrl
解决多智能体强化学习 (MARL) 问题。
为了便于使用,本教程将遵循已有教程的总体结构: 使用 TorchRL 的强化学习 (PPO) 教程。建议(非强制)在开始本教程之前熟悉该教程。
在本教程中,我们将使用 VMAS 中的 Navigation 环境,这是一个多机器人模拟器,同样基于 PyTorch,可在设备上运行并行批量模拟。
在 Navigation 环境中,我们需要训练多个机器人(随机位置生成)导航至其目标(也随机位置生成),同时使用 LIDAR 传感器 避免彼此之间发生碰撞。

多智能体 Navigation 场景¶
主要学习内容
如何在 TorchRL 中创建多智能体环境,其 specs 的工作原理以及如何与库集成;
如何在 TorchRL 中使用 GPU 向量化环境;
如何在 TorchRL 中创建不同的多智能体网络架构(例如,使用参数共享、集中式评论家);
如何使用
tensordict.TensorDict
来传递多智能体数据;如何在多智能体 MAPPO/IPPO 训练循环中串联所有库组件(收集器、模块、回放缓冲区和损失函数)。
如果您在 Google Colab 中运行此教程,请确保安装以下依赖项
!pip3 install torchrl
!pip3 install vmas
!pip3 install tqdm
近端策略优化 (PPO) 是一种策略梯度算法,它收集一批数据并直接用于训练策略,以在给定某些邻近性约束下最大化预期回报。您可以将其视为基础策略优化算法 REINFORCE 的高级版本。更多信息,请参阅 近端策略优化算法 (Proximal Policy Optimization Algorithms) 论文。
这类算法通常采用 on-policy(在线策略)方式训练。这意味着,在每个学习迭代中,我们都有一个 采样 阶段和一个 训练 阶段。在迭代 \(t\) 的 采样 阶段,使用当前策略 \(\mathbf{\pi}_t\) 收集智能体在环境中交互的 rollouts。在 训练 阶段,所有收集到的 rollouts 立即馈送到训练过程以执行反向传播。这会产生更新后的策略,然后再次用于采样。这个过程的循环执行构成了 on-policy learning(在线策略学习)。

在线策略学习¶
在 PPO 算法的训练阶段,使用一个 评论家 (critic) 来评估策略采取的行动的优劣。评论家学习估计特定状态的价值(平均折扣回报)。然后 PPO 损失函数会将策略获得的实际回报与评论家估计的回报进行比较,以确定所采取行动的优势并指导策略优化。
在多智能体设置中,情况有所不同。我们现在有多个策略 \(\mathbf{\pi}\),每个智能体一个。策略通常是局部的和去中心化的。这意味着单个智能体的策略仅根据其观测输出该智能体的行动。在 MARL 文献中,这被称为 去中心化执行 (decentralised execution)。另一方面,评论家存在不同的形式,主要包括
在 MAPPO 中,评论家是集中式的,并以系统的全局状态作为输入。这可以是全局观测,或者仅仅是智能体观测的串联。MAPPO 可用于执行 集中式训练 (centralised training) 的场景,因为它需要访问全局信息。
在 IPPO 中,评论家像策略一样,只将各自智能体的观测作为输入。这使得 去中心化训练 (decentralised training) 成为可能,因为评论家和策略都只需要局部信息来计算其输出。
集中式评论家有助于克服多个智能体同时学习时的非平稳性,但另一方面,它们可能会受到其庞大输入空间的影响。在本教程中,我们将能够训练这两种形式,并将讨论参数共享(在智能体之间共享网络参数的做法)如何影响每种形式。
本教程结构如下
首先,我们将定义一组要使用的超参数。
接下来,我们将使用 TorchRL 对 VMAS 模拟器的包装器创建一个向量化多智能体环境。
接下来,我们将设计策略网络和评论家网络,讨论各种选择对参数共享和评论家中心化的影响。
接下来,我们将创建采样收集器和回放缓冲区。
最后,我们将运行训练循环并分析结果。
如果您在 Colab 或带有 GUI 的机器中运行此教程,您还可以选择在训练前后渲染并可视化您自己训练的策略。
让我们导入依赖项
# Torch
import torch
# Tensordict modules
from tensordict.nn import set_composite_lp_aggregate, TensorDictModule
from tensordict.nn.distributions import NormalParamExtractor
from torch import multiprocessing
# Data collection
from torchrl.collectors import SyncDataCollector
from torchrl.data.replay_buffers import ReplayBuffer
from torchrl.data.replay_buffers.samplers import SamplerWithoutReplacement
from torchrl.data.replay_buffers.storages import LazyTensorStorage
# Env
from torchrl.envs import RewardSum, TransformedEnv
from torchrl.envs.libs.vmas import VmasEnv
from torchrl.envs.utils import check_env_specs
# Multi-agent network
from torchrl.modules import MultiAgentMLP, ProbabilisticActor, TanhNormal
# Loss
from torchrl.objectives import ClipPPOLoss, ValueEstimators
# Utils
torch.manual_seed(0)
from matplotlib import pyplot as plt
from tqdm import tqdm
定义超参数¶
我们为本教程设置超参数。根据可用资源,可以选择在 GPU 或其他设备上执行策略和模拟器。您可以调整其中一些值以适应计算需求。
# Devices
is_fork = multiprocessing.get_start_method() == "fork"
device = (
torch.device(0)
if torch.cuda.is_available() and not is_fork
else torch.device("cpu")
)
vmas_device = device # The device where the simulator is run (VMAS can run on GPU)
# Sampling
frames_per_batch = 6_000 # Number of team frames collected per training iteration
n_iters = 5 # Number of sampling and training iterations
total_frames = frames_per_batch * n_iters
# Training
num_epochs = 30 # Number of optimization steps per training iteration
minibatch_size = 400 # Size of the mini-batches in each optimization step
lr = 3e-4 # Learning rate
max_grad_norm = 1.0 # Maximum norm for the gradients
# PPO
clip_epsilon = 0.2 # clip value for PPO loss
gamma = 0.99 # discount factor
lmbda = 0.9 # lambda for generalised advantage estimation
entropy_eps = 1e-4 # coefficient of the entropy term in the PPO loss
# disable log-prob aggregation
set_composite_lp_aggregate(False).set()
环境¶
多智能体环境模拟多个智能体与世界互动。TorchRL API 允许集成各种类型的多智能体环境。一些示例包括具有共享或单独智能体奖励、完成标志和观测的环境。有关 TorchRL 中多智能体环境 API 工作原理的更多信息,您可以查阅专门的 文档章节。
特别是 VMAS 模拟器,它对具有独立奖励、信息、观测和行动的智能体进行建模,但共享一个集体完成标志。此外,它使用 vectorization(向量化)来批量执行模拟。这意味着其所有状态和物理量都是 PyTorch 张量,其第一个维度代表批次中并行环境的数量。这使得能够利用 GPU 的单指令多数据 (SIMD) 范例,并通过利用 GPU warps 中的并行化显著加速并行计算。这也意味着,在 TorchRL 中使用它时,模拟和训练都可以在设备上运行,而无需将数据传递给 CPU。
我们今天将解决的多智能体任务是 Navigation(参见上面的动画图)。在 Navigation 中,随机生成的智能体(带周围点的圆圈)需要导航到它们的目标(较小的圆圈)。智能体需要使用 LIDARs(它们周围的点)来避免彼此碰撞。智能体在具有阻力和弹性碰撞的 2D 连续世界中行动。它们的行动是决定其加速度的 2D 连续力。奖励由三部分组成:碰撞惩罚、基于到目标的距离的奖励,以及所有智能体到达目标时给予的最终共享奖励。基于距离的项计算为智能体与其目标之间在连续两个时间步内的相对距离的差。每个智能体观测其位置、速度、lidar 读数以及到其目标的相对位置。
现在我们将实例化环境。对于本教程,我们将把回合限制在 max_steps
内,之后会设置 done 标志。此功能已在 VMAS 模拟器中提供,但也可以替代使用 TorchRL 的 StepCount
transform。我们还将使用 num_vmas_envs
个向量化环境,以利用批量模拟。
max_steps = 100 # Episode steps before done
num_vmas_envs = (
frames_per_batch // max_steps
) # Number of vectorized envs. frames_per_batch should be divisible by this number
scenario_name = "navigation"
n_agents = 3
env = VmasEnv(
scenario=scenario_name,
num_envs=num_vmas_envs,
continuous_actions=True, # VMAS supports both continuous and discrete actions
max_steps=max_steps,
device=vmas_device,
# Scenario kwargs
n_agents=n_agents, # These are custom kwargs that change for each VMAS scenario, see the VMAS repo to know more.
)
环境不仅由其模拟器和 transforms 定义,还由一系列元数据定义,这些元数据描述了其执行过程中可能出现的情况。出于效率考虑,TorchRL 对环境 specs 要求相当严格,但您可以轻松检查您的环境 specs 是否足够。在我们的示例中,VmasEnv
负责为您的环境设置适当的 specs,因此您不必为此操心。
有四个需要关注的 specs
action_spec
定义了行动空间;reward_spec
定义了奖励域;done_spec
定义了 done 域;observation_spec
定义了环境步骤所有其他输出的域;
print("action_spec:", env.full_action_spec)
print("reward_spec:", env.full_reward_spec)
print("done_spec:", env.full_done_spec)
print("observation_spec:", env.observation_spec)
使用刚刚显示的命令,我们可以访问每个值的域。这样做我们可以看到,除了 done 之外,所有 specs 都具有前导形状 (num_vmas_envs, n_agents)
。这表示这些值将存在于每个独立环境的每个智能体中。另一方面,done spec 具有前导形状 num_vmas_envs
,表示 done 在智能体之间共享。
TorchRL 有一种方式来跟踪哪些 MARL specs 是共享的,哪些不是。实际上,具有额外智能体维度(即每个智能体都不同)的 specs 将包含在一个内部的“agents”键中。
正如您所见,奖励和行动 spec 都包含“agent”键,这意味着属于这些 specs 的 tensordicts 中的条目将嵌套在一个“agents”tensordict 中,将所有每个智能体的值分组在一起。
为了快速访问 tensordicts 中每个这些值的键,我们可以简单地向环境询问相应的键,我们将立即了解哪些是每个智能体的,哪些是共享的。此信息对于告知所有其他 TorchRL 组件在哪里找到每个值非常有用。
print("action_keys:", env.action_keys)
print("reward_keys:", env.reward_keys)
print("done_keys:", env.done_keys)
Transforms¶
我们可以将所需的任何 TorchRL transform 添加到我们的环境中。这些将以某种期望的方式修改其输入/输出。我们强调,在多智能体环境中,显式提供要修改的键至关重要。
例如,在这种情况下,我们将实例化一个 RewardSum
transform,它将回合内的奖励求和。我们将告诉此 transform 奖励键在哪里以及将求和的回合奖励写到哪里。转换后的环境将继承包装环境的设备和元数据,并根据其包含的 transforms 序列进行转换。
env = TransformedEnv(
env,
RewardSum(in_keys=[env.reward_key], out_keys=[("agents", "episode_reward")]),
)
check_env_specs()
函数运行一个小的 rollout 并将其输出与环境 specs 进行比较。如果没有引发错误,我们可以确信 specs 被正确定义。
check_env_specs(env)
Rollout¶
为了好玩,让我们看看一个简单的随机 rollout 是什么样子。您可以调用 env.rollout(n_steps) 并获取环境输入和输出的概述。行动将自动从 action spec 域中随机抽取。
n_rollout_steps = 5
rollout = env.rollout(n_rollout_steps)
print("rollout of three steps:", rollout)
print("Shape of the rollout TensorDict:", rollout.batch_size)
我们可以看到我们的 rollout 具有 batch_size
为 (num_vmas_envs, n_rollout_steps)
。这意味着其中的所有张量都将具有这些前导维度。
更深入地看,我们可以看到输出的 tensordict 可以按以下方式划分
在 root 中(通过运行
rollout.exclude("next")
访问),我们将找到在第一个时间步调用 reset 后可用的所有键。我们可以通过索引n_rollout_steps
维度查看它们在 rollout 步骤中的演变。在这些键中,我们将找到rollout["agents"]
tensordict 中每个智能体不同的键,它将具有批次大小(num_vmas_envs, n_rollout_steps, n_agents)
,表明它存储了额外的智能体维度。在此智能体 tensordict 之外的键将是共享的键(在本例中只有 done)。在 next 中(通过运行
rollout.get("next")
访问)。我们将找到与 root 相同的结构,但针对仅在 step 后可用的键。
在 TorchRL 中,约定是 done 和 observations 将同时存在于 root 和 next 中(因为它们在 reset 时和 step 后都可用)。Action 将仅存在于 root 中(因为 step 不会产生 action),而 reward 将仅存在于 next 中(因为 reset 时没有 reward)。此结构遵循 Reinforcement Learning: An Introduction (Sutton and Barto) 中的结构,其中 root 表示世界 step 的时间 \(t\) 的数据,next 表示时间 \(t+1\) 的数据。
渲染一个随机 rollout¶
如果您在 Google Colab 上,或者在装有 OpenGL 和 GUI 的机器上,您实际上可以渲染一个随机 rollout。这将让您了解随机策略在此任务中能 achieve 什么,以便与您自己训练的策略进行比较!
要渲染一个 rollout,请遵循本教程末尾 Render 部分的说明,并只需从 env.rollout()
中移除 policy=policy
这一行。
策略¶
PPO 利用随机策略来处理探索。这意味着我们的神经网络必须输出一个分布的参数,而不是对应于所采取行动的单个值。
由于数据是连续的,我们使用 Tanh-Normal 分布来遵守行动空间的边界。TorchRL 提供了这样的分布,我们唯一需要关注的是构建一个输出正确数量参数的神经网络。
在这种情况下,每个智能体的行动将由一个二维独立正态分布表示。为此,我们的神经网络必须为每个行动输出一个均值和一个标准差。因此,每个智能体将有 2 * n_actions_per_agents
个输出。
我们需要做出的另一个重要决定是是否让我们的智能体 共享策略参数 (share the policy parameters)。一方面,共享参数意味着它们将都共享相同的策略,这将使它们能够从彼此的经验中受益。这也会加快训练速度。另一方面,它会使它们的行为 homogenous(同质化),因为它们实际上共享相同的模型。对于本示例,我们将启用共享,因为我们不介意同质性并且可以从计算速度中受益,但在您自己的问题中始终考虑这个决定很重要!
我们分三步设计策略。
第一步:定义一个神经网络 n_obs_per_agent
-> 2 * n_actions_per_agents
为此,我们使用 MultiAgentMLP
,这是一个专门为多智能体设计的 TorchRL 模块,提供了丰富的定制选项。
share_parameters_policy = True
policy_net = torch.nn.Sequential(
MultiAgentMLP(
n_agent_inputs=env.observation_spec["agents", "observation"].shape[
-1
], # n_obs_per_agent
n_agent_outputs=2 * env.action_spec.shape[-1], # 2 * n_actions_per_agents
n_agents=env.n_agents,
centralised=False, # the policies are decentralised (ie each agent will act from its observation)
share_params=share_parameters_policy,
device=device,
depth=2,
num_cells=256,
activation_class=torch.nn.Tanh,
),
NormalParamExtractor(), # this will just separate the last dimension into two outputs: a loc and a non-negative scale
)
第二步:将神经网络包装在 TensorDictModule
中
这只是一个模块,它将从 tensordict 读取 in_keys
,将它们馈送到神经网络,并在 out_keys
位置原地写入输出。
请注意,我们使用 ("agents", ...)
键,因为这些键表示具有额外 n_agents
维度的数据。
policy_module = TensorDictModule(
policy_net,
in_keys=[("agents", "observation")],
out_keys=[("agents", "loc"), ("agents", "scale")],
)
第三步:将 TensorDictModule
包装在 ProbabilisticActor
中
现在我们需要根据正态分布的位置和尺度构建一个分布。为此,我们指示 ProbabilisticActor
类根据位置和尺度参数构建一个 TanhNormal
。我们还提供了此分布的最小值和最大值,这些值我们从环境 specs 中获取。
in_keys
的名称(以及因此上面 TensorDictModule
的 out_keys
的名称)必须以 TanhNormal
分布构造函数的关键字参数(loc 和 scale)结尾。
policy = ProbabilisticActor(
module=policy_module,
spec=env.action_spec_unbatched,
in_keys=[("agents", "loc"), ("agents", "scale")],
out_keys=[env.action_key],
distribution_class=TanhNormal,
distribution_kwargs={
"low": env.full_action_spec_unbatched[env.action_key].space.low,
"high": env.full_action_spec_unbatched[env.action_key].space.high,
},
return_log_prob=True,
) # we'll need the log-prob for the PPO loss
评论家网络¶
评论家网络是 PPO 算法的关键组成部分,尽管在采样时未使用它。此模块将读取观测并返回相应的价值估计。
如前所述,应该仔细考虑 共享评论家参数 (sharing the critic parameters) 的决定。通常,参数共享会加快训练收敛速度,但需要考虑一些重要的因素
当智能体具有不同的奖励函数时,不建议共享,因为评论家需要学习为同一状态分配不同的值(例如,在混合合作竞争环境中)。
在去中心化训练设置中,如果没有额外的基础设施来同步参数,则无法执行共享。
在所有其他情况下,如果奖励函数(与奖励区分开来)对所有智能体都是相同的(如当前场景),共享可以提供改进的性能。这可能会以智能体策略的同质性为代价。总的来说,了解哪种选择更可取的方法是快速实验这两种选项。
在这里,我们还需要在 MAPPO 和 IPPO 之间做出选择
使用 MAPPO,我们将获得一个具有完全可观测性的中心评论家(即,它将把所有串联的智能体观测作为输入)。我们之所以能做到这一点,是因为我们在模拟器中,且训练是集中式的。
使用 IPPO,我们将拥有一个局部的去中心化评论家,就像策略一样。
无论如何,评论家输出的形状将是 (..., n_agents, 1)
。如果评论家是集中式且共享的,则沿 n_agents
维度的所有值都将相同。
share_parameters_critic = True
mappo = True # IPPO if False
critic_net = MultiAgentMLP(
n_agent_inputs=env.observation_spec["agents", "observation"].shape[-1],
n_agent_outputs=1, # 1 value per agent
n_agents=env.n_agents,
centralised=mappo,
share_params=share_parameters_critic,
device=device,
depth=2,
num_cells=256,
activation_class=torch.nn.Tanh,
)
critic = TensorDictModule(
module=critic_net,
in_keys=[("agents", "observation")],
out_keys=[("agents", "state_value")],
)
让我们试试我们的策略模块和评论家模块。如前所述,使用 TensorDictModule
可以直接读取环境的输出以运行这些模块,因为它们知道要读取什么信息以及写到哪里。
从这一点开始,多智能体特定的组件已经实例化,我们将只需使用与单智能体学习相同的组件。这不是很棒吗?
print("Running policy:", policy(env.reset()))
print("Running value:", critic(env.reset()))
数据收集器¶
TorchRL 提供了一组数据收集器类。简单来说,这些类执行三个操作:重置环境、使用策略和最新观测计算行动、在环境中执行一个 step,并重复最后两个步骤,直到环境发出停止信号(或达到 done 状态)。
我们将使用最简单的数据收集器,其输出与环境 rollout 相同,唯一的区别是它会自动重置 done 状态,直到收集到所需的帧。
collector = SyncDataCollector(
env,
policy,
device=vmas_device,
storing_device=device,
frames_per_batch=frames_per_batch,
total_frames=total_frames,
)
回放缓冲区¶
回放缓冲区是 off-policy RL 算法的常见组成部分。在 on-policy 场景中,每次收集一批数据时都会重新填充回放缓冲区,并且其数据会重复消耗一定的 epoch 次数。
为 PPO 使用回放缓冲区并非强制,我们可以直接在线使用收集的数据,但使用这些类使得我们能够以可复现的方式轻松构建内部训练循环。
replay_buffer = ReplayBuffer(
storage=LazyTensorStorage(
frames_per_batch, device=device
), # We store the frames_per_batch collected at each iteration
sampler=SamplerWithoutReplacement(),
batch_size=minibatch_size, # We will sample minibatches of this size
)
损失函数¶
为了方便起见,可以直接从 TorchRL 导入 PPO 损失函数,使用 ClipPPOLoss
类。这是利用 PPO 最简单的方法:它隐藏了 PPO 的数学运算及其相关的控制流程。
PPO 需要计算一些“优势估计”。简而言之,优势是一个值,它反映了在处理偏差/方差权衡时对回报值的期望。要计算优势,只需 (1) 构建优势模块,该模块使用我们的价值算子,以及 (2) 在每个 epoch 之前将每批数据通过它。GAE 模块将使用新的 "advantage"
和 "value_target"
条目更新输入的 TensorDict
。"value_target"
是一个无梯度的张量,表示价值网络应通过输入观测表示的经验价值。这两者都将由 ClipPPOLoss
用于返回策略和价值损失。
loss_module = ClipPPOLoss(
actor_network=policy,
critic_network=critic,
clip_epsilon=clip_epsilon,
entropy_coef=entropy_eps,
normalize_advantage=False, # Important to avoid normalizing across the agent dimension
)
loss_module.set_keys( # We have to tell the loss where to find the keys
reward=env.reward_key,
action=env.action_key,
value=("agents", "state_value"),
# These last 2 keys will be expanded to match the reward shape
done=("agents", "done"),
terminated=("agents", "terminated"),
)
loss_module.make_value_estimator(
ValueEstimators.GAE, gamma=gamma, lmbda=lmbda
) # We build GAE
GAE = loss_module.value_estimator
optim = torch.optim.Adam(loss_module.parameters(), lr)
训练循环¶
现在我们拥有编写训练循环所需的所有部分。步骤包括
- 收集数据
- 计算优势
- 循环遍历 epoch
- 循环遍历 minibatches 计算损失值
反向传播
优化
重复
重复
重复
重复
pbar = tqdm(total=n_iters, desc="episode_reward_mean = 0")
episode_reward_mean_list = []
for tensordict_data in collector:
tensordict_data.set(
("next", "agents", "done"),
tensordict_data.get(("next", "done"))
.unsqueeze(-1)
.expand(tensordict_data.get_item_shape(("next", env.reward_key))),
)
tensordict_data.set(
("next", "agents", "terminated"),
tensordict_data.get(("next", "terminated"))
.unsqueeze(-1)
.expand(tensordict_data.get_item_shape(("next", env.reward_key))),
)
# We need to expand the done and terminated to match the reward shape (this is expected by the value estimator)
with torch.no_grad():
GAE(
tensordict_data,
params=loss_module.critic_network_params,
target_params=loss_module.target_critic_network_params,
) # Compute GAE and add it to the data
data_view = tensordict_data.reshape(-1) # Flatten the batch size to shuffle data
replay_buffer.extend(data_view)
for _ in range(num_epochs):
for _ in range(frames_per_batch // minibatch_size):
subdata = replay_buffer.sample()
loss_vals = loss_module(subdata)
loss_value = (
loss_vals["loss_objective"]
+ loss_vals["loss_critic"]
+ loss_vals["loss_entropy"]
)
loss_value.backward()
torch.nn.utils.clip_grad_norm_(
loss_module.parameters(), max_grad_norm
) # Optional
optim.step()
optim.zero_grad()
collector.update_policy_weights_()
# Logging
done = tensordict_data.get(("next", "agents", "done"))
episode_reward_mean = (
tensordict_data.get(("next", "agents", "episode_reward"))[done].mean().item()
)
episode_reward_mean_list.append(episode_reward_mean)
pbar.set_description(f"episode_reward_mean = {episode_reward_mean}", refresh=False)
pbar.update()
结果¶
让我们绘制每个回合获得的平均奖励
为了让训练持续更长时间,请增加 n_iters
超参数。
plt.plot(episode_reward_mean_list)
plt.xlabel("Training iterations")
plt.ylabel("Reward")
plt.title("Episode reward mean")
plt.show()
渲染¶
如果您在带有 GUI 的机器中运行此教程,可以通过运行以下命令渲染训练好的策略
with torch.no_grad():
env.rollout(
max_steps=max_steps,
policy=policy,
callback=lambda env, _: env.render(),
auto_cast_to_device=True,
break_when_any_done=False,
)
如果您在 Google Colab 中运行此教程,可以通过运行以下命令渲染训练好的策略
!apt-get update
!apt-get install -y x11-utils
!apt-get install -y xvfb
!pip install pyvirtualdisplay
import pyvirtualdisplay
display = pyvirtualdisplay.Display(visible=False, size=(1400, 900))
display.start()
from PIL import Image
def rendering_callback(env, td):
env.frames.append(Image.fromarray(env.render(mode="rgb_array")))
env.frames = []
with torch.no_grad():
env.rollout(
max_steps=max_steps,
policy=policy,
callback=rendering_callback,
auto_cast_to_device=True,
break_when_any_done=False,
)
env.frames[0].save(
f"{scenario_name}.gif",
save_all=True,
append_images=env.frames[1:],
duration=3,
loop=0,
)
from IPython.display import Image
Image(open(f"{scenario_name}.gif", "rb").read())
结论和后续步骤¶
在本教程中,我们看到了
如何在 TorchRL 中创建多智能体环境,其 specs 的工作原理以及如何与库集成;
如何在 TorchRL 中使用 GPU 向量化环境;
如何在 TorchRL 中创建不同的多智能体网络架构(例如,使用参数共享、集中式评论家);
如何使用
tensordict.TensorDict
来传递多智能体数据;如何在多智能体 MAPPO/IPPO 训练循环中串联所有库组件(收集器、模块、回放缓冲区和损失函数)。
现在您已经熟练掌握了多智能体 DDPG,您可以查看 GitHub 仓库中所有 TorchRL 的多智能体实现。这些是许多流行 MARL 算法(如本教程中介绍的算法、QMIX、MADDPG、IQL 等等)的代码脚本!
您还可以查看我们的另一个多智能体教程,了解如何在 PettingZoo/VMAS 中训练具有多个智能体组的竞争性 MADDPG/IDDPG: 使用 TorchRL 的竞争性多智能体强化学习 (DDPG) 教程。
如果您有兴趣在 TorchRL 中创建或包装您自己的多智能体环境,可以查阅专门的 文档章节。
最后,您可以修改本教程的参数,尝试许多其他配置和场景,成为一名 MARL 大师。以下是一些您可以在 VMAS 中尝试的可能场景的视频。
