name: gymnasium
description: API standard pour les environnements d'apprentissage par renforcement mono-agent (Gymnasium). Fournit des environnements Classic Control, Box2D, Toy Text, MuJoCo et Atari avec une interface unifiée env.step()/env.reset(). Pour l'RL multi-agent, utilisez PettingZoo. Pour les implémentations d'algorithmes, utilisez stable-baselines3 ou CleanRL.
license: MIT license
tags: [single-agent-rl, rl-environments, control-benchmarks, environment-wrappers, gymnasium]
metadata:
skill-author: K-Dense Inc.
-----|------|---------|
| observation | ndarray / dict | Observation d'état actuelle |
| reward | float | Récompense immédiate |
| terminated | bool | État terminal atteint (succès/échec) |
| truncated | bool | Épisode terminé par limite de temps/signal externe |
| info | dict | Infos diagnostiques auxiliaires |
Distinction critique : terminated signifie que le MDP s'est terminé naturellement. truncated signifie qu'il a atteint une limite de temps. Les deux doivent déclencher reset(), mais votre algorithme doit les gérer différemment (pas de bootstrap de valeur sur terminated).
3. Familles d'environnements disponibles
| Famille | Exemples | Installation | Cas d'usage |
|---|---|---|---|
| Classic Control | CartPole, MountainCar, Pendulum, Acrobot | pip install gymnasium |
Débogage d'algorithmes, tests rapides |
| Box2D | LunarLander, BipedalWalker, CarRacing | pip install "gymnasium[box2d]" |
Problèmes jouets basés sur la physique |
| Toy Text | FrozenLake, Taxi, Blackjack | pip install gymnasium |
RL discret, enseignement |
| MuJoCo | HalfCheetah, Hopper, Humanoid, Ant | pip install "gymnasium[mujoco]" |
Benchmarks de contrôle continu |
| Atari | Breakout, Pong, SpaceInvaders | pip install "gymnasium[atari]" (ALE) |
RL basé pixels, développement DQN |
Installer tous :
pip install "gymnasium[all]"
4. Espaces d'observation et d'action
import gymnasium as gym
from gymnasium import spaces
env = gym.make("CartPole-v1")
print(env.observation_space) # Box([-4.8 ...], [4.8 ...], (4,), float32)
print(env.action_space) # Discrete(2)
# Vérifier les propriétés de l'espace
assert isinstance(env.observation_space, spaces.Box)
print(env.observation_space.shape) # (4,)
print(env.observation_space.dtype) # float32
print(env.observation_space.low) # [-4.8 -inf -0.418 -inf]
print(env.observation_space.high) # [4.8 inf 0.418 inf]
assert isinstance(env.action_space, spaces.Discrete)
print(env.action_space.n) # 2
5. Créer des environnements personnalisés
import gymnasium as gym
from gymnasium import spaces
import numpy as np
class CustomEnv(gym.Env):
metadata = {"render_modes": ["human", "rgb_array"], "render_fps": 30}
def __init__(self, render_mode=None, size=5):
super().__init__()
self.size = size
self.observation_space = spaces.Dict({
"agent": spaces.Box(0, size - 1, shape=(2,), dtype=int),
"target": spaces.Box(0, size - 1, shape=(2,), dtype=int),
})
self.action_space = spaces.Discrete(4) # 0=up, 1=right, 2=down, 3=left
self._action_to_direction = {
0: np.array([1, 0]),
1: np.array([0, 1]),
2: np.array([-1, 0]),
3: np.array([0, -1]),
}
self.render_mode = render_mode
def _get_obs(self):
return {"agent": self._agent_location, "target": self._target_location}
def reset(self, seed=None, options=None):
super().reset(seed=seed)
self._agent_location = self.np_random.integers(0, self.size, size=2)
self._target_location = self._agent_location.copy()
while np.array_equal(self._target_location, self._agent_location):
self._target_location = self.np_random.integers(0, self.size, size=2)
return self._get_obs(), {}
def step(self, action):
direction = self._action_to_direction[action]
self._agent_location = np.clip(
self._agent_location + direction, 0, self.size - 1
)
terminated = np.array_equal(self._agent_location, self._target_location)
reward = 1 if terminated else -0.01
return self._get_obs(), reward, terminated, False, {}
def render(self):
if self.render_mode == "human":
grid = np.full((self.size, self.size), ".")
grid[self._target_location[0], self._target_location[1]] = "T"
grid[self._agent_location[0], self._agent_location[1]] = "A"
print("\n".join(" ".join(row) for row in grid) + "\n")
def close(self):
pass
Enregistrer et utiliser :
gym.register(id="CustomEnv-v0", entry_point=CustomEnv, max_episode_steps=100)
env = gym.make("CustomEnv-v0")
6. Wrappers essentiels
from gymnasium import wrappers
env = gym.make("CartPole-v1")
# Normaliser les observations (moyenne/écart-type courants)
env = wrappers.NormalizeObservation(env)
# Normaliser les récompenses
env = wrappers.NormalizeReward(env, gamma=0.99)
# Écrêter les actions à la plage valide
env = wrappers.ClipAction(env)
# Redimensionner les actions de [-1,1] aux bornes de l'environnement
env = wrappers.RescaleAction(env, min_action=-1, max_action=1)
# Convertir en observation unique (aplatir les espaces dict)
env = wrappers.FlattenObservation(env)
# Redimensionner les observations d'image
env = wrappers.ResizeObservation(env, shape=(84, 84))
# Empilement de frames (style Atari)
env = wrappers.FrameStackObservation(env, stack_size=4)
# Application de la limite de temps
env = wrappers.TimeLimit(env, max_episode_steps=500)
# Enregistrer les épisodes comme vidéos
env = wrappers.RecordVideo(env, "videos/", episode_trigger=lambda x: x % 100 == 0)
# Transformer les récompenses
from gymnasium.wrappers import TransformReward
env = TransformReward(env, lambda r: np.clip(r, -1, 1))
7. Environnements vectorisés
from gymnasium.vector import SyncVectorEnv, AsyncVectorEnv
def make_env(env_id, seed):
def _init():
env = gym.make(env_id)
env.reset(seed=seed)
return env
return _init
# Synchrone (séquentiel)
envs = SyncVectorEnv([make_env("CartPole-v1", i) for i in range(4)])
obs, _ = envs.reset()
obs, rewards, terminateds, truncateds, infos = envs.step(actions)
# Asynchrone (processus parallèles)
envs = AsyncVectorEnv([make_env("CartPole-v1", i) for i in range(8)])
8. Versioning des environnements
Gymnasium utilise le versioning sémantique : CartPole-v0, CartPole-v1. Quand la dynamique, la fonction de récompense ou l'espace d'observation change, le numéro de version s'incrémente. Fixez toujours les versions d'environnement dans vos expériences pour la reproductibilité.
9. Vérifier la validité d'un environnement
from gymnasium.utils.env_checker import check_env
env = gym.make("CartPole-v1")
check_env(env, warn=True) # Vérifie la conformité API
Patterns clés
- Utilisez toujours
seeddansreset()pour des expériences reproductibles - Distinguez
terminateddetruncateddans le bootstrap de valeur - Utilisez
wrappers.RecordVideopour déboguer et partager les résultats - Préférez Gymnasium à l'ancien Gym — Gym n'est plus maintenu
- Utilisez
AsyncVectorEnvpour les environnements limités par CPU,SyncVectorEnvpour les légers info["terminal_observation"]est disponible après auto-reset dans les envs vectorisés