基本用法

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()

与环境交互

在强化学习中,下面所示的经典“智能体-环境循环”是对智能体和环境如何相互作用的简化表示。智能体接收关于环境的观测,然后智能体选择一个动作,环境使用该动作来确定奖励和下一个观测。然后循环重复自身,直到环境结束(终止)。

../../_images/AE_loop.png ../../_images/AE_loop_dark.png

对于 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()

输出应如下所示

https://user-images.githubusercontent.com/15806078/153222406-af5ce6f0-4696-4a24-a683-46ad4939170c.gif

代码解释

首先,使用 make() 创建环境,并使用额外的关键字 "render_mode" 来指定环境应如何可视化。有关不同渲染模式的默认含义的详细信息,请参阅 Env.render()。在此示例中,我们使用 "LunarLander" 环境,其中智能体控制需要安全着陆的宇宙飞船。

初始化环境后,我们 Env.reset() 环境以获取环境的第一个观测以及附加信息。为了使用特定的随机种子或选项初始化环境(有关可能的值,请参见环境文档),请将 seedoptions 参数与 reset() 一起使用。

由于我们希望继续智能体-环境循环直到环境结束,这在未知数量的时间步长内,我们将 episode_over 定义为一个变量,以了解何时停止与环境交互以及使用它的 while 循环。

接下来,智能体在环境中执行一个动作,Env.step() 执行所选动作(在本例中为随机动作,使用 env.action_space.sample())以更新环境。此动作可以想象成移动机器人或按下游戏控制器的按钮,从而导致环境内部发生变化。结果,智能体从更新后的环境接收到新的观测以及执行动作的奖励。例如,此奖励可能是摧毁敌人后的正奖励,或者是移入熔岩后的负奖励。这种动作-观测交换被称为时间步

但是,在一些时间步之后,环境可能会结束,这称为终止状态。例如,机器人可能已坠毁,或者可能已成功完成任务,环境将需要停止,因为智能体无法继续。在 Gymnasium 中,如果环境已终止,则 step() 将其作为第三个变量 terminated 返回。同样,我们也可能希望环境在固定数量的时间步后结束,在这种情况下,环境会发出截断信号。如果 terminatedtruncated 中的任何一个为 True,那么我们将结束 episode,但在大多数情况下,用户可能希望重新启动环境,这可以使用 env.reset() 完成。

动作空间和观测空间

每个环境都使用 action_spaceobservation_space 属性指定有效动作和观测的格式。这有助于了解环境的预期输入和输出,因为所有有效动作和观测都应包含在其各自的空间内。在上面的示例中,我们通过 env.action_space.sample() 采样随机动作,而不是使用智能体策略,将观测映射到用户想要执行的动作。

重要的是,Env.action_spaceEnv.observation_spaceSpace 的实例,这是一个高级 python 类,提供关键函数:Space.contains()Space.sample()。Gymnasium 支持用户可能需要的各种空间

  • Box:描述具有任意 n 维形状的上限和下限的有界空间。

  • Discrete:描述一个离散空间,其中 {0, 1, ..., n-1} 是我们的观测或动作可以采用的可能值。

  • MultiBinary:描述任意 n 维形状的二进制空间。

  • MultiDiscrete:由一系列 Discrete 动作空间组成,每个元素中的动作数量不同。

  • Text:描述具有最小和最大长度的字符串空间。

  • Dict:描述更简单空间的字典。

  • Tuple:描述简单空间的元组。

  • Graph:描述具有互连节点和边的数学图(网络)。

  • Sequence:描述更简单空间元素的可变长度。

有关空间的示例用法,请参阅其 文档 以及 实用工具函数。还有一些更小众的空间 GraphSequenceText

修改环境

封装器是修改现有环境的便捷方法,无需直接更改底层代码。使用封装器将使您避免大量样板代码,并使您的环境更模块化。封装器也可以链接起来以结合其效果。大多数通过 gymnasium.make() 生成的环境默认情况下已经使用 TimeLimitOrderEnforcingPassiveEnvChecker 进行封装。

为了封装环境,您必须首先初始化一个基本环境。然后,您可以将此环境以及(可能可选的)参数传递给封装器的构造函数

>>> 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>

更多信息