基本用法¶
Gymnasium 是一个项目,为所有单智能体强化学习环境提供 API(应用程序编程接口),并实现了常见环境:cartpole、pendulum、mountain-car、mujoco、atari 等。本页将概述如何使用 Gymnasium 的基础知识,包括其四个关键功能:make()
、Env.reset()
、Env.step()
和 Env.render()
。
Gymnasium 的核心是 Env
,一个高级 python 类,表示来自强化学习理论的马尔可夫决策过程 (MDP)(注意:这不是一个完美的重构,缺少 MDP 的几个组成部分)。该类为用户提供了生成初始状态、转换/移动到给定动作的新状态以及可视化环境的能力。与 Env
一起,提供了 Wrapper
来帮助增强/修改环境,特别是智能体观测、奖励和采取的动作。
初始化环境¶
在 Gymnasium 中初始化环境非常容易,可以通过 make()
函数完成
import gymnasium as gym
env = gym.make('CartPole-v1')
此函数将返回一个 Env
,供用户与之交互。要查看您可以创建的所有环境,请使用 pprint_registry()
。此外,make()
提供了许多额外的参数,用于指定环境的关键字、添加更多或更少的封装器等。有关更多信息,请参阅 make()
。
与环境交互¶
在强化学习中,下面所示的经典“智能体-环境循环”是对智能体和环境如何相互作用的简化表示。智能体接收关于环境的观测,然后智能体选择一个动作,环境使用该动作来确定奖励和下一个观测。然后循环重复自身,直到环境结束(终止)。


对于 Gymnasium,“智能体-环境循环”在下面针对单个 episode(直到环境结束)实现。有关逐行解释,请参见下一节。请注意,运行此代码需要安装 swig (pip install swig
或 下载) 以及 pip install "gymnasium[box2d]"
。
import gymnasium as gym
env = gym.make("LunarLander-v3", render_mode="human")
observation, info = env.reset()
episode_over = False
while not episode_over:
action = env.action_space.sample() # agent policy that uses the observation and info
observation, reward, terminated, truncated, info = env.step(action)
episode_over = terminated or truncated
env.close()
输出应如下所示

代码解释¶
首先,使用 make()
创建环境,并使用额外的关键字 "render_mode"
来指定环境应如何可视化。有关不同渲染模式的默认含义的详细信息,请参阅 Env.render()
。在此示例中,我们使用 "LunarLander"
环境,其中智能体控制需要安全着陆的宇宙飞船。
初始化环境后,我们 Env.reset()
环境以获取环境的第一个观测以及附加信息。为了使用特定的随机种子或选项初始化环境(有关可能的值,请参见环境文档),请将 seed
或 options
参数与 reset()
一起使用。
由于我们希望继续智能体-环境循环直到环境结束,这在未知数量的时间步长内,我们将 episode_over
定义为一个变量,以了解何时停止与环境交互以及使用它的 while 循环。
接下来,智能体在环境中执行一个动作,Env.step()
执行所选动作(在本例中为随机动作,使用 env.action_space.sample()
)以更新环境。此动作可以想象成移动机器人或按下游戏控制器的按钮,从而导致环境内部发生变化。结果,智能体从更新后的环境接收到新的观测以及执行动作的奖励。例如,此奖励可能是摧毁敌人后的正奖励,或者是移入熔岩后的负奖励。这种动作-观测交换被称为时间步。
但是,在一些时间步之后,环境可能会结束,这称为终止状态。例如,机器人可能已坠毁,或者可能已成功完成任务,环境将需要停止,因为智能体无法继续。在 Gymnasium 中,如果环境已终止,则 step()
将其作为第三个变量 terminated
返回。同样,我们也可能希望环境在固定数量的时间步后结束,在这种情况下,环境会发出截断信号。如果 terminated
或 truncated
中的任何一个为 True
,那么我们将结束 episode,但在大多数情况下,用户可能希望重新启动环境,这可以使用 env.reset()
完成。
动作空间和观测空间¶
每个环境都使用 action_space
和 observation_space
属性指定有效动作和观测的格式。这有助于了解环境的预期输入和输出,因为所有有效动作和观测都应包含在其各自的空间内。在上面的示例中,我们通过 env.action_space.sample()
采样随机动作,而不是使用智能体策略,将观测映射到用户想要执行的动作。
重要的是,Env.action_space
和 Env.observation_space
是 Space
的实例,这是一个高级 python 类,提供关键函数:Space.contains()
和 Space.sample()
。Gymnasium 支持用户可能需要的各种空间
Box
:描述具有任意 n 维形状的上限和下限的有界空间。Discrete
:描述一个离散空间,其中{0, 1, ..., n-1}
是我们的观测或动作可以采用的可能值。MultiBinary
:描述任意 n 维形状的二进制空间。MultiDiscrete
:由一系列Discrete
动作空间组成,每个元素中的动作数量不同。Text
:描述具有最小和最大长度的字符串空间。Dict
:描述更简单空间的字典。Tuple
:描述简单空间的元组。Graph
:描述具有互连节点和边的数学图(网络)。Sequence
:描述更简单空间元素的可变长度。
有关空间的示例用法,请参阅其 文档 以及 实用工具函数。还有一些更小众的空间 Graph
、Sequence
和 Text
。
修改环境¶
封装器是修改现有环境的便捷方法,无需直接更改底层代码。使用封装器将使您避免大量样板代码,并使您的环境更模块化。封装器也可以链接起来以结合其效果。大多数通过 gymnasium.make()
生成的环境默认情况下已经使用 TimeLimit
、OrderEnforcing
和 PassiveEnvChecker
进行封装。
为了封装环境,您必须首先初始化一个基本环境。然后,您可以将此环境以及(可能可选的)参数传递给封装器的构造函数
>>> import gymnasium as gym
>>> from gymnasium.wrappers import FlattenObservation
>>> env = gym.make("CarRacing-v3")
>>> env.observation_space.shape
(96, 96, 3)
>>> wrapped_env = FlattenObservation(env)
>>> wrapped_env.observation_space.shape
(27648,)
Gymnasium 已经为您提供了许多常用的封装器。一些例子
TimeLimit
:如果超过最大时间步数(或基本环境已发出截断信号),则发出截断信号。ClipAction
:裁剪传递给step
的任何动作,使其位于基本环境的动作空间中。RescaleAction
:对动作应用仿射变换,以线性缩放环境的新下限和上限。TimeAwareObservation
:向观测添加有关时间步索引的信息。在某些情况下,有助于确保转换是马尔可夫的。
有关 Gymnasium 中已实现的封装器的完整列表,请参阅 封装器。
如果您有一个封装的环境,并且想要获取所有封装器层下方的未封装环境(以便您可以手动调用函数或更改环境的某些底层方面),则可以使用 unwrapped
属性。如果环境已经是基本环境,则 unwrapped
属性将只返回自身。
>>> wrapped_env
<FlattenObservation<TimeLimit<OrderEnforcing<PassiveEnvChecker<CarRacing<CarRacing-v3>>>>>>
>>> wrapped_env.unwrapped
<gymnasium.envs.box2d.car_racing.CarRacing object at 0x7f04efcb8850>