当前位置: 首页 > news >正文

TensorFlow深度学习实战(31)——强化学习仿真库Gymnasium

TensorFlow深度学习实战(31)——强化学习仿真库Gymnasium

    • 0. 前言
    • 1. 强化学习仿真环境
    • 2. Gymnasium
      • 2.1 Gymnasium 简介
      • 2.2 Gymnasium 环境
      • 2.3 Gymnasium 接口
    • 3. 构建随机智能体进行 Breakout 游戏
    • 4. Gymnasium 中的包装器
    • 系列链接

0. 前言

Gymnasium 是一个用于开发和测试强化学习 (Reinforcement Learning, RL) 算法的开源工具包,旨在提供一个标准化的平台,让研究人员和开发者可以在各种不同的环境中训练和评估强化学习算法。主要用于提供易于使用的接口、丰富的环境,并使得强化学习的研究和开发更加高效。

1. 强化学习仿真环境

试错是强化学习 (Reinforcement Learning, RL) 算法中的重要组成部分,因此,首先需要在仿真环境中训练 RL 智能体,然后才能在实际环境中进行部署。常用的仿真环境包括:

  • Gymnasium:包含了用来训练 RL 智能体的环境集合
  • Unity ML-Agents SDK:允许开发者将使用 Unity 编辑器创建的游戏和仿真转换为可以用深度强化学习、进化策略或其他机器学习方法训练智能代理的环境。与 TensorFlow 兼容,并提供了训练 2D/3DVR/AR 游戏智能体的能力
  • Gazebo:可以在 Gazebo 中创建基于物理模拟的三维世界。gym-gazebo 工具包结合了 Gazebo、机器人操作系统 (Robot Operating System, ROS) 和 Gymnasium 接口,用于训练 RL 智能体
  • Blender 学习环境:Blender 游戏引擎的 Python 接口,也与 Gymnasium 兼容。Blender 是一个免费的 3D 建模软件,含有集成的游戏引擎,提供了一套易于使用且功能强大的工具用于创建游戏。可以通过 Blender 游戏引擎创建自定义虚拟环境,用于训练 RL 智能体以解决特定问题
  • Malmo:由微软团队构建,Malmo 是一个建立在 Minecraft 之上的 AI 实验和研究平台,提供了一个简单的 API 来创建任务

2. Gymnasium

2.1 Gymnasium 简介

Gymnasium 是一个用于强化学习 (Reinforcement Learning, RL) 的开源库,它继承并扩展了 OpenAIGym 库,提供了标准化的 API 和多种 RL 环境,用于开发和比较 RL 算法。它包含了各种模拟环境,可以用于训练智能体和开发新的 RL 算法。现在,GymnasiumFarama Foundation 维护,Gymnasium 针对各种 RL 任务提供了统一的接口和广泛的环境支持。Gymnasium 保持了与 OpenAI Gym 的兼容性,可以将代码轻松地从 Gym 迁移到 Gymnasium
Gymnasium 库的安装和其它第三方库相同,通过在命令行中执行 pip 命令:

$ pip install gymnasium

如果想安装所有(免费的) Gymnasium 模块,可以在其后添加 [all]

$ pip install gymnasium[all]

对于基于 Atari 的游戏,需要安装 Atari 依赖项 (Box2DROM):

$ pip install box2d-py

2.2 Gymnasium 环境

Gymnasium 提供了多种环境,从简单的基于文本的环境到三维游戏,可以分为以下几类:

  • 算法:包含相关执行计算(如加法)的环境
  • Atari:提供各种经典的 Atari 游戏环境
  • Box2D:包含二维的机器人任务,如赛车竞速或双足机器人
  • 经典控制:包含经典控制问题,如平衡杆问题
  • MuJoCo:一个授权环境(可以获得一个月的免费试用),支持各种机器人仿真任务,该环境包含物理引擎,因此可以用于训练机器人任务
  • 机器人:使用 MuJoCo 的物理引擎,模拟基于目标的任务
  • 简单文本:简单的基于文本的环境

可以使用以下代码查看安装的所有可用环境:

from gymnasium import envs
envall = envs.registry.keys()
print(len(envall))

通过 make 函数可以创建环境,每个环境都有一个唯一的 ID、动作空间、动作空间和默认的奖励范围。遍历 envall 列表中的所有环境,并记录其唯一 ID,该 ID 用于通过 make 方法创建环境,以及其状态空间、奖励范围和动作空间:

