python笔记 gym Wrapper
Posted UQI-LIUWJ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python笔记 gym Wrapper相关的知识,希望对你有一定的参考价值。
1 介绍
Wrapper是一种无需直接更改底层代码即可修改现有环境的便捷方式。
为了包装一个环境,必须首先初始化一个基础环境。 然后您可以将此环境与(可选的)参数一起传递给Wrapper的构造函数:
举例:
import gym
from gym.wrappers import RescaleAction
base_env = gym.make("BipedalWalker-v3")
base_env.action_space
#Box([-1. -1. -1. -1.], [1. 1. 1. 1.], (4,), float32)
#没包装之前的动作空间
wrapped_env = RescaleAction(base_env, min_action=0, max_action=1)
wrapped_env.action_space
#Box([0. 0. 0. 0.], [1. 1. 1. 1.], (4,), float32)
#经过Wrapper,也就是被包装之后的动作空间,可以发现我们用一行就修改了环境的动作空间
2 一个Wrapper可以做的事
包装器做三件常见的事情:
- 转换动作
- 转换观测
- 转换reward
通过从 ActionWrapper、ObservationWrapper 或 RewardWrapper 继承并实现相应的转换,可以轻松实现此类包装器。 如果需要一个包装器来完成更复杂的任务,你可以直接从 Wrapper 类继承。
3 ActionWrapper
如果想在将函数传递给基础环境之前将函数应用于“动作”,则可以简单地从 ActionWrapper 继承并覆盖方法“action”以实现该转换。
该方法中定义的转换必须采用基础环境的操作空间中的值。 但是,它的域可能与原始动作空间不同。 在这种情况下,您需要通过在包装器的 __init__ 方法中设置 self._action_space 来指定包装器的新操作空间。
假设您有一个动作空间类型为 Box 的环境,但您只想使用有限的动作子集。 然后,您可能想要实现以下包装器
env = gym.make("LunarLanderContinuous-v2")
env.action_space
#Box([-1. -1.], [1. 1.], (2,), float32)
from gym.spaces import Discrete
class DiscreteActions(gym.ActionWrapper):
def __init__(self, env, disc_to_cont):
super().__init__(env)
self.disc_to_cont = disc_to_cont
self._action_space = Discrete(len(disc_to_cont))
def action(self, act):
return self.disc_to_cont[act]
wrapped_env = DiscreteActions(env, [np.array([1,0]),
np.array([-1,0]),
np.array([0,1]),
np.array([0,-1])])
print(wrapped_env.action_space)
#Discrete(4)
4 ObservationWrapper
如果想在将基本环境返回的“观察”传递给代码之前将某个function应用于“观察”,可以简单地从 ObservationWrapper 继承并覆盖“observation”方法来实现该转换。
该方法中定义的转换必须在基础环境的观察空间上定义。 但是,它可能会在不同的空间中取值。 在这种情况下,您需要通过在包装器的 __init__ 方法中设置 self._observation_space 来指定包装器的新观察空间。
例如,您可能有一个 2D 导航任务,其中环境返回字典作为带有键“agent_position”和“target_position”的观察值。 一个常见的做法可能是放弃一些自由度,只考虑目标相对于agent的位置,即observation[“target_position”] - observation[“agent_position”]。
为此,可以像这样实现观察包装器:
class RelativePosition(gym.ObservationWrapper):
def __init__(self, env):
super().__init__(env)
self._observation_space = Box(shape=(2,), low=-np.inf, high=np.inf)
def observation(self, obs):
return obs["target"] - obs["agent"]
4.1 举例
未包装之前——每个observation是一个离散的数
env =gym.make("FrozenLake-v1")
env.reset()
for t in range(5):
a_t = env.action_space.sample()
s_t, r_t, done, info = env.step(a_t)
print(s_t)
'''
1
0
4
5
5
'''
包装之后——每个observation是一个one-hot编码
class DiscreteToBoxWrapper(gym.ObservationWrapper):
def __init__(self, env):
super().__init__(env)
assert isinstance(env.observation_space, gym.spaces.Discrete), \\
"Should only be used to wrap Discrete envs."
self.n = self.observation_space.n
self.observation_space = gym.spaces.Box(0, 1, (self.n,))
def observation(self, obs):
new_obs = np.zeros(self.n)
new_obs[obs] = 1
return new_obs
env_1 = DiscreteToBoxWrapper(gym.make("FrozenLake-v1"))
env_1.reset()
for t in range(10):
a_t = env_1.action_space.sample()
s_t, r_t, done, info = env_1.step(a_t)
print(s_t)
'''
[1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
'''
5 RewardWrapper
如果想在将基本环境返回的“reward”传递给代码之前将某个function应用于“reward”,可以简单地从 RewardWrapper 继承并覆盖“reward”方法来实现该转换。
这种转变可能会改变奖励范围; 要指定包装器的奖励范围,可以简单地在 __init__ 中定义 self._reward_range。
比如:,我们希望将奖励限制在一个范围内以获得一些数值稳定性。 为此,我们可以实现以下包装器:
class ClipReward(gym.RewardWrapper):
def __init__(self, env, min_reward, max_reward):
super().__init__(env)
self.min_reward = min_reward
self.max_reward = max_reward
self._reward_range = (min_reward, max_reward)
def reward(self, reward):
return np.clip(reward, self.min_reward, self.max_reward)
6 还原未包装的情况
6.1 .env
访问未经过最近一次包装器下的环境:
wrapped_env.action_space,wrapped_env.env.action_space
'''
(Box([0. 0. 0. 0.], [1. 1. 1. 1.], (4,), float32),
Box([-1. -1. -1. -1.], [1. 1. 1. 1.], (4,), float32))
'''
6.2 .unwrapped
访问未经过所有一次包装器下的环境:
wrapped_env.action_space,wrapped_env.unwrapped.action_space
'''
(Box([0. 0. 0. 0.], [1. 1. 1. 1.], (4,), float32),
Box([-1. -1. -1. -1.], [1. 1. 1. 1.], (4,), float32))
'''
参考内容
Gym Wrappers | alexandervandekleut.github.io
以上是关于python笔记 gym Wrapper的主要内容,如果未能解决你的问题,请参考以下文章
Gym wrapper videorecorder 在 Hopper-v2 环境中无法正常工作。给出分段错误