【强化学习】 OpenAI Gym入门:基础组件(Getting Started With OpenAI Gym: The Basic Building Blocks)
本文说明
本文是对 OpenAI官方教程 中的“Getting Started With OpenAI Gym: The Basic Building Blocks”文章进行笔记精简总结,方便后续查询与复习。
虽然整体结构与官方文章一致,但内容并不一致,我按照我的思路进行了一定程度的修改。
学习本文需要对强化学习有一丢丢了解即可,主要是一些关键词。
这里也简单介绍和复习一下:
Environment
: 可以理解为一个游戏。Observation
:游戏运行过程中的某一个时刻的状态。例如某一帧游戏画面。Agent
:被操控的游戏角色。例如在赛车中你的赛车就是Agent。Action
:Agent可以做出的动作。分为离散和连续两种。例如:人物可以上下左右移动,这就是一个离散的动作,即从上下左右四种动作中选择一种Action。再比如,汽车的转向角度可以是0-90度的其中一个,甚至可以是小数,那么这就是一个连续的动作。reward
:玩游戏时得到的奖励。例如吃到金币则加分,死亡则扣分。该值是用于训练AI的重要指标。AI的目标就是最大化reward
OpenAI Gym简介
OpenAI Gym是强化学习(Reinforcement Learning, RL)的一个库,其可以帮你方便的验证你的强化学习算法的性能,其中提供了许多Enviorment。目前是学术界公认的benchmark。
本文内容
- 安装
- Environments
- Spaces
- Wrappers
- Vectorized Environments
安装
直接使用pip安装即可(官方github地址):
pip install -U gym
注意,仅支持Linux和MacOs, 官方不支持windows,但你可以找第三方的解决方案。 虽然官网这么说,但我测试下来发现windows可以直接安装。
本教程使用的是最新的 ‘0.25.1’ 版本
gym提供了许多Environment,所以你可能还需要安装具体的Environment,例如本教程需要使用classic_control,所以还需要执行:
pip install -U gym[classic_control]
Environments
Environment是Gym最核心的一个概念,一个Environment可以理解为一个游戏,例如:
这个让小车到达山顶就是一个简单的游戏。你可以通过一个如下代码来加载该Environment:
import gym
env = gym.make('MountainCar-v0')
其返回的是一个 Env
对象。OpenAI Gym提供了许多Environment可供选择:
例如,上图是OpenAI Gym提供的雅达利游戏机的一些小游戏。你可以到官方寻找适合你的Environment来验证你的强化学习算法。
前面的小车游戏你可以在该地址找到,进入官方页面后,里面是对该Environment的描述:
这其中最重要的就是表格中的内容,其主要包括两大部分:
- Action:Action就是Agent可以做出的动作,通常分为离散和连续两种。该表格中的
Discrete(3)
表示该Agent可以做3中不同的动作。 - Observation:游戏Observation的状态。例如:Observation Shape为(2, ) 就表示该Environment的Observation是一个2维向量,其最大值分别为[0.6, 0.07],最小值分别为[-1.2, -0.07]
你也可以通过env
对象的observation_space
和action_space
属性来查看上述内容:
print(env.observation_space)
print(env.action_space)
输出:
Box([-1.2 -0.07], [0.6 0.07], (2,), float32)
Discrete(3)
与Environment进行交互
与Environment进行交互换句话说就是打游戏。其主要通过调用env
对象的函数来完成,其包含两个重要函数:
reset
:重置环境,就是重置游戏。其会对环境进行状态初始化,并返回初始化后的observation。注意:虽然是重置,但也是初始化,也就是env即使是第一次使用也要调用reset
step
:采取行动。就是让Agent采取一个动作,例如向前移动。step
函数返回做完该动作后的信息,包括以下4个返回值:observation
:执行该动作后的游戏状态reward
:执行该动作后得到的reward。done
:游戏是否终止。例如命都用完了,则游戏终止,done=True
info
:一些额外的信息,例如还剩几条命等。不同的游戏info不同
代码演示:
# 重置环境,虽说是重置,第一次使用env前,也要调用
# reset会返回初始的observation
observation = env.reset()
print("The initial observation is {}".format(observation))
# 从动作中随机选择一个,random_actio
random_action = env.action_space.sample()
print("The random action is {}".format(random_action))
# 调用step,执行上述的动作,得到下一个状态
new_obs, reward, done, info = env.step(random_action)
print("The new observation is {}".format(new_obs))
print("The reward is {}".format(reward))
输出:
The initial observation is [-0.5330634 0. ]
The random action is 0
The new observation is [-0.41475227 -0.0018148 ]
The reward is -1.0
看这种干巴巴的数字没意思,可以通过render
方法渲染成图片:
import matplotlib.pyplot as plt
env_screen = env.render(mode = 'rgb_array')
plt.imshow(env_screen)
我们来看一个更完整的例子:
import time
# 初始化环境
obs = env.reset()
# 让Agent进行1500次动作
for step in range(1500):
# 选择一个随机的动作,这里可以替换成你训练好的智能算法
action = env.action_space.sample()
# 采取行动,然后得到下个状态
obs, reward, done, info = env.step(action)
# 如果游戏结束,则跳出循环
if done:
break
# 关闭env
env.close()
你可以依据你的具体环境(Jupyter, Py等)来在上面的代码中使用env.render
来增加实时动画,例如如果使用Google Colab,则你可以使用以下代码来显示动画:
!apt install xvfb
!pip install pyvirtualdisplay
%%capture
from pyvirtualdisplay import Display
virtual_display = Display(visible=0, size=(1400, 900))
virtual_display.start()
%matplotlib inline
import matplotlib.pyplot as plt
from IPython import display
import time
import gym
env = gym.make('MountainCar-v0')
# 初始化环境
obs = env.reset()
img = plt.imshow(env.render(mode='rgb_array'))
# 让Agent进行1500次动作
for step in range(1500):
# 选择一个随机的动作,这里可以替换成你训练好的智能算法
action = env.action_space.sample()
# 采取行动,然后得到下个状态
obs, reward, done, info = env.step(action)
img.set_data(env.render(mode='rgb_array'))
display.display(plt.gcf())
display.clear_output(wait=True)
# 如果游戏结束,则跳出循环
if done:
break
# 关闭env
env.close()
Spaces
上一节我们提到每个Environment的文档中都会有一个表格:
这个表格就是Space,它里面记录了这个环境的Observation和Action的合法值。例如Action Space是3个离散值,通常为0,1,2
,如果此时你使用env.step(3)
,那就会报错,因为3不是一个合法的Action。
我们可以通过env.observation_space
获取到observation的space,其返回一个Box的对象,里面记录了Observation的Shape、High(最大值)、Low(最小值)等信息。这些我们上一节都讲过了。这节就不再赘述了
Wrapper
有时候官方提供的observation和reward等不满足你的需求,那么你可以使用包装类来自定义你的需求。
这里直接上例子。假设我们现在要训练AI玩打砖块游戏:
官方提供对该游戏的observation的Shape为(210, 160, 3),也就是一帧图片:
env = gym.make("BreakoutNoFrameskip-v4")
print("Observation Space: ", env.observation_space)
print("Action Space ", env.action_space)
输出:
Observation Space: Box(210, 160, 3)
Action Space Discrete(4)
但为了训练处更好的AI,用一帧图片来决定木板应该如何移动不太够,最好可以有前几帧的画面,所以我们希望Observation的Shape为(4, 210, 160, 3),其中4代表前4帧的图片。使用包装类,我们可以这么做:
from collections import deque
from gym import spaces
import numpy as np
class ConcatObs(gym.Wrapper):
def __init__(self, env, k):
gym.Wrapper.__init__(self, env)
self.k = k
self.frames = deque([], maxlen=k)
shp = env.observation_space.shape
self.observation_space = \
spaces.Box(low=0, high=255, shape=((k,) + shp), dtype=env.observation_space.dtype)
def reset(self):
ob = self.env.reset()
for _ in range(self.k):
self.frames.append(ob)
return self._get_ob()
def step(self, action):
ob, reward, done, info = self.env.step(action)
self.frames.append(ob)
return self._get_ob(), reward, done, info
def _get_ob(self):
return np.array(self.frames)
env = gym.make("BreakoutNoFrameskip-v4")
wrapped_env = ConcatObs(env, 4)
print("The new observation space is", wrapped_env.observation_space)
输出:
The new observation space is Box(4, 210, 160, 3)
OpenAI Gym对Observation、Reward和Action也都提供了Wrapper类:
import random
class ObservationWrapper(gym.ObservationWrapper):
def __init__(self, env):
super().__init__(env)
def observation(self, obs):
# Normalise observation by 255
return obs / 255.0
class RewardWrapper(gym.RewardWrapper):
def __init__(self, env):
super().__init__(env)
def reward(self, reward):
# Clip reward between 0 to 1
return np.clip(reward, 0, 1)
class ActionWrapper(gym.ActionWrapper):
def __init__(self, env):
super().__init__(env)
def action(self, action):
if action == 3:
return random.choice([0,1,2])
else:
return action
env = gym.make("BreakoutNoFrameskip-v4")
wrapped_env = ObservationWrapper(RewardWrapper(ActionWrapper(env)))
obs = wrapped_env.reset()
for step in range(500):
action = wrapped_env.action_space.sample()
obs, reward, done, info = wrapped_env.step(action)
# Raise a flag if values have not been vectorised properly
if (obs > 1.0).any() or (obs < 0.0).any():
print("Max and min value of observations out of range")
# Raise a flag if reward has not been clipped.
if reward < 0.0 or reward > 1.0:
assert False, "Reward out of bounds"
# Check the rendering if the slider moves to the left.
wrapped_env.render()
time.sleep(0.001)
wrapped_env.close()
print("All checks passed")
Vectorized Environments
该模块是关于强化学习并行计算的,个人认为是非入门部分,暂不学习。如果感兴趣,可以去官网看。
相关文章
- 【LeetCode】按公因数计算最大组件大小 [H](并查集)
- 云小课 | MRS基础入门之HDFS组件介绍
- android基础组件---->Checkboxe的使用
- Watson Explorer 基础组件概述
- 如何写出高质量的代码 data 组件 函数 注释 命名 变量的次数
- Twaver-HTML5基础学习(41)列表可视化视图组件(List)
- Twaver-HTML5基础学习(39)鹰眼可视化视图组件(OverView)
- 美团React Native基础组件库beeshell详解
- 基础组件-统一服务日志切面
- 深度长文回顾web基础组件 (二)
- 深度长文回顾web基础组件 (三)
- vue 组件数据传递
- react基础语法(三)组件的创建和复合组件
- JS组件系列——表格组件神器:bootstrap table(二:父子表和行列调序)
- PyQt学习随笔:重写组件的event方法捕获组件的事件
- edtFTPnet/PRO组件集,文件传输的控件
- component object model(组件对象模型)
- 【Vue 开发实战】基础篇 # 8:如何触发组件的更新
- 【Vue 开发实战】基础篇 # 4:Vue组件的核心概念:插槽
- 湖仓一体电商项目(三):从头搭建12个大数据项目基础组件
- 从0到1开发一个React组件库
- React Native常用组件样式总结