from tqdm import tqdm
import pandas as pd
List = []
for e in tqdm(envall):try:env = gym.make(e)List.append([e.id, env.observation_space, env.action_space, env.reward_range])env.close()except:continue
df = pd.DataFrame(List, columns= ['Environment', 'Observation Space', 'Action Space', 'Reward'])
df.sample(20)

可以通过以下方式获取 Gymnasium 中任意环境的详细信息,例如,打印 MountainCar 环境的详细信息:

env = gym.make('MountainCar-v0')
print(f"The Observation space is {env.observation_space}" )
print(f"Upper Bound for Env Observation {env.observation_space.high}")
print(f"Lower Bound for Env Observation {env.observation_space.low}")
print(f"Action Space {env.action_space}")obs = env.reset()
print(f"The initial observation is {obs}")
# Take a random actionget the new observation space
obs, reward, done, truncated, info = env.step(env.action_space.sample())
print(f"The new observation is {obs}")
env.close()

2.3 Gymnasium 接口

Gymnasium 的核心是统一的环境接口。智能体可以通过三个基本方法与环境进行交互,即 reset()step()render()reset() 方法重置环境并返回初始环境状态,step() 方法执行给定动作,并返回新的环境状态new_obs、奖励 reward、回合完成标志 done、回合(超时或人为限制)截断标志 truncated 和信息 inforender() 方法用于渲染环境帧。接下来,查看一些不同的环境并观察它们的初始环境状态:

# Physics Engine
e = 'LunarLander-v2'
env = gym.make(e, render_mode='rgb_array')
obs = env.reset()
img = env.render()
env.close()
plt.imshow(img)
plt.show()# Classic Control
e = 'CartPole-v0'
env = gym.make(e, render_mode='rgb_array')
obs = env.reset()
img = env.render()
env.close()
plt.imshow(img)
plt.show()# Atari
e = 'ALE/SpaceInvaders-v5'
env = gym.make(e, render_mode='rgb_array')
obs = env.reset()
img = env.render()
env.close()
plt.imshow(img)
plt.show()

环境绘制

除了使用 Matplotlib 显示环境外,也可以直接使用 render() 方法:

env = gym.make('ALE/Breakout-v5', render_mode='human')
obs, info = env.reset()
done = False
while not done:action = env.action_space.sample()  obs, reward, done, truncated, info = env.step(action)env.render()

在下图中可以看到 Breakout 环境,render() 函数会弹出环境图像窗口:

环境可视化

可以使用 env.observation_spaceenv.action_space 来了解关于 Breakout 游戏的状态空间和动作空间的信息。可以看到,状态由一个大小为 210 × 160 的三通道图像组成,动作空间是离散的,有四个可能的动作,完成所有动作后,使用 close() 方法关闭环境:

env.close()

3. 构建随机智能体进行 Breakout 游戏

接下来,我们进行 Breakout 游戏。当我们第一次玩这个游戏时,通常不知道规则或如何操作,所以会随机选择控制按钮,而对于智能体同样如此,在刚开始训练时,它会从动作空间中随机选择动作。Gymnasium 提供了 sample() 函数用于从动作空间中随机选择一个动作。此外,我们还可以保存游戏回放,以便用于后续查看,有两种保存游戏回放的方法,一种是使用 Matplotlib,另一种是使用 Gymnasium Monitor 包装器。在本小节中,使用 Matplotlib 方法保存游戏回放。

(1) 首先导入所需模块,本节只需要 gymnasiummatplotlib,因为智能体采用随机动作:

import gymnasium as gym
import matplotlib.pyplot as plt
import matplotlib.animation as animation

(2) 创建 Gymnasium 环境:

env_name = 'ALE/Breakout-v5'
env = gym.make(env_name, render_mode='rgb_array')

(3) 接下来,运行游戏,每个时间步选择随机动作,最多运行 300 步,或直到游戏结束。在每一步中,都将环境状态保存在列表 frames 中:

env.reset()
done = False
for _ in range(300): #print(done)frames.append(env.render())obs, reward, done, truncated, info = env.step(env.action_space.sample())if done:break

(4) 使用 Matplotlib Animation 将所有帧合成为一个 GIF 图像。首先创建一个图像对象 patch,然后定义函数 animate(),将图像数据设置为特定的帧索引,Matplotlib Animation 类使用该函数创建动画,最后将其保存为文件 random_agent.gif

