Gymnasium 向量环境 Wrappers 完全指南:VectorWrapper 体系、内置实现与实战应用

发布时间:2026/9/15 21:27:17
Gymnasium 向量环境 Wrappers 完全指南:VectorWrapper 体系、内置实现与实战应用
Gymnasium 向量环境 Wrappers 完全指南VectorWrapper 体系、内置实现与实战应用【免费下载链接】GymnasiumA standard API for single-agent reinforcement learning environments, with popular reference environments and related utilities (formerly Gym)项目地址: https://gitcode.com/GitHub_Trending/gy/Gymnasium导读向量环境Vector Env是 Gymnasium 中通过并行运行多个环境副本以提升采样吞吐量的核心机制。与单智能体环境一样向量环境也拥有一套完整的 Wrapper 体系——gymnasium.vector.VectorWrapper及其观察/动作/奖励三个子类以及围绕它们构建的几十个内置向量化 Wrapper覆盖观测变换、动作裁剪、奖励归一化、信息格式转换与数据框架转换等高频场景。本文以 docs/api/vector/wrappers.md 为主线结合 gymnasium/vector/vector_env.py 与 gymnasium/wrappers/vector/ 下的源码实现系统讲解向量 Wrapper 的类层次、四种分类Vector Only / Vectorized Common / Observation / Action / Reward / Data Conversion、每个内置 Wrapper 的参数语义与底层原理并提供可直接运行的代码示例帮助读者在训练管线中正确、高效地组合使用向量 Wrapper。向量 Wrapper 的分类总览根据 gymnasium/wrappers/vector/init.py 的__all__导出向量 Wrapper 可分为以下几大类分类包含的 Wrapper向量专属Vector OnlyDictInfoToList、VectorizeTransformObservation、VectorizeTransformAction、VectorizeTransformReward向量化通用Vectorized CommonRecordEpisodeStatistics观测 WrapperTransformObservation、FilterObservation、FlattenObservation、GrayscaleObservation、ResizeObservation、ReshapeObservation、RescaleObservation、DtypeObservation、NormalizeObservation动作 WrapperTransformAction、ClipAction、RescaleAction奖励 WrapperTransformReward、ClipReward、NormalizeReward数据转换Data ConversionArrayConversion、JaxToNumpy、JaxToTorch、NumpyToTorch此外gymnasium/wrappers/vector/init.py 还导出了渲染相关的RecordVideo与HumanRendering它们与单环境同名 Wrapper 对应。值得注意的是其中JaxToNumpy、JaxToTorch、NumpyToTorch以及ArrayConversion需要依赖jax或torch。为避免在import gymnasium时引入这些重依赖init.py 采用惰性加载机制它们不会在导入阶段直接 import而是通过模块级__getattr__在首次访问时才importlib.import_module对应模块。这意味着只有在真正使用这些 Wrapper 时才会加载jax/torch。VectorWrapper 基类向量的模块化变换接口类层次与核心职责所有向量 Wrapper 的根基是定义在 gymnasium/vector/vector_env.py 中的VectorWrapper。它的职责与单环境版的gymnasium.Wrapper完全对等——包装向量化环境允许模块化变换通过子类重写部分方法即可改变原环境行为而无需改动原始代码。类层次如下VectorEnv └── VectorWrapper # 通用包装基类 ├── VectorObservationWrapper # 观测变换observations() ├── VectorActionWrapper # 动作变换actions() └── VectorRewardWrapper # 奖励变换rewards()VectorWrapper.__init__接收一个VectorEnv实例并存储在self.env中若传入的不是VectorEnv实例会抛出TypeError见 vector_env.py。文档特别提醒子类若重写__init__不要忘记调用super().__init__(env)。透传接口与空间属性VectorWrapper默认将reset、step、render、close、close_extras全部透传给被包装的环境同时以属性形式透传num_envs、np_random、metadata、spec、render_mode、closed等元信息。它引入了一个关键设计四个可覆写的空间属性——observation_space、action_space、single_observation_space、single_action_space。其中single_*表示单个子环境的空间非single_*表示批量化后的空间通常维度多出一个num_envs首维。当包装器改变了观测或动作的形状/范围时就应该覆写对应空间否则下游算法会按错误的维度构建网络。其__repr__输出形如ClipReward, SyncVectorEnv(CartPole-v1, num_envs3)直观展示包装链。三个语义子类VectorObservationWrappervector_env.py对应单环境的ObservationWrapper。在reset与step返回观测后调用抽象方法observations(observations)做批量变换rewards、terminations、truncations、infos原样透传。构造时还会检查env.metadata中是否存在autoreset_mode只允许NEXT_STEP或DISABLED两种模式SAME_STEP会抛出ValueError并会告警缺失该元数据的环境。VectorActionWrappervector_env.py在step中先将动作交给抽象方法actions(actions)变换再把变换后的动作送入环境。VectorRewardWrappervector_env.py在step返回后调用抽象方法rewards(rewards)批量变换奖励。快速上手示例来自 vector_env.py 的 docstring 演示了向量 Wrapper 与make_vec的组合使用import gymnasium as gym envs gym.make_vec(CartPole-v1, num_envs3, vectorization_modesync, wrappers(gym.wrappers.TimeAwareObservation,)) envs gym.wrappers.vector.ClipReward(envs, min_reward0.2, max_reward0.8) print(envs) # ClipReward, SyncVectorEnv(CartPole-v1, num_envs3) print(envs.num_envs) # 3 print(envs.action_space) # MultiDiscrete([2 2 2]) print(envs.observation_space) # Box(..., (3, 5), float64) observations, infos envs.reset(seed123) _ envs.action_space.seed(123) actions envs.action_space.sample() observations, rewards, terminations, truncations, infos envs.step(actions) print(rewards) # array([0.8, 0.8, 0.8]) envs.close()从这个示例可以看到向量 Wrapper 的三个要点既可以通过make_vec的wrappers参数在创建时内置包装也可以在创建后用gymnasium.wrappers.vector.ClipReward(...)逐层叠加observation_space/action_space是批量化空间(3, 5)而single_observation_space/single_action_space是单个环境的空间(5,)step返回的rewards是形状为(num_envs,)的 NumPy 数组terminations与truncations同理infos是键 → 数组的字典结构。向量专属 Wrapper处理向量特有的问题VectorizeTransformObservation / VectorizeTransformAction / VectorizeTransformReward这三者解决了向量 Wrapper 家族中最核心的一个工程问题如何复用单环境的变换函数。以 vectorize_observation.py 中的VectorizeTransformObservation为例其构造方式与单环境版不同——它接收一个单环境 Wrapper 类wrapper和透传给该 Wrapper 的**kwargs内部构造一个仅含observation_space的伪单环境_SingleEnv实例化单环境 Wrapper 后在observations()中通过iterate逐个子环境应用self.wrapper.func(obs)再用concatenate拼回批量数组。这种设计让用户可以为向量环境复用任意自定义的 lambda 观测变换。以下示例来自 vectorize_observation.py把每个观测复制成两份import numpy as np import gymnasium as gym from gymnasium.spaces import Box from gymnasium.wrappers import TransformObservation from gymnasium.wrappers.vector import VectorizeTransformObservation envs gym.make_vec(CartPole-v1, num_envs3, vectorization_modesync) old_space envs.single_observation_space new_space Box(lownp.array([old_space.low, old_space.low]), highnp.array([old_space.high, old_space.high])) envs VectorizeTransformObservation( envs, wrapperTransformObservation, funclambda x: np.array([x, x]), observation_spacenew_space) obs, info envs.reset(seed123) # obs.shape (3, 2, 4) envs.close()其内部有两个值得注意的实现细节通过same_out self.observation_space self.env.observation_space判断变换是否改变空间形状若未改变则复用原数组内存做 in-place 拼接避免拷贝若改变则用deepcopy输出到预分配的空数组self.out。step中会额外处理infos[final_obs]在SAME_STEPautoreset 模式下终止子环境的最终观测同样需要逐个经过单环境 Wrapper 变换见 vectorize_observation.py保证最终观测与变换后观测空间一致。VectorizeTransformActionvectorize_action.py与VectorizeTransformRewardvectorize_reward.py遵循同一模式分别用于动作与奖励的逐元素变换。例如对奖励施加 ReLUfrom gymnasium.wrappers import TransformReward from gymnasium.wrappers.vector import VectorizeTransformReward envs gym.make_vec(MountainCarContinuous-v0, num_envs3) envs VectorizeTransformReward(envs, wrapperTransformReward, funclambda x: (x 0.0) * x)TransformObservation / TransformAction / TransformReward直接给出批量函数与上述三个向量化 Wrapper 相对的是三个直接批量 WrapperTransformObservation、TransformAction、TransformReward。它们不要求逐个元素变换而是让用户直接提供一个作用于整个批量数组的函数func。以 vectorize_observation.py 的TransformObservation为例其构造函数签名为TransformObservation(env, func, observation_spaceNone, single_observation_spaceNone)func作用于批量观测的函数observation_space包装后的批量观测空间为None时若提供了single_observation_space则由batch_space(single_observation_space, num_envs)自动推算single_observation_space单个子环境的观测空间为None时假定与env.single_observation_space相同。当两个空间均未提供时默认沿用env原空间若最终observation_space与batch_space(single_observation_space, num_envs)不一致会发出告警。docstring 中的完整示例将观测整体缩放平移import gymnasium as gym from gymnasium.spaces import Box from gymnasium.wrappers.vector import TransformObservation def scale_and_shift(obs): return (obs - 1.0) * 2.0 envs gym.make_vec(CartPole-v1, num_envs3, vectorization_modesync) new_obs_space Box(lowenvs.observation_space.low, highenvs.observation_space.high) envs TransformObservation(envs, funcscale_and_shift, observation_spacenew_obs_space) obs, info envs.reset(seed123) # 观测值全部被 (obs - 1.0) * 2.0 变换 envs.close()官方文档建议当批量函数与逐元素函数都存在时优先使用TransformObservation这类批量版本因为批量处理可以借助向量化运算如 NumPy/JAX 的并行优化获得更高吞吐只有无法写出批量版本、只能定义单元素变换时才使用VectorizeTransformObservation。TransformActionvectorize_action.py签名与之一致action_space/single_action_space典型用法是将连续动作整体收缩from gymnasium.spaces import Box from gymnasium.wrappers.vector import TransformAction def shrink_action(act): return act * 0.3 envs gym.make_vec(MountainCarContinuous-v0, num_envs3) new_action_space Box(lowshrink_action(envs.action_space.low), highshrink_action(envs.action_space.high)) envs TransformAction(envenvs, funcshrink_action, action_spacenew_action_space)TransformRewardvectorize_reward.py则只接受func对整个(num_envs,)奖励数组做变换。DictInfoToListdict 风格 info 与旧版 list 风格互转DictInfoToListdict_info_to_list.py用于把向量环境的info从dict 风格每个键对应一个长度为num_envs的数组并配套_key布尔掩码标记哪些子环境携带该键转换回list 风格[env_0_info, env_1_info, ...]即 v0.25 之前的旧接口。其_convert_info_to_list会递归处理嵌套 dict并依据_key掩码决定每个子环境的 info 是否包含对应键。envs gym.make_vec(CartPole-v1, num_envs3) obs, info envs.reset(seed123) # info {} envs DictInfoToList(envs) obs, info envs.reset(seed123) # info [{}, {}, {}]docstring 中给出的转换对照非常直观# dict 风格 {k: np.array([0., 0., 0.5, 0.3]), _k: np.array([False, False, True, True])} # list 风格 [{}, {}, {k: 0.5}, {k: 0.3}]文档强调了一个包装顺序约束若与其他会读写 info 的 Wrapper如RecordEpisodeStatistics联用DictInfoToList必须放在最外层即DictInfoToList(RecordEpisodeStatistics(vector_env))。因为RecordEpisodeStatistics要求infos为 dict 类型其step中会assert isinstance(infos, dict)见 common.py而DictInfoToList输出的 list 无法被它解析。向量化通用 WrapperRecordEpisodeStatisticsRecordEpisodeStatisticscommon.py是向量环境中用于追踪 episode 统计的核心 Wrapper。每当向量环境中任意子环境终止或截断时它会以键episode写入 infoinfos { ... episode: { r: 每个 done 子环境的累计奖励数组, l: 每个 done 子环境的 episode 长度数组, t: 每个 done 子环境从开始到结束的耗时数组 }, _episode: 长度等于 num_envs 的布尔数组 }其中_episode掩码标识哪些子环境在本步结束。其构造函数为env被包装的向量环境buffer_length100return_queue、length_queue、time_queue三个环形缓冲deque(maxlen...)的容量存放最近buffer_length个已结束 episode 的累计奖励、长度与耗时stats_keyepisodeinfo 中写入统计数据的键名可自定义以避免与环境中已有的同名键冲突若冲突会抛出ValueError。除写入 info 外还可以通过envs.return_queue与envs.length_queue直接读取最近若干 episode 的回报与长度用于绘制训练曲线。完整示例import gymnasium as gym from gymnasium.wrappers.vector import RecordEpisodeStatistics envs gym.make_vec(CartPole-v1, num_envs3) envs RecordEpisodeStatistics(envs) obs, info envs.reset(123) _ envs.action_space.seed(123) end False while not end: obs, rew, term, trunc, info envs.step(envs.action_space.sample()) end term.any() or trunc.any() envs.close() # info 形如 # {_episode: array([ True, False, False]), # episode: {l: array([11, 0, 0], dtypeint32), # r: array([11., 0., 0.], dtypefloat32), # t: array([0.007812, 0. , 0. ], dtypefloat32)}}实现上它区分两种 autoreset 模式NEXT_STEP默认终止/截断后的下一步才发生自动重置因此该步不计入下一个 episode 的统计——episode_returns[prev_dones] 0、episode_lengths[prev_dones] 0SAME_STEP子环境在终止/截断的同一步内完成重置每步都计入某个 episode因此不需要跳过前一步 done 的子环境。同时其reset支持options[reset_mask]做部分重置可以只对掩码为True的子环境清零统计、重设起始时间该掩码必须是形状为(num_envs,)的np.bool_数组且至少含一个True对应向量环境的部分重置partial reset能力。若环境 metadata 缺失autoreset_mode它会告警并默认按NEXT_STEP处理。向量化观测 Wrapper从 Filter 到 Normalize 的九件套九个观测 Wrapper 均继承自VectorizeTransformObservation即复用单环境gymnasium.wrappers中同名 Wrapper 的变换逻辑因此参数语义与单环境版本一一对应。Wrapper构造参数作用FilterObservationfilter_keysSequence[str \| int]从Dict/Tuple观测空间中挑选子键str对应 dict 键、int对应 tuple 索引FlattenObservation无展平观测要求空间实现spaces.utils.flatten_space/flattenGrayscaleObservationkeep_dimFalse将 RGB 图像转灰度keep_dimTrue时保留通道维ResizeObservationshape用 OpenCV 将图像观测缩放到指定形状ReshapeObservationshape改变数组观测形状元素总数须一致RescaleObservationmin_obs、max_obs将Box观测线性缩放到[min_obs, max_obs]DtypeObservationdtype转换观测的 dtypeNormalizeObservationepsilon1e-8基于RunningMeanStd对观测逐坐标做中心化与单位方差归一TransformObservation见上文自定义批量变换函数各 Wrapper 在源码 docstring 中均有带输入输出形状的示例例如# FlattenObservation把 CarRacing 的 (3, 96, 96, 3) 展平为 (3, 27648) envs FlattenObservation(envs) obs, info envs.reset(seed123) print(obs.shape) # (3, 27648) # GrayscaleObservationRGB → 灰度默认去掉通道维 envs GrayscaleObservation(envs) obs, info envs.reset(seed123) print(obs.shape) # (3, 96, 96) # ResizeObservation缩放到 (28, 28) envs ResizeObservation(envs, shape(28, 28)) obs, info envs.reset(seed123) print(obs.shape) # (3, 28, 28, 3) # ReshapeObservation(96, 96, 3) → (9216, 3) envs ReshapeObservation(envs, shape(9216, 3)) obs, info envs.reset(seed123) print(obs.shape) # (3, 9216, 3)FilterObservation的 docstring 演示了先构造 Dict 空间再过滤键的完整流程import numpy as np import gymnasium as gym from gymnasium.spaces import Dict, Box from gymnasium.wrappers import TransformObservation from gymnasium.wrappers.vector import VectorizeTransformObservation, FilterObservation envs gym.make_vec(CartPole-v1, num_envs3, vectorization_modesync) make_dict lambda x: {obs: x, junk: np.array([0.0])} new_space Dict({obs: envs.single_observation_space, junk: Box(low-1.0, high1.0)}) envs VectorizeTransformObservation(envenvs, wrapperTransformObservation, funcmake_dict, observation_spacenew_space) envs FilterObservation(envs, [obs]) obs, info envs.reset(seed123) # obs {obs: array(..., shape(3, 4))} envs.close()NormalizeObservation带状态的观测归一化NormalizeObservationstateful_observation.py是少数有内部状态的观测 Wrapper。它内部维护一个RunningMeanStd统计器在每次reset/step时更新观测的均值与方差然后输出(observations - obs_rms.mean) / sqrt(obs_rms.var epsilon)关键参数与行为epsilon1e-8防除零稳定项必须严格为正否则抛出InvalidBound源码注释指出非正值会让归一化结果退化为 NaNupdate_running_mean属性置为False可冻结统计更新典型场景是评估阶段沿用训练期统计归一化后的观测空间自动替换为Box(low-inf, highinf, shape..., dtypefloat32)仅支持NEXT_STEPautoreset 模式SAME_STEP会抛出ValueErrorreset不支持部分重置若options中出现不全为True的reset_mask会抛出ValueError见 stateful_observation.py。源码 docstring 的对照实验显示同样的随机策略跑 100 步未归一化时观测均值约为0.024、标准差约为0.62归一化后均值为-0.24、标准差约为1.19可见逐坐标中心化/单位方差的效果。向量化动作 WrapperClip 与 Rescale三个动作 Wrapper 中TransformAction已在上文介绍其余两个都继承自VectorizeTransformActionClipAction(env)vectorize_action.py把连续动作裁剪到Box动作空间的合法边界内无需额外参数。docstring 示例中向环境传入越界动作[5.0, -5.0, 2.0]环境照常运行说明动作已被安全裁剪。RescaleAction(env, min_action, max_action)vectorize_action.py对连续动作空间做仿射缩放使动作落在[min_action, max_action]区间。min_action/max_action既可以是标量也可以是逐维度的数组非常适合把策略网络的输出例如 sigmoid/tanh 输出[0,1]或[-1,1]映射到环境实际动作范围from gymnasium.wrappers.vector import RescaleAction # 将 MountainCarContinuous 的动作原本约 [-1, 1]缩放到 [0, 1] envs gym.make_vec(MountainCarContinuous-v0, num_envs3) envs RescaleAction(envs, 0.0, 1.0) _ envs.action_space.seed(123) obs, info envs.reset(seed123) obs, rew, term, trunc, info envs.step(0.5 * np.ones((3, 1)))其 docstring 的对照实验显示缩放前后施加相同的0.5动作环境的轨迹出现差异验证了仿射变换确实生效。向量化奖励 WrapperClip 与 NormalizeClipReward(env, min_rewardNone, max_rewardNone)vectorize_reward.py将每个子环境的奖励裁剪到[min_reward, max_reward]None表示对应方向不裁剪。docstring 示例把奖励裁剪到[0.0, 2.0]后MountainCarContinuous的稀疏负奖励全部被裁为0。NormalizeReward(env, gamma0.99, epsilon1e-8)stateful_reward.py基于折扣累计回报的指数滑动平均将奖励缩放到近似固定方差。其核心逻辑是维护每个子环境的折扣累计回报accumulated_reward accumulated_reward * gamma * (1 - terminated) reward再用return_rmsRunningMeanStd跟踪该累计回报的均值方差最终输出reward / sqrt(var epsilon)。参数约束gamma必须在[0, 1]内指数滑动平均每步乘以gamma超过 1 会发散负值会震荡符号否则抛InvalidBoundepsilon必须严格为正与NormalizeObservation相同提供update_running_mean属性用于评估阶段冻结统计。实现同样区分 autoreset 模式SAME_STEP模式下所有子环境每一步都参与统计更新NEXT_STEP/DISABLED模式下则跳过前一步已 done 的子环境见 stateful_reward.py。数据转换 Wrapper跨框架的无缝互操作当向量环境本身基于某种 Array API 框架如jax.numpy、torch实现时可用数据转换 Wrapper 把环境输入输出统一到目标框架同时尽可能避免数据搬运与设备迁移。ArrayConversion通用转换基座ArrayConversionarray_conversion.py接收四个参数env被包装的向量环境env_xp环境所在框架Array API 模块如jnp、np、torchtarget_xp目标框架模块env_device/target_device环境侧与目标侧设备如cuda可省略。其step先把动作转换回env_xp含设备迁移环境返回后把观测、奖励、终止、截断与 info 全部转换到target_xp/target_devicereset还会把options一并转换。该 Wrapper 还实现了__getstate__/__setstate__以模块名字符串而非模块对象进行序列化保证可被 pickle。JaxToNumpy / JaxToTorch / NumpyToTorch三个便捷子类对ArrayConversion做了框架固定JaxToNumpy(env)jax_to_numpy.py包装 JAX 向量环境动作以 NumPy 数组输入观测/奖励/终止/截断以 NumPy 数组返回。若环境未安装 JAX会抛出DependencyNotInstalled提示执行pip install gymnasium[jax]JaxToTorch、NumpyToTorch对应地转换为 PyTorch 张量需要安装torch。import gymnasium as gym from gymnasium.wrappers.vector import JaxToNumpy # 包装一个 JAX 实现的向量环境以 numpy 接口交互 envs gym.make_vec(JaxEnv-vx, 3) # 示意 envs JaxToNumpy(envs) obs, info envs.reset(seed123) # obs 为 numpy 数组实战组合构建一条典型训练采样管线综合以上内容一条面向策略梯度类算法的典型向量采样管线可以这样搭建import gymnasium as gym from gymnasium.wrappers.vector import ( RecordEpisodeStatistics, NormalizeObservation, NormalizeReward, ClipReward, RescaleAction, FlattenObservation, ) # 1. 创建 8 个并行子环境的向量环境异步模式进一步提速 envs gym.make_vec(CarRacing-v3, num_envs8, vectorization_modeasync) # 2. 观测侧展平 → 运行均值归一化 envs FlattenObservation(envs) envs NormalizeObservation(envs) # 3. 动作侧将策略输出 [0, 1] 缩放到环境实际动作范围 envs RescaleAction(envs, min_action-1.0, max_action1.0) # 4. 奖励侧先裁剪极值再归一化 envs ClipReward(envs, min_reward-10.0, max_reward10.0) envs NormalizeReward(envs, gamma0.99) # 5. 记录 episode 统计最外层训练循环从 info 读取 episode 数据 envs RecordEpisodeStatistics(envs, buffer_length100) obs, info envs.reset(seed42) while not (term.any() or trunc.any()): obs, rew, term, trunc, info envs.step(envs.action_space.sample()) # 从 info[episode] 读取最近结束子环境的回报/长度/耗时 if episode in info: print(returns:, info[episode][r]) print(lengths:, info[episode][l]) envs.close()组合时需要留意以下几点包装顺序从内到外依次是数据形态修正Flatten/Rescale/Clip→ 归一化Normalize→ 统计记录RecordEpisodeStatistics。RecordEpisodeStatistics依赖 dict 风格 info因此DictInfoToList若同时使用必须位于其外层同理NormalizeObservation/NormalizeReward都要求infos为 dict不能包裹在DictInfoToList之内。空间一致性任何改变观测/动作形状或范围的 Wrapper都应同步更新对应的(single_)observation_space/(single_)action_space内置 Wrapper 已自动处理否则后续网络构建会出错。autoreset 模式约束VectorObservationWrapper及其子类、NormalizeObservation要求环境为NEXT_STEP或DISABLED模式RecordEpisodeStatistics与NormalizeReward对两种模式都有专门适配逻辑。Gymnasium 默认实现使用NEXT_STEPAutoresetMode枚举定义见 vector_env.py而某些第三方向量实现或训练算法可能只支持特定模式组合前应确认env.metadata[autoreset_mode]。info 掩码语义dict 风格 info 中每个键都伴随_key布尔掩码标记哪些子环境在该步携带了该键读取info[final_obs]等稀疏键时必须结合info[_final_obs]使用这正是DictInfoToList帮你完成的转换工作。小结Gymnasium 的向量 Wrapper 体系以VectorWrapper→VectorObservationWrapper/VectorActionWrapper/VectorRewardWrapper为骨架gymnasium/vector/vector_env.py以 gymnasium/wrappers/vector/ 下按职责拆分的实现为血肉VectorizeTransform*三件套让单环境变换函数得以复用DictInfoToList打通新旧 info 接口RecordEpisodeStatistics输出训练所需的 episode 统计观测/动作/奖励三类 Wrapper 覆盖了从图像预处理到奖励归一化的全部常规需求ArrayConversion家族则让跨框架NumPy / JAX / PyTorch交互变得无痛。理解它们的类层次、参数语义与包装顺序约束即可在向量化训练管线中灵活组合出稳定、高效的数据流。延伸阅读向量环境基类与 autoreset 模式gymnasium/vector/vector_env.py向量 Wrapper 导出清单与惰性加载gymnasium/wrappers/vector/init.py向量专属 Wrapper 源码vectorize_observation.py、vectorize_action.py、vectorize_reward.py、dict_info_to_list.py有状态 Wrapper 源码stateful_observation.py、stateful_reward.py、common.py数据转换 Wrapper 源码array_conversion.py、jax_to_numpy.py、jax_to_torch.py、numpy_to_torch.py向量 Wrapper 测试tests/wrappers/vector/如 test_normalize_observation.py、test_normalize_reward.py【免费下载链接】GymnasiumA standard API for single-agent reinforcement learning environments, with popular reference environments and related utilities (formerly Gym)项目地址: https://gitcode.com/GitHub_Trending/gy/Gymnasium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考