其他包裝函式

通用包裝函式

class gymnasium.wrappers.TimeLimit(env: Env, max_episode_steps: int)[原始碼]

透過在超過最大時間步數時截斷環境,來限制環境的步數。

如果截斷未在環境本身內部定義,這是發出截斷訊號的唯一位置。 關鍵的是,這與來自底層環境作為 MDP 一部分的 terminated 訊號不同。 不存在向量包裝函式。

使用 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 決定 episode 步數的範例
>>> 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 - 隨著 step API 更新,終止和截斷訊號會分開傳回。

參數:
  • env – 要套用包裝函式的環境

  • max_episode_steps – episode 在此環境步數之後被截斷 (elapsed >= max_episode_steps)

class gymnasium.wrappers.RecordVideo(env: gym.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)[原始碼]

使用環境的 render 函式錄製環境 episode 的影片。

通常,您只想間歇性地錄製 episode,例如每隔一百個 episode 或每隔一千個環境步數。 若要執行此操作,您可以指定 episode_triggerstep_trigger。 它們應該是傳回布林值的函式,指示是否應分別在目前的 episode 或步數開始錄製。

episode_trigger 應在應開始錄製的 episode 上傳回 Truestep_trigger 應在應開始錄製的第 n 個環境步數上傳回 True,其中 n 是所有先前 episode 的總和。 如果未傳遞 episode_triggerstep_trigger,則將採用預設的 episode_trigger,即 capped_cubic_video_schedule()。 此函式會在每個 3 的冪次的 episode 開始錄製影片,直到 1000,然後每 1000 個 episode 錄製一次。 依預設,一旦呼叫 reset,錄製就會停止。 但是,您也可以透過為 video_length 傳遞嚴格正值來建立固定長度的錄製 (可能會跨越多個 episode)。

不存在此包裝函式的向量版本。

範例 - 執行環境 50 個 episode,並從第 0 個 episode 開始每 10 個 episode 儲存影片
>>> 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 個 episode,每 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 個 episode,錄製所有內容,但以 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 的函式,表示是否應在此 episode 開始錄製

  • step_trigger – 接受整數並傳回 True 的函式,表示是否應在此步數開始錄製

  • video_length (int) – 錄製的 episode 長度。 如果為 0,則會錄製整個 episode。 否則,會擷取指定長度的片段

  • name_prefix (str) – 將前置於錄製內容的檔案名稱

  • fps (int) – 影片中的每秒幀數。 為環境提供自訂影片 fps,如果 None,則使用環境中繼資料 render_fps 鍵 (如果存在),否則使用預設值 30。

  • disable_logger (bool) – 是否停用 moviepy logger,預設為停用

class gymnasium.wrappers.RecordEpisodeStatistics(env: Env[ObsType, ActType], buffer_length: int = 100, stats_key: str = 'episode')[原始碼]

此包裝函式將追蹤累積獎勵和 episode 長度。

在 episode 結束時,episode 的統計資訊將使用索引鍵 episode 新增至 info。 如果使用向量化環境,也會使用索引鍵 _episode,這表示在個別索引處的 env 是否具有 episode 統計資訊。 存在此包裝函式的向量版本,gymnasium.wrappers.vector.RecordEpisodeStatistics

在 episode 完成後,info 看起來會像這樣

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

對於向量化環境,輸出將採用以下形式

>>> infos = {
...     "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>"
... }

此外,最新的獎勵和 episode 長度會儲存在緩衝區中,這些緩衝區可以透過 wrapped_env.return_queuewrapped_env.length_queue 分別存取。

變數:
  • time_queue (*) – 最後 deque_size 個 episode 的時間長度

  • return_queue (*) – 最後 deque_size 個 episode 的累積獎勵

  • length_queue (*) – 最後 deque_size 個 episode 的長度

變更日誌
參數:
  • env (Env) – 要套用包裝函式的環境

  • buffer_length – 緩衝區 return_queuelength_queuetime_queue 的大小

  • stats_key – episode 統計資訊的 info 索引鍵

class gymnasium.wrappers.AtariPreprocessing(env: gym.Env, noop_max: int = 30, frame_skip: int = 4, screen_size: int | tuple[int, int] = 84, terminal_on_life_loss: bool = False, grayscale_obs: bool = True, grayscale_newaxis: bool = False, scale_obs: bool = False)[原始碼]

實作 Atari 環境的通用預先處理技術 (不包括幀堆疊)。

