遷移指南 - v0.21 到 v1.0.0

誰應該閱讀本指南?

如果您是 Gymnasium 的新使用者:您可以跳過此頁面!本指南適用於從舊版本 OpenAI Gym 遷移的使用者。如果您剛開始接觸強化學習,請轉到基本用法

如果您正在從 OpenAI Gym 遷移:本指南將幫助您更新程式碼以與 Gymnasium 相容。這些更改意義重大,但一旦您理解了其背後的原因,就會發現它們很簡單。

如果您正在更新舊教程:許多線上強化學習教程使用舊的 v0.21 API。本指南將向您展示如何使這些程式碼現代化。

為什麼 API 發生了變化?

Gymnasium 是 OpenAI Gym v0.26 的一個分支,該版本引入了與 Gym v0.21 不相容的重大更改。這些更改並非輕率而為——它們解決了導致強化學習研究和開發更加困難的重要問題。

舊版 API 的主要問題包括: - 回合結束的歧義:單個 done 標誌無法區分“任務完成”和“達到時間限制” - 不一致的隨機種子:隨機數生成不可靠且難以復現 - 渲染複雜性:在不同視覺模式之間切換不必要的複雜 - 復現性問題:細微的錯誤使得研究結果難以復現

對於仍在使用 v0.21 API 的環境,請參閱相容性指南

快速參考:完整更改表

元件

v0.21 (舊)

v0.26+ (新)

影響

包匯入

import gym

import gymnasium as gym

所有程式碼

環境重置

obs = env.reset()

obs, info = env.reset()

訓練迴圈

隨機種子

env.seed(42)

env.reset(seed=42)

復現性

步進函式

obs, reward, done, info = env.step(action)

obs, reward, terminated, truncated, info = env.step(action)

強化學習演算法

回合結束

while not done:

while not (terminated or truncated):

訓練迴圈

渲染模式

env.render(mode="human")

gym.make(env_id, render_mode="human")

視覺化

時間限制檢測

info.get('TimeLimit.truncated')

truncated 返回值

強化學習演算法

價值自舉

target = reward + (1-done) * gamma * next_value

target = reward + (1-terminated) * gamma * next_value

強化學習正確性

程式碼並排比較

舊版 v0.21 程式碼

import gym

# Environment creation and seeding
env = gym.make("LunarLander-v3", options={})
env.seed(123)
observation = env.reset()

# Training loop
done = False
while not done:
    action = env.action_space.sample()
    observation, reward, done, info = env.step(action)
    env.render(mode="human")

env.close()

新版 v0.26+ 程式碼(包括 v1.0.0)

import gymnasium as gym  # Note: 'gymnasium' not 'gym'

# Environment creation with render mode specified upfront
env = gym.make("LunarLander-v3", render_mode="human")

# Reset with seed parameter
observation, info = env.reset(seed=123, options={})

# Training loop with terminated/truncated distinction
done = False
while not done:
    action = env.action_space.sample()
    observation, reward, terminated, truncated, info = env.step(action)

    # Episode ends if either terminated OR truncated
    done = terminated or truncated

env.close()

關鍵更改細分

1. 包名稱更改

舊版import gym 新版import gymnasium as gym

原因:Gymnasium 是一個獨立專案,它維護並改進了原始 Gym 程式碼庫。

# Update your imports
# OLD
import gym

# NEW
import gymnasium as gym

2. 隨機種子和隨機數生成

最大的概念性變化是隨機性的處理方式。

舊版 v0.21:獨立的 seed() 方法

env = gym.make("CartPole-v1")
env.seed(42)  # Set random seed
obs = env.reset()  # Reset environment

新版 v0.26+:種子透過 reset() 傳遞

env = gym.make("CartPole-v1")
obs, info = env.reset(seed=42)  # Seed and reset together

為什麼會改變:某些環境(特別是模擬遊戲)只能在回合開始時設定其隨機狀態,而不能在回合中間設定。舊方法可能導致不一致的行為。

實際影響:

# OLD: Seeding applied to all future episodes
env.seed(42)
for episode in range(10):
    obs = env.reset()

# NEW: Each episode can have its own seed
for episode in range(10):
    obs, info = env.reset(seed=42 + episode)  # Each episode gets unique seed

3. 環境重置的變化

舊版 v0.21:僅返回觀測

observation = env.reset()

新版 v0.26+:返回觀測和資訊

observation, info = env.reset()

為什麼會改變:

  • info 提供對除錯資訊的一致訪問

  • seed 引數實現可復現的回合

  • options 引數允許回合特定配置

常見遷移模式:

# If you don't need the new features, just unpack the tuple
obs, _ = env.reset()  # Ignore info with underscore

# If you want to maintain the same random behavior as v0.21
env.reset(seed=42)  # Set seed once
# Then for subsequent resets:
obs, info = env.reset()  # Uses internal random state

4. 步進函式:doneterminated/truncated 分割

這是訓練演算法最重要的變化。

舊版 v0.21:單個 done 標誌

obs, reward, done, info = env.step(action)

新版 v0.26+:獨立的 terminatedtruncated 標誌

obs, reward, terminated, truncated, info = env.step(action)

為什麼這很重要:

  • terminated:回合因任務完成或失敗而結束(智慧體達到目標、死亡等)

  • truncated:回合因外部限制而結束(時間限制、步數限制等)

這種區分對於強化學習演算法中的價值函式自舉至關重要

# OLD (ambiguous)
if done:
    # Should we bootstrap? We don't know if this was natural termination or time limit!
    next_value = 0  # Assumption that may be wrong

# NEW (clear)
if terminated:
    next_value = 0      # Natural ending - no future value
elif truncated:
    next_value = value_function(next_obs)  # Time limit - estimate future value

