快捷方式

CatFrames

class torchrl.envs.transforms.CatFrames(N: int, dim: int, in_keys: Sequence[NestedKey] | None = None, out_keys: Sequence[NestedKey] | None = None, padding='same', padding_value=0, as_inverse=False, reset_key: NestedKey | None = None, done_key: NestedKey | None = None)[源代码]

将连续的观察帧串联成单个张量。

此 transform 对于在观察到的特征中创建运动感或速度感很有用。它也可以与需要访问过去观察的模型(如 transformers 等)一起使用。它最初在 “Playing Atari with Deep Reinforcement Learning” (https://arxiv.org/pdf/1312.5602.pdf) 中提出。

当在转换后的环境中使用时,CatFrames 是一个有状态的类,可以通过调用 reset() 方法将其重置为原生状态。此方法接受包含 "_reset" 条目的 tensordict,该条目指示要重置哪个缓冲区。

参数:
  • N (int) – 要串联的观察帧数。

  • dim (int) – 串联观察值的维度。应为负数,以确保其与不同 batch_size 的环境兼容。

  • in_keys (sequence of NestedKey, optional) – 指向需要串联的帧的键。默认为 [“pixels”]。

  • out_keys (sequence of NestedKey, optional) – 指向输出写入位置的键。默认为 in_keys 的值。

  • padding (str, optional) – 填充方法。可以是 "same""constant"。默认为 "same",即使用第一个值进行填充。

  • padding_value (float, optional) – 如果 padding="constant",用于填充的值。默认为 0。

  • as_inverse (bool, optional) – 如果为 True,则应用 inverse transform。默认为 False

  • reset_key (NestedKey, optional) – 用作部分重置指示符的 reset 键。必须是唯一的。如果未提供,则默认为父环境唯一的 reset 键(如果只有一个),否则会引发异常。

  • done_key (NestedKey, optional) – 用作部分 done 指示符的 done 键。必须是唯一的。如果未提供,则默认为 "done"

示例

>>> from torchrl.envs.libs.gym import GymEnv
>>> env = TransformedEnv(GymEnv('Pendulum-v1'),
...     Compose(
...         UnsqueezeTransform(-1, in_keys=["observation"]),
...         CatFrames(N=4, dim=-1, in_keys=["observation"]),
...     )
... )
>>> print(env.rollout(3))

CatFrames transform 也可以离线使用,以在不同规模下重现在线帧串联的效果(或为了限制内存消耗)。以下示例给出了完整的说明,以及 torchrl.data.ReplayBuffer 的用法

示例

>>> from torchrl.envs.utils import RandomPolicy        >>> from torchrl.envs import UnsqueezeTransform, CatFrames
>>> from torchrl.collectors import SyncDataCollector
>>> # Create a transformed environment with CatFrames: notice the usage of UnsqueezeTransform to create an extra dimension
>>> env = TransformedEnv(
...     GymEnv("CartPole-v1", from_pixels=True),
...     Compose(
...         ToTensorImage(in_keys=["pixels"], out_keys=["pixels_trsf"]),
...         Resize(in_keys=["pixels_trsf"], w=64, h=64),
...         GrayScale(in_keys=["pixels_trsf"]),
...         UnsqueezeTransform(-4, in_keys=["pixels_trsf"]),
...         CatFrames(dim=-4, N=4, in_keys=["pixels_trsf"]),
...     )
... )
>>> # we design a collector
>>> collector = SyncDataCollector(
...     env,
...     RandomPolicy(env.action_spec),
...     frames_per_batch=10,
...     total_frames=1000,
... )
>>> for data in collector:
...     print(data)
...     break
>>> # now let's create a transform for the replay buffer. We don't need to unsqueeze the data here.
>>> # however, we need to point to both the pixel entry at the root and at the next levels:
>>> t = Compose(
...         ToTensorImage(in_keys=["pixels", ("next", "pixels")], out_keys=["pixels_trsf", ("next", "pixels_trsf")]),
...         Resize(in_keys=["pixels_trsf", ("next", "pixels_trsf")], w=64, h=64),
...         GrayScale(in_keys=["pixels_trsf", ("next", "pixels_trsf")]),
...         CatFrames(dim=-4, N=4, in_keys=["pixels_trsf", ("next", "pixels_trsf")]),
... )
>>> from torchrl.data import TensorDictReplayBuffer, LazyMemmapStorage
>>> rb = TensorDictReplayBuffer(storage=LazyMemmapStorage(1000), transform=t, batch_size=16)
>>> data_exclude = data.exclude("pixels_trsf", ("next", "pixels_trsf"))
>>> rb.add(data_exclude)
>>> s = rb.sample(1) # the buffer has only one element
>>> # let's check that our sample is the same as the batch collected during inference
>>> assert (data.exclude("collector")==s.squeeze(0).exclude("index", "collector")).all()

注意

CatFrames 目前仅支持根级别的 "done" 信号。目前不支持嵌套的 done,例如在 MARL 设置中发现的那些。如果需要此功能,请在 TorchRL 仓库上提出一个 issue。

注意

在回放缓冲区中存储帧堆栈会显著增加内存消耗(增加 N 倍)。为了缓解这个问题,你可以直接在回放缓冲区中存储轨迹,并在采样时应用 CatFrames。此方法包括对存储的轨迹进行切片采样,然后应用帧堆叠 transform。为了方便起见,CatFrames 提供了一个 make_rb_transform_and_sampler() 方法,该方法会创建

  • 适合在回放缓冲区中使用的 transform 的修改版本

  • 一个用于缓冲区的相应 SliceSampler

forward(tensordict: TensorDictBase) TensorDictBase[源代码]

读取输入 tensordict,并对选定的键应用 transform。

make_rb_transform_and_sampler(batch_size: int, **sampler_kwargs) Tuple[Transform, 'torchrl.data.replay_buffers.SliceSampler'][源代码]

创建用于存储帧堆叠数据时与回放缓冲区一起使用的 transform 和 sampler。

此方法通过避免在缓冲区中存储整个帧堆栈来帮助减少存储数据中的冗余。它会创建一个在采样时即时堆叠帧的 transform,以及一个确保维护正确序列长度的 sampler。

参数:
  • batch_size (int) – 用于 sampler 的 batch size。

  • **sampler_kwargs – 传递给 SliceSampler 构造函数的附加关键字参数。

返回:

  • transform (Transform): 在采样时即时堆叠帧的 transform。

  • sampler (SliceSampler): 确保维护正确序列长度的 sampler。

返回类型:

一个包含以下内容的元组

示例

>>> env = TransformedEnv(...)
>>> catframes = CatFrames(N=4, ...)
>>> transform, sampler = catframes.make_rb_transform_and_sampler(batch_size=32)
>>> rb = ReplayBuffer(..., sampler=sampler, transform=transform)

注意

在使用图像时,建议在前面的 ToTensorImage transform 中使用不同的 in_keysout_keys。这确保存储在缓冲区中的张量与它们的处理后版本分开,我们不希望存储处理后版本。对于非图像数据,考虑在 CatFrames 之前插入一个 RenameTransform,以创建将在缓冲区中存储的数据副本。

注意

将 transform 添加到回放缓冲区时,应注意同时传递在 CatFrames 之前的 transform,例如 ToTensorImageUnsqueezeTransform,以便 CatFrames transform 看到的数据格式与数据收集时的格式相同。

注意

有关更完整的示例,请参阅 torchrl 的 github 仓库 examples 文件夹: https://github.com/pytorch/rl/tree/main/examples/replay-buffers/catframes-in-buffer.py

transform_observation_spec(observation_spec: TensorSpec) TensorSpec[源代码]

转换观察规范,使结果规范与 transform 映射匹配。

参数:

observation_spec (TensorSpec) – transform 之前的规范

返回:

transform 之后的预期规范

文档

查阅全面的 PyTorch 开发者文档

查看文档

教程

获取针对初学者和高级开发者的深度教程

查看教程

资源

查找开发资源并获得问题解答

查看资源