patch = plt.imshow(frames[0])
plt.axis('off')
plt.tick_params(axis='both', left='off', top='off', right='off', bottom='off', labelleft='off', labeltop='off', labelright='off', labelbottom='off')
def animate(i):patch.set_data(frames[i])
anim = animation.FuncAnimation(plt.gcf(), animate, \frames=len(frames), interval=10)
anim.save('./images/drone_random.gif', writer='pillow')  ##Comment on colab

生成 GIF 图像结果如下:

随机动作

介绍了 Gymnasium 后,我们将研究包装器,用于来创建自定义环境。

4. Gymnasium 中的包装器

Gymnasium 提供了多种包装器 (Wrapper),用于修改现有环境。例如,如果神经网络的输入是图像,RGB 强度值在 0255 之间,而神经网络的最佳输入范围是 [0, 1],这种情况下就可以使用 Gymnasium 包装器类对状态进行预处理。

接下来,定义一个将状态串联起来的包装器:

from collections import deque
import gymnasium as gym
from gymnasium import spaces
import numpy as npclass ConcatObservations(gym.Wrapper):def __init__(self, env, n):gym.Wrapper.__init__(self, env)shape = env.observation_space.shapeself.n = nself.frames = deque([], maxlen=n)self.observation_space = \spaces.Box(low=0, high=255, shape=((n,) + shape), dtype=env.observation_space.dtype)def reset(self):obs = self.env.reset()for _ in range(self.n):self.frames.append(obs)return self._get_obs()def step(self, action):obs, reward, done, truncated, info = self.env.step(action)self.frames.append(obs)return self._get_obs(), reward, done, infodef _get_obs(self):return np.array(self.frames)

可以看到,需要更改默认的 reset() 函数、step() 函数和 _get_obs() 函数,还需要修改默认的返回状态:

env = gym.make("BreakoutNoFrameskip-v4")
print(f"The original observation space is {env.observation_space}")
# The original observation space is Box(0, 255, (210, 160, 3), uint8)

如果使用 BreakoutNoFrameskip-v4 环境,那么原始的状态尺寸为 210 x 160 x 3

env = ConcatObservations(env, 4)
print(f"The new observation space is {env.observation_space}")
# The new observation space is Box(0, 255, (4, 210, 160, 3), uint8)

而如果使用了刚刚创建的包装器,会发现状态增加了一个维度,其包含四个帧,每个帧的大小是 210 x 160 x 3

也可以使用包装器来修改奖励。在这种情况下,可以使用超类 RewardWrapper,在以下代码中,将奖励限制在 [-10, 10] 范围内:

class ClippedRewards(gym.RewardWrapper):def __init__(self, env):gym.RewardWrapper.__init__(self, env)self.reward_range = (-10,10)def reward(self, reward):"""Clip to {+10, 0, -10} by its sign."""return reward if reward >= -10 and reward <= 10 else 10 * np.sign(reward)

CartPole 环境中使用 ClippedRewards,该环境的奖励范围是 [−∞, ∞]

env = gym.make("CartPole-v0")
print("Original Rewards:", env.reward_range)
env.close()
env = ClippedRewards(gym.make("CartPole-v0"))
print(f'Clipped reward range: {env.reward_range}')
env.close()
# Clipped reward range: (-10, 10)

包装器的另一个有用应用是在智能体学习时保存状态。通常,一个 RL 智能体需要大量的步骤来进行适当的训练,因此在每一步存储状态并不实际,我们可以选择在每隔指定步(例如 50500 步)后进行存储。Gymnasium 提供了 Wrapper Monitor 类来将游戏保存为视频。首先导入包装器,然后创建环境,最后使用 Monitor
默认情况下,会存储 182764 等步数时的视频,然后是每 1,000 步的视频;每次训练,默认情况下,视频保存在同一个文件夹中:

import gymnasium as gym
env = gym.make("ALE/Breakout-v5", render_mode='rgb_array')
env = gym.wrappers.RecordVideo(env, 'recording', episode_trigger=lambda x: True)
observation = env.reset()
for _ in range(1000):#env.render()action = env.action_space.sample() # your agent here (this takes random actions)observation, reward, done, truncated, info = env.step(action)if done:observation = env.reset()
env.close()

为了使 Monitor 正常工作,需要 FFmpeg 工具支持。视频结果将以 .mp4 格式保存在录制文件夹中。需要注意的是,如果想在下一个训练会话中使用相同的文件夹,必须设置 force=True 选项。

视频保存结果

系列链接

TensorFlow深度学习实战(1)——神经网络与模型训练过程详解
TensorFlow深度学习实战(2)——使用TensorFlow构建神经网络
TensorFlow深度学习实战(3)——深度学习中常用激活函数详解
TensorFlow深度学习实战(4)——正则化技术详解
TensorFlow深度学习实战(5)——神经网络性能优化技术详解
TensorFlow深度学习实战(6)——回归分析详解
TensorFlow深度学习实战(7)——分类任务详解
TensorFlow深度学习实战(8)——卷积神经网络
TensorFlow深度学习实战(9)——构建VGG模型实现图像分类
TensorFlow深度学习实战(10)——迁移学习详解
TensorFlow深度学习实战(11)——风格迁移详解
TensorFlow深度学习实战(12)——词嵌入技术详解
TensorFlow深度学习实战(13)——神经嵌入详解
TensorFlow深度学习实战(14)——循环神经网络详解
TensorFlow深度学习实战(15)——编码器-解码器架构
TensorFlow深度学习实战(16)——注意力机制详解
TensorFlow深度学习实战(17)——主成分分析详解
TensorFlow深度学习实战(18)——K-means 聚类详解
TensorFlow深度学习实战(19)——受限玻尔兹曼机
TensorFlow深度学习实战(20)——自组织映射详解
TensorFlow深度学习实战(21)——Transformer架构详解与实现
TensorFlow深度学习实战(22)——从零开始实现Transformer机器翻译
TensorFlow深度学习实战(23)——自编码器详解与实现
TensorFlow深度学习实战(24)——卷积自编码器详解与实现
TensorFlow深度学习实战(25)——变分自编码器详解与实现
TensorFlow深度学习实战(26)——生成对抗网络详解与实现
TensorFlow深度学习实战(27)——CycleGAN详解与实现
TensorFlow深度学习实战(28)——扩散模型(Diffusion Model)
TensorFlow深度学习实战(29)——自监督学习(Self-Supervised Learning)
TensorFlow深度学习实战(30)——强化学习(Reinforcement learning,RL)

http://www.lryc.cn/news/619401.html

相关文章:

  • 【IntelliJ IDEA】如何在pom.xml中去除maven中未使用的依赖
  • 七大排序算法全解析:从入门到精通
  • 各种排序算法(一)
  • Java开发环境搭建(WIN+IDEA+Maven)
  • STM32的UART奇偶校验注意
  • C# xml UI格式化字符串
  • IDEA创建一个VUE项目
  • 基于人工智能和物联网融合跌倒监控系统(LW+源码+讲解+部署)
  • CW32L011电机开发板控制教程
  • 分布式与微服务宝典
  • js:13KB或者xxxkb、xxxMB\xxxtb\xxb等多种情况怎么获取后面的单位
  • FluxSelectMultiple 技术设计文档
  • 飞算JavaAI的中间件风暴:Redis + Kafka 全链路实战
  • docker network 与host的区别
  • 数据科学与爬虫技术学习笔记
  • 玩转Docker | 使用Docker部署WordPress网站服务
  • 【车联网kafka】Kafka核心架构与实战经验(第四篇)
  • 猿大师中间件:Chrome网页内嵌PhotoShop微信桌面应用程序
  • Jetson NX Python环境搭建:使用APT轻松安装NumPy, scikit-learn, OpenCV
  • java学习 leetcode 二分查找 图论
  • 图论理论部分
  • 【C++ STL】list详解和模拟
  • Day52--图论--101. 孤岛的总面积(卡码网),102. 沉没孤岛(卡码网),103. 水流问题(卡码网),104. 建造最大岛屿(卡码网)
  • day50 图论基础 卡码网98. 所有可达路径
  • 15-docker的企业级私有仓库之docker-harbor
  • 若依plus SpringCloud [DUBBO] 多模块异常抛出 异常里面包了一层异常
  • docker load镜像后 名字和标签异常解决
  • 【Docker项目实战】使用Docker部署todo任务管理器
  • 飞算JavaAI云原生实践:基于Docker与K8s的自动化部署架构解析
  • python环境依赖冲突问题(1)