遷移策略:

# Simple migration (works for many cases)
obs, reward, terminated, truncated, info = env.step(action)
done = terminated or truncated

# Better migration (preserves RL algorithm correctness)
obs, reward, terminated, truncated, info = env.step(action)
if terminated:
    # Episode naturally ended - use reward as-is
    target = reward
elif truncated:
    # Episode cut short - may need to estimate remaining value
    target = reward + discount * estimate_value(obs)

更多資訊,請參閱我們關於此的部落格文章

5. 渲染模式更改

舊版 v0.21:每次指定渲染模式

env = gym.make("CartPole-v1")
env.render(mode="human")     # Visual window
env.render(mode="rgb_array") # Get pixel array

新版 v0.26+:建立時固定渲染模式

env = gym.make("CartPole-v1", render_mode="human")     # For visual display
env = gym.make("CartPole-v1", render_mode="rgb_array") # For recording
env.render()  # Uses the mode specified at creation

為什麼會改變:有些環境無法在執行時切換渲染模式。在建立時固定模式可以實現更好的最佳化並防止錯誤。

實際影響:

# OLD: Could switch modes dynamically
env = gym.make("CartPole-v1")
for episode in range(10):
    # ... episode code ...
    if episode % 10 == 0:
        env.render(mode="human")  # Show every 10th episode

# NEW: Create separate environments for different purposes
training_env = gym.make("CartPole-v1")  # No rendering for speed
eval_env = gym.make("CartPole-v1", render_mode="human")  # Visual for evaluation

# Or use None for no rendering, then create visual env when needed
env = gym.make("CartPole-v1", render_mode=None)  # Fast training
if need_visualization:
    visual_env = gym.make("CartPole-v1", render_mode="human")

TimeLimit 封裝器更改

TimeLimit 封裝器的行為也已更改,以符合新的終止模型。

舊版 v0.21:將 TimeLimit.truncated 新增到 info 字典 ```python obs, reward, done, info = env.step(action) if done and info.get(‘TimeLimit.truncated’, False)

# 回合因時間限制而結束

新版 v0.26+:使用 truncated 返回值

obs, reward, terminated, truncated, info = env.step(action)
if truncated:
    # Episode ended due to time limit (or other truncation)
    pass
if terminated:
    # Episode ended naturally (success/failure)
    pass

這使得時間限制檢測更加清晰和明確。


## Updating Your Training Code

### Basic Training Loop Migration

**Old v0.21 pattern**:
```python
for episode in range(num_episodes):
    obs = env.reset()
    done = False

    while not done:
        action = agent.get_action(obs)
        next_obs, reward, done, info = env.step(action)

        # Train agent (this may have bugs due to ambiguous 'done')
        agent.learn(obs, action, reward, next_obs, done)
        obs = next_obs

新版 v0.26+ 模式:

for episode in range(num_episodes):
    obs, info = env.reset(seed=episode)  # Optional: unique seed per episode
    terminated, truncated = False, False

    while not (terminated or truncated):
        action = agent.get_action(obs)
        next_obs, reward, terminated, truncated, info = env.step(action)

        # Train agent with proper termination handling
        agent.learn(obs, action, reward, next_obs, terminated)
        obs = next_obs

Q-Learning 更新遷移

舊版 v0.21(可能不正確):

def update_q_value(obs, action, reward, next_obs, done):
    if done:
        target = reward  # Assumes all episode endings are natural terminations
    else:
        target = reward + gamma * max(q_table[next_obs])

    q_table[obs][action] += lr * (target - q_table[obs][action])

新版 v0.26+(正確):

def update_q_value(obs, action, reward, next_obs, terminated):
    if terminated:
        # Natural termination - no future value
        target = reward
    else:
        # Episode continues - truncation has no impact on the possible future value
        target = reward + gamma * max(q_table[next_obs])

    q_table[obs][action] += lr * (target - q_table[obs][action])

深度強化學習框架遷移

大多數庫已更新,請查閱其文件以獲取更多資訊。

環境特定更改

已移除的環境

部分環境已被移動或移除

# OLD: Robotics environments in main gym
import gym
env = gym.make("FetchReach-v1")  # No longer available

# NEW: Moved to separate package
import gymnasium

import gymnasium_robotics
import ale_py

gymnasium.register_envs((gymnasium_robotics, ale_py))

env = gymnasium.make("FetchReach-v1")
env = gymnasium.make("ALE/Pong-v5")

相容性助手

使用舊版環境

如果您需要使用尚未更新到新 API 的環境

```python # 對於仍使用舊版 gym 的環境 env = gym.make(“GymV21Environment-v0”, env_id=”OldEnv-v0”)

# 此封裝器自動將舊版 API 轉換為新版 API

更多詳情,請參閱相容性指南 <gym_compatibility>_。

測試您的遷移

遷移後,請驗證以下幾點:

  • [ ] 匯入語句使用 gymnasium 而非 gym

  • [ ] 重置呼叫處理 (obs, info) 返回格式

  • [ ] 步進呼叫單獨處理 terminatedtruncated

  • [ ] 渲染模式在環境建立時指定

  • [ ] 隨機種子使用 reset() 中的 seed 引數

  • [ ] 訓練演算法正確區分終止型別

使用 from gymnasium.utils.env_checker import check_env 來驗證它們的實現。

獲取幫助

如果您在遷移過程中遇到問題:

  1. 查閱相容性指南:一些舊環境可以透過相容性封裝器使用

  2. 查閱環境文件:每個環境可能有特定的遷移說明

  3. 首先使用簡單環境進行測試:從 CartPole 開始,然後再轉移到複雜環境

  4. 比較舊版與新版行為:使用兩種 API 執行相同的程式碼以瞭解差異

常見資源: