强化学习环境接入
概述
强化学习领域中,智能体与环境交互过程中,学习策略来使得数值化的收益信号最大化。“环境”作为待解决的问题,是强化学习领域中重要的要素。
目前强化学习使用的环境种类繁多:Mujoco、MPE、Atari、PySC2、SMAC、TORCS、Isaac等,目前MindSpore Reinforcement接入了Gym、SMAC两个环境,后续随着算法的丰富,还会逐渐接入更多的环境。本文将介绍如何在MindSpore Reinforcement下接入第三方环境。
将环境Python函数封装为算子
在此之前,先介绍一下静态图和动态图模式。
动态图模式下,程序按照代码的编写顺序逐行执行,编译器将神经网络中的各个算子逐一下发到设备进行计算操作,方便用户编写和调试神经网络模型。
静态图模式下,程序在编译执行时,会将开发者定义的算法编译成一张计算图。在这个过程中,编译器可以通过使用图优化技术来降低资源开销,获得更好的执行性能。
由于静态图模式支持的语法是Python语言的子集,而常用的环境一般使用Python接口实现交互,二者之间的语法差异往往会造成图编译错误。对于这个问题,开发者可以使用PyFunc
算子将Python函数封装为一个MindSpore计算图中的算子。
接下来以gym为例,将env.reset()
封装为一个MindSpore计算图中的算子:
下面的代码中创建了一个CartPole-v0
的环境,执行env.reset()
方法,可以看到state
的类型是numpy.ndarray
,数据类型和维度分别是np.float64
和(4,)
。
import gym
env = gym.make('CartPole-v0')
state = env.reset()
print('type: {}, shape: {}, dtype: {}'.format(type(state), state.dtype, state.shape))
# Result:
# type: <class 'numpy.ndarray'>, shape: (4,), dtype: float64
接下来,使用PyFunc
算子将env.reset()
封装为一个MindSpore算子:
fn
指定需要封装的Python函数名,既可以是普通的函数,也可以是成员函数。in_types
和in_shapes
指定输入的数据类型和维度。env.reset
没有入参,因此填写空的列表。out_types
,out_shapes
指定返回值的数据类型和维度。从之前的执行结果可以看到,env.reset()
返回值是一个numpy数组,数据类型和维度分别是np.float64
和(4,)
,因此填写[ms.float64,]
和[(4,),]
。PyFunc
返回值是个tuple(Tensor)。更加详细的使用说明参考。
环境和算法解耦
强化学习算法通常应该具备良好的泛化性,例如解决HalfCheetah
的算法也应该能够解决Pendulum
。为了贯彻泛化性的要求,有必要将环境和算法其余部分进行解耦,从而确保在更换环境后,脚本中的其余部分尽量少的修改。建议开发者参考Environment
对环境进行封装。
class Environment(nn.Cell):
def __init__(self):
super(Environment, self).__init__(auto_prefix=False)
def reset(self):
pass
def step(self, action):
pass
@property
def action_space(self) -> Space:
pass
@property
def observation_space(self) -> Space:
pass
@property
def reward_space(self) -> Space:
pass
@property
def done_space(self) -> Space:
pass
Environment
除了提供reset
和step
等与环境交互的接口之外,还需要提供action_space
、observation_space
等方法,这些接口返回Space类型。算法可以根据Space
信息:
获取环境的状态空间和动作空间的维度,用于构建神经网络。
读取合法的动作范围,对策略网络给出的动作进行缩放和裁剪。
识别环境的动作空间是离散的还是连续的,选择采用连续分布还是离散分布对环境探索。