杂项包装器

常用包装器

class gymnasium.wrappers.TimeLimit(env: Env, max_episode_steps: int)[源代码]

通过在超过最大时间步数时截断环境,限制环境的步数。

如果在环境中未定义截断,则这是发出截断信号的唯一位置。关键的是,这与源自基础环境作为MDP一部分的终止信号不同。不存在向量包装器。

使用 TimeLimit 包装器的示例:
>>> from gymnasium.wrappers import TimeLimit
>>> from gymnasium.envs.classic_control import CartPoleEnv
>>> spec = gym.spec("CartPole-v1")
>>> spec.max_episode_steps
500
>>> env = gym.make("CartPole-v1")
>>> env  # TimeLimit is included within the environment stack
<TimeLimit<OrderEnforcing<PassiveEnvChecker<CartPoleEnv<CartPole-v1>>>>>
>>> env.spec  
EnvSpec(id='CartPole-v1', ..., max_episode_steps=500, ...)
>>> env = gym.make("CartPole-v1", max_episode_steps=3)
>>> env.spec  
EnvSpec(id='CartPole-v1', ..., max_episode_steps=3, ...)
>>> env = TimeLimit(CartPoleEnv(), max_episode_steps=10)
>>> env
<TimeLimit<CartPoleEnv instance>>
TimeLimit 决定剧集步骤的示例
>>> env = gym.make("CartPole-v1", max_episode_steps=3)
>>> _ = env.reset(seed=123)
>>> _ = env.action_space.seed(123)
>>> _, _, terminated, truncated, _ = env.step(env.action_space.sample())
>>> terminated, truncated
(False, False)
>>> _, _, terminated, truncated, _ = env.step(env.action_space.sample())
>>> terminated, truncated
(False, False)
>>> _, _, terminated, truncated, _ = env.step(env.action_space.sample())
>>> terminated, truncated
(False, True)
变更日志:
  • v0.10.6 - 最初添加

  • v0.25.0 - 随着步骤 API 的更新,终止和截断信号被分别返回。