如需幀堆疊,請使用 gymnasium.wrappers.FrameStackObservation。 不存在此包裝函式的向量版本

此類別遵循 Machado et al. (2018) 中的指南,「重新檢視 Arcade Learning Environment:通用智能體的評估協定和開放問題」。

具體來說,以下預先處理階段適用於 atari 環境

  • Noop Reset:透過在 reset 時執行隨機次數的 no-ops 來取得初始狀態,預設最大值為 30 個 no-ops。

  • 幀跳過:步驟之間跳過的幀數,預設為 4。

  • 最大池化:池化來自幀跳過的最新的兩個觀察結果。

  • 生命值損失時的終止訊號:當智能體在環境中損失生命值時,環境會終止。

    預設為關閉。 Machado et al. (2018) 不建議使用。

  • 調整大小為正方形影像:將 atari 環境的原始觀察形狀從 210x180 調整為 84x84 (預設)。

  • 灰階觀察:使觀察結果為灰階,預設為啟用。

  • 灰階新軸:擴展觀察結果的最後一個通道,使影像為 3 維,預設為不啟用。

  • 縮放觀察:是否將觀察結果縮放介於 [0, 1) 或 [0, 255) 之間,預設為不縮放。

範例

>>> import gymnasium as gym
>>> import ale_py
>>> gym.register_envs(ale_py)
>>> env = gym.make("ALE/Pong-v5", frameskip=1)
>>> env = AtariPreprocessing(
...     env,
...     noop_max=10, frame_skip=4, terminal_on_life_loss=True,
...     screen_size=84, grayscale_obs=False, grayscale_newaxis=False
... )
變更日誌
  • 在 gym v0.12.2 中新增 (gym #1455)

參數:
  • env (Env) – 要套用預先處理的環境

  • noop_max (int) – 對於 No-op reset,在 reset 時執行的最大 no-ops 動作次數,若要關閉,請設定為 0。

  • frame_skip (int) – 新觀察結果之間的幀數,智能體的觀察結果會影響智能體體驗遊戲的頻率。

  • screen_size (int | tuple[int, int]) – 調整 Atari 幀大小。

  • terminal_on_life_loss (bool) – 如果為 True,則每當損失生命值時,step() 就會傳回 terminated=True

  • grayscale_obs (bool) – 如果為 True,則傳回灰階觀察結果,否則傳回 RGB 觀察結果。

  • grayscale_newaxis (bool) – 如果為 True 且 grayscale_obs=True,則會將通道軸新增至灰階觀察結果,使其成為 3 維。

  • scale_obs (bool) – 如果為 True,則會傳回範圍 [0,1) 中正規化的觀察結果。 這也會限制 FrameStack 包裝函式的記憶體最佳化優勢。

引發:
  • DependencyNotInstalled – 未安裝 opencv-python 套件

  • ValueError – 在原始環境中停用幀跳過

非通用包裝函式

class gymnasium.wrappers.Autoreset(env: Env)[原始碼]

當達到終止或截斷狀態時,包裝的環境會自動重設。

這遵循向量自動重設 API,在 episode 終止或截斷後的步驟中,環境會重設。

變更日誌
  • 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。

此包裝函式會在建立期間自動套用,並且可以使用 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 - 錯誤已全部修正

  • v0.29.0 - 移除 Box 觀察和動作空間的無限邊界以及不規則邊界形狀的警告

使用環境初始化包裝函式,執行觀察和動作空間測試。

class gymnasium.wrappers.HumanRendering(env: Env[ObsType, ActType])[原始碼]

允許對支援「rgb_array」render 的環境進行類人 render。

當您已實作可以產生 RGB 影像但尚未實作任何程式碼將影像 render 到螢幕的環境時,此包裝函式特別有用。 如果您想要將此包裝函式與您的環境搭配使用,請記住在您環境的中繼資料中指定 "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

當環境實例化時,也可以直接套用包裝函式,只需將 render_mode="human" 傳遞至 make 即可。 只有在環境未在本機實作人類 render (即 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",則其 (即基礎環境的) render 方法將始終傳回空列表

>>> 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 - 新增 render 函式的順序強制執行

參數:
  • env – 要包裝的環境

  • disable_render_order_enforcing – 是否停用 render 順序強制執行

class gymnasium.wrappers.RenderCollection(env: Env[ObsType, ActType], pop_frames: bool = True, reset_clean: bool = True)[原始碼]

收集環境的 render 幀,例如 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

傳回 episode 執行步數的幀列表。 >>> 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

收集所有 episode 的所有幀,而不會在呼叫 render 時清除它們 >>> 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) – 如果為 true,則在呼叫 meth:render 後清除收集幀。 預設值為 True

  • reset_clean (bool) – 如果為 true,則在呼叫 meth:reset 時清除收集幀。 預設值為 True

資料轉換包裝函式

class gymnasium.wrappers.JaxToNumpy(env: Env[ObsType, ActType])[原始碼]

包裝基於 Jax 的環境,使其可以與 NumPy 陣列互動。

動作必須以 numpy 陣列形式提供,觀察結果將以 numpy 陣列形式傳回。 存在此包裝函式的向量版本,gymnasium.wrappers.vector.JaxToNumpy

註解

Jax To Numpy 和 Numpy to Jax 轉換不保證往返 (jax -> numpy -> jax) 和反之亦然。 原因在於 jax 不支援非陣列值,因此 numpy int_32(5) -> DeviceArray([5], dtype=jnp.int23)

範例

>>> import gymnasium as gym                                     
>>> env = gym.make("JaxEnv-vx")                                 
>>> env = JaxToNumpy(env)                                       
>>> obs, _ = env.reset(seed=123)                                
>>> type(obs)                                                   
<class 'numpy.ndarray'>
>>> action = env.action_space.sample()                          
>>> obs, reward, terminated, truncated, info = env.step(action) 
>>> type(obs)                                                   
<class 'numpy.ndarray'>
>>> type(reward)                                                
<class 'float'>
>>> type(terminated)                                            
<class 'bool'>
>>> type(truncated)                                             
<class 'bool'>
變更日誌
  • v1.0.0 - 初始新增

參數:

env – 要包裝的 jax 環境

class gymnasium.wrappers.JaxToTorch(env: gym.Env, device: Device | None = None)[原始碼]

包裝基於 Jax 的環境,使其可以與 PyTorch Tensor 互動。

動作必須以 PyTorch Tensor 形式提供,觀察結果將以 PyTorch Tensor 形式傳回。 存在此包裝函式的向量版本,gymnasium.wrappers.vector.JaxToTorch

註解

對於 rendered,這會以 NumPy 陣列而非 pytorch Tensor 形式傳回。

範例

>>> import torch                                                
>>> import gymnasium as gym                                     
>>> env = gym.make("JaxEnv-vx")                                 
>>> env = JaxtoTorch(env)                                       
>>> obs, _ = env.reset(seed=123)                                
>>> type(obs)                                                   
<class 'torch.Tensor'>
>>> action = torch.tensor(env.action_space.sample())            
>>> obs, reward, terminated, truncated, info = env.step(action) 
>>> type(obs)                                                   
<class 'torch.Tensor'>
>>> type(reward)                                                
<class 'float'>
>>> type(terminated)                                            
<class 'bool'>
>>> type(truncated)                                             
<class 'bool'>
變更日誌
  • v1.0.0 - 初始新增

參數:
  • env – 要包裝的基於 Jax 的環境

  • device – 應將 torch Tensor 移至的裝置

class gymnasium.wrappers.NumpyToTorch(env: gym.Env, device: Device | None = None)[source]

包裝一個基於 NumPy 的環境,使其可以與 PyTorch 張量互動。

動作必須以 PyTorch 張量形式提供,並且觀測將以 PyTorch 張量形式返回。 此包裝器存在向量版本,gymnasium.wrappers.vector.NumpyToTorch

註解

對於 rendered,這會以 NumPy 陣列而非 pytorch Tensor 形式傳回。

範例

>>> import torch
>>> import gymnasium as gym
>>> env = gym.make("CartPole-v1")
>>> env = NumpyToTorch(env)
>>> obs, _ = env.reset(seed=123)
>>> type(obs)
<class 'torch.Tensor'>
>>> action = torch.tensor(env.action_space.sample())
>>> obs, reward, terminated, truncated, info = env.step(action)
>>> type(obs)
<class 'torch.Tensor'>
>>> type(reward)
<class 'float'>
>>> type(terminated)
<class 'bool'>
>>> type(truncated)
<class 'bool'>
變更日誌
  • v1.0.0 - 初始新增

參數:
  • env – 要包裝的基於 NumPy 的環境

  • device – 應將 torch Tensor 移至的裝置