参数:
  • env – 应用包装器的环境

  • max_episode_steps – 可选的最大情节步数(如果为 None,则使用 env.spec.max_episode_steps

class gymnasium.wrappers.RecordVideo(env: Env[ObsType, ActType], video_folder: str, episode_trigger: Callable[[int], bool] | None = None, step_trigger: Callable[[int], bool] | None = None, video_length: int = 0, name_prefix: str = 'rl-video', fps: int | None = None, disable_logger: bool = True)[源代码]

使用环境的渲染函数记录环境片段的视频。

通常,你只想间歇性地记录剧集,比如说每第一百个剧集或每一千个环境步骤。为此,你可以指定 episode_triggerstep_trigger。它们应该是返回布尔值的函数,分别指示是否应在当前剧集或步骤开始记录。

episode_trigger 应在录制开始的剧集中返回 Truestep_trigger 应在录制开始的第 n 个环境步中返回 True,其中 n 是所有先前剧集的总和。如果既没有传递 :attr:episode_trigger 也没有传递 step_trigger,将使用默认的 episode_trigger,即 :func:capped_cubic_video_schedule。此函数在每个是 3 的幂次的剧集中开始视频录制,直到 1000 集,然后每 1000 集录制一次。默认情况下,一旦调用 reset,录制将停止。但是,您也可以通过为 video_length 传递一个严格正值来创建固定长度的录制(可能跨越多个剧集)。

不存在包装器的矢量版本。

示例 - 运行环境50个回合,从第0个回合开始,每10个回合保存一次视频:
>>> import os
>>> import gymnasium as gym
>>> env = gym.make("LunarLander-v3", render_mode="rgb_array")
>>> trigger = lambda t: t % 10 == 0
>>> env = RecordVideo(env, video_folder="./save_videos1", episode_trigger=trigger, disable_logger=True)
>>> for i in range(50):
...     termination, truncation = False, False
...     _ = env.reset(seed=123)
...     while not (termination or truncation):
...         obs, rew, termination, truncation, info = env.step(env.action_space.sample())
...
>>> env.close()
>>> len(os.listdir("./save_videos1"))
5
示例 - 运行环境5个回合,每200步开始一次录制,确保每个视频长度为100帧:
>>> import os
>>> import gymnasium as gym
>>> env = gym.make("LunarLander-v3", render_mode="rgb_array")
>>> trigger = lambda t: t % 200 == 0
>>> env = RecordVideo(env, video_folder="./save_videos2", step_trigger=trigger, video_length=100, disable_logger=True)
>>> for i in range(5):
...     termination, truncation = False, False
...     _ = env.reset(seed=123)
...     _ = env.action_space.seed(123)
...     while not (termination or truncation):
...         obs, rew, termination, truncation, info = env.step(env.action_space.sample())
...
>>> env.close()
>>> len(os.listdir("./save_videos2"))
2
示例 - 运行3个回合,记录所有内容,但以1000帧为块:
>>> import os
>>> import gymnasium as gym
>>> env = gym.make("LunarLander-v3", render_mode="rgb_array")
>>> env = RecordVideo(env, video_folder="./save_videos3", video_length=1000, disable_logger=True)
>>> for i in range(3):
...     termination, truncation = False, False
...     _ = env.reset(seed=123)
...     while not (termination or truncation):
...         obs, rew, termination, truncation, info = env.step(env.action_space.sample())
...
>>> env.close()
>>> len(os.listdir("./save_videos3"))
2
变更日志:
  • v0.25.0 - 最初添加以替换 wrappers.monitoring.VideoRecorder

参数:
  • env – 将被包装的环境

  • video_folder (str) – 录音将存储的文件夹

  • episode_trigger – 接受一个整数并返回 True 的函数,当且仅当在此集数应开始录制时

  • step_trigger – 接受一个整数并返回 True 的函数,当且仅当在此步骤应开始录制时。

  • video_length (int) – 记录的片段长度。如果为0,则记录整个片段。否则,捕获指定长度的片段。

  • name_prefix (str) – 将被添加到录音文件名的开头

  • fps (int) – 视频中的每秒帧数。如果为 None ,则使用环境元数据中的 render_fps 键(如果存在),否则使用默认值 30。

  • disable_logger (bool) – 是否禁用 moviepy 日志记录器,默认情况下是禁用的

class gymnasium.wrappers.RecordEpisodeStatistics(env: Env[ObsType, ActType], buffer_length: int = 100, stats_key: str = 'episode')[源代码]

这个包装器将跟踪累积奖励和情节长度。

在剧集结束时,剧集的统计数据将使用键 episode 添加到 info 中。如果使用矢量化环境,还会使用键 _episode,它指示相应索引处的环境是否具有剧集统计数据。包装器的矢量化版本存在,即 :class:gymnasium.wrappers.vector.RecordEpisodeStatistics

在完成一个片段后,info 将会看起来像这样::

>>> info = {
...     "episode": {
...         "r": "<cumulative reward>",
...         "l": "<episode length>",
...         "t": "<elapsed time since beginning of episode>"
...     },
... }

对于矢量化环境,输出将以以下形式呈现::

>>> infos = {
...     "final_observation": "<array of length num-envs>",
...     "_final_observation": "<boolean array of length num-envs>",
...     "final_info": "<array of length num-envs>",
...     "_final_info": "<boolean array of length num-envs>",
...     "episode": {
...         "r": "<array of cumulative reward>",
...         "l": "<array of episode length>",
...         "t": "<array of elapsed time since beginning of episode>"
...     },
...     "_episode": "<boolean array of length num-envs>"
... }

此外,最近的奖励和情节长度存储在可以通过 :attr:wrapped_env.return_queue 和 :attr:wrapped_env.length_queue 分别访问的缓冲区中。

变量:
  • time_queue (*) – 最后 deque_size 个回合的时间长度

  • return_queue (*) – 过去 deque_size 个回合的累积奖励

  • length_queue (*) – 最后 deque_size 个回合的长度

变更日志:
  • v0.15.4 - 最初添加

  • v1.0.0 - 移除了向量环境支持(参见 :class:gymnasium.wrappers.vector.RecordEpisodeStatistics)并添加了属性 time_queue

参数:
  • env (Env) – 应用包装器的环境

  • buffer_length – 缓冲区的大小 :attr:return_queue, :attr:length_queue 和 :attr:time_queue

  • stats_key – 剧集统计的信息键

class gymnasium.wrappers.AtariPreprocessing(env: Env, noop_max: int = 30, frame_skip: int = 4, screen_size: int = 84, terminal_on_life_loss: bool = False, grayscale_obs: bool = True, grayscale_newaxis: bool = False, scale_obs: bool = False)[源代码]

实现了Atari环境常用的预处理技术(不包括帧堆叠)。

对于帧堆叠,使用 :class:gymnasium.wrappers.FrameStackObservation。该包装器没有向量版本。

本类遵循 Machado 等人(2018 年)的指南,《重访街机学习环境:通用代理的评估协议和开放问题》。

具体来说,以下预处理阶段适用于atari环境:

  • 无操作重置:通过在重置时执行随机数量的无操作来获取初始状态,默认最大无操作数为30。

  • 跳帧数:每步之间跳过的帧数,默认为4。

  • 最大池化:从帧跳过的最近两次观察中进行池化。

  • 生命丢失时的终止信号:当代理在环境中失去生命时,环境将被终止。

    默认关闭。Machado 等人(2018)不推荐。

  • 调整到方形图像:默认将atari环境原始观察形状从210x180调整为84x84。

  • 灰度观察:使观察结果变为灰度,默认启用。

  • 灰度新轴:扩展观察的最后一个通道,使得图像变为三维,默认不启用。

  • 缩放观察:是否将观察值缩放在 [0, 1) 或 [0, 255) 之间,默认不进行缩放。

示例

>>> import gymnasium as gym 
>>> env = gym.make("ALE/Adventure-v5") 
>>> env = AtariPreprocessing(env, noop_max=10, frame_skip=0, screen_size=84, terminal_on_life_loss=True, grayscale_obs=False, grayscale_newaxis=False) 
变更日志:
  • 在 gym v0.12.2 中添加(gym #1455)

参数:
  • env (Env) – 应用预处理的环境

  • noop_max (int) – 对于无操作重置,重置时执行的最大无操作次数,要关闭,请设置为0。

  • frame_skip (int) – 新观察之间的帧数会影响代理体验游戏的频率。

  • screen_size (int) – 调整Atari帧的大小。

  • terminal_on_life_loss (bool) – 如果为真,那么 :meth:步骤() 在每次失去生命时返回 终止=真

  • grayscale_obs (bool) – 如果为真,则返回灰度观察结果,否则返回RGB观察结果。

  • grayscale_newaxis (bool) – if True and grayscale_obs=True, 那么灰度观测值会添加一个通道轴,使其变为三维。

  • scale_obs (bool) – 如果为真,则返回范围为 [0,1) 的归一化观测值。同时,这也会限制 FrameStack 包装器的内存优化效果。

抛出:
  • DependencyNotInstalled – opencv-python 包未安装

  • ValueError – 在原始环境中禁用帧跳过

不常见的包装器

class gymnasium.wrappers.Autoreset(env: Env)[源代码]

当达到终止或截断状态时,包装环境会自动重置。

当调用步骤导致 :meth:Env.step 返回 terminated=Truetruncated=True 时,调用 :meth:Env.reset,并且 :meth:self.step 的返回格式如下:(new_obs, final_reward, final_terminated, final_truncated, info) 使用新的步骤 API,(new_obs, final_reward, final_done, info) 使用旧的步骤 API。不存在包装器的向量版本。

  • obs 是在调用 :meth:self.env.reset 后的第一个观察结果

  • final_reward 是在调用 :meth:self.env.step 之后的奖励,在调用 :meth:self.env.reset 之前。

  • final_terminated 是在调用 :meth:self.env.reset 之前的终止值。

  • final_truncated 是在调用 :meth:self.env.reset 之前的截断值。final_terminatedfinal_truncated 不能同时为 False。

  • info 是一个字典,包含从对 :meth:self.env.reset 的调用返回的 info 字典中的所有键,并额外包含一个键 “final_observation”,该键包含最后一次调用 :meth:self.env.step 返回的观察结果,以及一个键 “final_info”,该键包含最后一次调用 :meth:self.env.step 返回的 info 字典。

警告

在使用此包装器收集回放时,请注意当 :meth:Env.step 返回 terminatedtruncated 时,:meth:Env.step 会返回调用 :meth:Env.reset 后的新观测值,以及前一回合的最终奖励、终止和截断状态。如果你需要前一回合的最终状态,你需要通过 info 字典中的 “final_observation” 键来获取。如果你使用此包装器,请确保你知道自己在做什么!

变更日志:
  • v0.24.0 - 最初作为 AutoResetWrapper 添加

  • v1.0.0 - 重命名为 Autoreset 并且自动重置顺序改为在环境终止或截断后的步骤重置。因此,"final_observation""final_info" 被移除。

参数:

env (gym.Env) – 应用包装器的环境

class gymnasium.wrappers.PassiveEnvChecker(env: Env[ObsType, ActType])[源代码]

一个被动包装器,围绕 stepresetrender 函数,检查它们是否遵循 Gymnasium 的 API。

此包装器在执行 make 时自动应用,可以通过 disable_env_checker 禁用。没有此包装器的向量版本。

示例

>>> import gymnasium as gym
>>> env = gym.make("CartPole-v1")
>>> env
<TimeLimit<OrderEnforcing<PassiveEnvChecker<CartPoleEnv<CartPole-v1>>>>>
>>> env = gym.make("CartPole-v1", disable_env_checker=True)
>>> env
<TimeLimit<OrderEnforcing<CartPoleEnv<CartPole-v1>>>>
变更日志:
  • v0.24.1 - 最初添加但存在多种问题

  • v0.25.0 - 所有Bug已修复

  • v0.29.0 - 移除了对Box观测和动作空间的无界警告以及不规则边界形状的警告

使用环境初始化包装器,运行观察和动作空间测试。

class gymnasium.wrappers.HumanRendering(env: Env[ObsType, ActType])[源代码]

允许在支持“rgb_array”渲染的环境中进行类似人类的渲染。

当你实现了一个可以生成RGB图像的环境,但还没有实现任何将图像渲染到屏幕的代码时,这个包装器特别有用。如果你想在环境中使用这个包装器,记得在你的环境元数据中指定 "render_fps"

被包装环境的 render_mode 必须是 'rgb_array''rgb_array_list'

不存在包装器的矢量版本。

示例

>>> import gymnasium as gym
>>> from gymnasium.wrappers import HumanRendering
>>> env = gym.make("LunarLander-v3", render_mode="rgb_array")
>>> wrapped = HumanRendering(env)
>>> obs, _ = wrapped.reset()     # This will start rendering to the screen

包装器也可以在环境实例化时直接应用,只需向 make 传递 render_mode="human" 即可。只有当环境本身不支持原生人类渲染时(即 render_mode 不包含 "human"),才会应用包装器。

>>> env = gym.make("phys2d/CartPole-v1", render_mode="human")      # CartPoleJax-v1 doesn't implement human-rendering natively
>>> obs, _ = env.reset()     # This will start rendering to the screen

警告:如果基础环境使用 render_mode="rgb_array_list" ,其(即 基础环境的 )渲染方法将始终返回一个空列表:

>>> env = gym.make("LunarLander-v3", render_mode="rgb_array_list")
>>> wrapped = HumanRendering(env)
>>> obs, _ = wrapped.reset()
>>> env.render() # env.render() will always return an empty list!
[]
变更日志:
  • v0.25.0 - 最初添加

参数:

env – 正在被包装的环境

class gymnasium.wrappers.OrderEnforcing(env: Env[ObsType, ActType], disable_render_order_enforcing: bool = False)[源代码]

如果在调用 reset 之前调用了 steprender,将会产生错误。

不存在包装器的矢量版本。

示例

>>> import gymnasium as gym
>>> from gymnasium.wrappers import OrderEnforcing
>>> env = gym.make("CartPole-v1", render_mode="human")
>>> env = OrderEnforcing(env)
>>> env.step(0)
Traceback (most recent call last):
    ...
gymnasium.error.ResetNeeded: Cannot call env.step() before calling env.reset()
>>> env.render()
Traceback (most recent call last):
    ...
gymnasium.error.ResetNeeded: Cannot call `env.render()` before calling `env.reset()`, if this is an intended action, set `disable_render_order_enforcing=True` on the OrderEnforcer wrapper.
>>> _ = env.reset()
>>> env.render()
>>> _ = env.step(0)
>>> env.close()
变更日志:
  • v0.22.0 - 最初添加

  • v0.24.0 - 为渲染函数添加了顺序强制功能

参数:
  • env – 要包装的环境

  • disable_render_order_enforcing – 如果要禁用渲染顺序强制执行

class gymnasium.wrappers.RenderCollection(env: Env[ObsType, ActType], pop_frames: bool = True, reset_clean: bool = True)[源代码]

收集环境的渲染帧,例如 render 返回一个 list[RenderedFrame]

不存在包装器的矢量版本。

示例

返回 render 未被调用的步数对应的帧列表。 >>> import gymnasium as gym >>> env = gym.make(“LunarLander-v3”, render_mode=”rgb_array”) >>> env = RenderCollection(env) >>> _ = env.reset(seed=123) >>> for _ in range(5): … _ = env.step(env.action_space.sample()) … >>> frames = env.render() >>> len(frames) 6

>>> frames = env.render()
>>> len(frames)
0

返回该集运行步数对应的帧列表。 >>> import gymnasium as gym >>> env = gym.make(“LunarLander-v3”, render_mode=”rgb_array”) >>> env = RenderCollection(env, pop_frames=False) >>> _ = env.reset(seed=123) >>> for _ in range(5): … _ = env.step(env.action_space.sample()) … >>> frames = env.render() >>> len(frames) 6

>>> frames = env.render()
>>> len(frames)
6

收集所有剧集的所有帧,在调用渲染时不清除它们 >>> import gymnasium as gym >>> env = gym.make(“LunarLander-v3”, render_mode=”rgb_array”) >>> env = RenderCollection(env, pop_frames=False, reset_clean=False) >>> _ = env.reset(seed=123) >>> for _ in range(5): … _ = env.step(env.action_space.sample()) … >>> _ = env.reset(seed=123) >>> for _ in range(5): … _ = env.step(env.action_space.sample()) … >>> frames = env.render() >>> len(frames) 12

>>> frames = env.render()
>>> len(frames)
12
变更日志:
  • v0.26.2 - 最初添加

参数:
  • env – 正在被包装的环境

  • pop_frames (bool) – 如果为真,在调用 meth:render 后清除集合帧。默认值是 True

  • reset_clean (bool) – 如果为真,当调用 meth:reset 时清除集合帧。默认值为 True

数据转换包装器