强化学习实践(三)基于gym搭建自己的环境

目录

前言

1.搭建环境

前言

1.1构建自己的环境文件

1.2 __init __

1.3 seed

1.4 step

1.5 reset

1.6 render

1.7 close

2.调用环境

2.1 注册

2.2 放入库中

2.3 测试

参考文献


前言

      为了减少训练成本,必须搭建合适的训练环境(仿真环境),在训练环境中测试算法,再将训练好的模型移植到真实的训练平台中。


      Openai的gym或者universe是当前最为流行的两个可以搭建训练环境的平台。支持Tensorflow和Pytorch等主流深度学习框架,但目前仅支持python语言。

      补充:可以直接用指令:pip show gym 找到安装目录,我的是 D:\anaconda3\lib\site-packages 

1.搭建环境

前言

自我搭建的环境可以视为一个类。主要包含:变量、函数。

变量:必须含有动作和状态,如self.states 状态空间,self.actions 动作空间,self.t 状态转移,self.rewards 回报,self.terminate_states 终止状态等。

函数包含:__init __ seed,step, reset, render, close。
 

1.1构建自己的环境文件

      以官方的MountainCarEnv为例。

      新建文件命名为grid_mdp.py,路径放在D:\anaconda3\lib\site-packages\gym\envs\classic_control中。

1.2 __init __

初始化一些参数,此处定义car的位置、大小、重量,推力大小,动作空间,观测空间。

    def __init__(self, goal_velocity=0):
        self.min_position = -1.2
        self.max_position = 0.6
        self.max_speed = 0.07
        self.goal_position = 0.5
        self.goal_velocity = goal_velocity

        self.force = 0.001
        self.gravity = 0.0025

        self.low = np.array([self.min_position, -self.max_speed], dtype=np.float32)
        self.high = np.array([self.max_position, self.max_speed], dtype=np.float32)

        self.viewer = None

        self.action_space = spaces.Discrete(3) # 动作空间,此处有三个动作空间,向左,不动,向右。
        self.observation_space = spaces.Box(self.low, self.high, dtype=np.float32) # 观测空间,环境中所能观测到的范围

        self.seed()

1.3 seed

      可以不设,但必须有这个模块。

随机种子:用于生成随机数的起始值或种子值,可以控制随机过程的可重复性。随机过程通常涉及到随机数的生成,例如在数据的划分、模型的初始化、参数的随机初始化等情况下。设置随机种子可以确保每次运行时使用相同的种子值,从而获得相同的随机数序列,使得实验或模型训练的结果可以重现。

好处

      结果可重现性:通过设置相同的随机种子,可以确保每次运行时获得相同的随机数序列,使实验结果可重现,方便调试和比较不同模型或算法的性能。

      模型比较:在比较不同模型或算法的性能时,使用相同的随机种子可以确保每个模型或算法在相同的随机条件下进行比较,消除了随机性对结果的影响。

      调试和开发:在调试和开发阶段,使用固定的随机种子可以使得结果可重现,方便定位问题和调整模型参数。

设置随机种子的方式可以归为以下三类

      设置为固定的整数值:如 random_state = 0。
      使用当前时间作为种子值:如 random_state = None 或 random_state = int(time.time())。
      使用其他可确定的值:如数据集的标识符或任务的编号。
 

    def seed(self, seed=None):
        self.np_random, seed = seeding.np_random(seed)
        return [seed]

1.4 step

      在训练环境中充当物理引擎,基于agent的运动学模型或动力学模型计算执行完当前输入动作(action)后,得到下一步的状态(state)和即时回报(reward),同时判断是否达到终止条件(done)。

    def step(self, action):
        assert self.action_space.contains(action), "%r (%s) invalid" % (
            action,
            type(action),
        )

        position, velocity = self.state
        velocity += (action - 1) * self.force + math.cos(3 * position) * (-self.gravity)
        velocity = np.clip(velocity, -self.max_speed, self.max_speed)
        position += velocity
        position = np.clip(position, self.min_position, self.max_position)
        if position == self.min_position and velocity < 0:
            velocity = 0

        done = bool(position >= self.goal_position and velocity >= self.goal_velocity)
        reward = -1.0

        self.state = (position, velocity)
        return np.array(self.state, dtype=np.float32), reward, done, {}

position, velocity = self.state:从self.state提取position, velocity(这里的初始值将在下一个reset函数中对其进行初始化)。

其后六行代码:根据运动学方程以及动力学方程对position, velocity进行更新。
done:判断智能体是否达到终止条件,此处终止条件为是否到达终点或是否到达指定速度
reward:这里是对每步进行惩罚以求最快到达山顶,reward不仅可以奖励也可以惩罚。reward如何设计影响训练速度。
return np.array(self.state, dtype=np.float32), reward, done, {}:返回值包括下一个状态(self.state),奖励(reward),完成状态(done)和调试接口({})。

state:包含智能体的运动学方程信息,编写智能体时可将所需的信息都加入其中,如无人机可加入俯仰角,xyz空间位置,速度,加速度等参数。
 

1.5 reset

      重置环境,将状态设置为初始状态,返回状态信息(不参与网络的计算)
补充: step中的state需要几个参数,这里就需要初始化几个参数。

    def reset(self):
        self.state = np.array([self.np_random.uniform(low=-0.6, high=-0.4), 0])
        return np.array(self.state, dtype=np.float32)

1.6 render

绘图函数,可以为空,但必须存在。

        def render(self, mode='human', close=False):
        if close:
            if self.viewer is not None:
                self.viewer.close()
                self.viewer = None
            return
        screen_width = 600
        screen_height = 400

        world_width = self.max_position - self.min_position
        scale = screen_width / world_width
        carwidth = 40
        carheight = 20

        if self.viewer is None:
            from gym.envs.classic_control import rendering

            self.viewer = rendering.Viewer(screen_width, screen_height)
            xs = np.linspace(self.min_position, self.max_position, 100)
            ys = self._height(xs)
            xys = list(zip((xs - self.min_position) * scale, ys * scale))

            self.track = rendering.make_polyline(xys)
            self.track.set_linewidth(4)
            self.viewer.add_geom(self.track)

            clearance = 10

            l, r, t, b = -carwidth / 2, carwidth / 2, carheight, 0
            car = rendering.FilledPolygon([(l, b), (l, t), (r, t), (r, b)])
            car.add_attr(rendering.Transform(translation=(0, clearance)))
            self.cartrans = rendering.Transform()
            car.add_attr(self.cartrans)
            self.viewer.add_geom(car)
            frontwheel = rendering.make_circle(carheight / 2.5)
            frontwheel.set_color(0.5, 0.5, 0.5)
            frontwheel.add_attr(
                rendering.Transform(translation=(carwidth / 4, clearance))
            )
            frontwheel.add_attr(self.cartrans)
            self.viewer.add_geom(frontwheel)
            backwheel = rendering.make_circle(carheight / 2.5)
            backwheel.add_attr(
                rendering.Transform(translation=(-carwidth / 4, clearance))
            )
            backwheel.add_attr(self.cartrans)
            backwheel.set_color(0.5, 0.5, 0.5)
            self.viewer.add_geom(backwheel)
            flagx = (self.goal_position - self.min_position) * scale
            flagy1 = self._height(self.goal_position) * scale
            flagy2 = flagy1 + 50
            flagpole = rendering.Line((flagx, flagy1), (flagx, flagy2))
            self.viewer.add_geom(flagpole)
            flag = rendering.FilledPolygon(
                [(flagx, flagy2), (flagx, flagy2 - 10), (flagx + 25, flagy2 - 5)]
            )
            flag.set_color(0.8, 0.8, 0)
            self.viewer.add_geom(flag)

        pos = self.state[0]
        self.cartrans.set_translation(
            (pos - self.min_position) * scale, self._height(pos) * scale
        )
        self.cartrans.set_rotation(math.cos(3 * pos))

        return self.viewer.render(return_rgb_array=mode == "rgb_array")

开头设定画布的大小,以及智能体。

rendering.Line:画线

rendering.make_circle(10):画圆

rendering.Transform():添加旋转平移属性等

注意:可在奖励累积到一定程度时再调用绘图查看训练效果。可以减少资源浪费。

1.7 close

    def close(self):
        if self.viewer:
            self.viewer.close()
            self.viewer = None

2.调用环境

搭建好训练环境之后需要执行以下操作才可调用。

2.1 注册

      找到Gym的安装目录,就是说打开D:\anaconda3\Lib\site-packages\gym\envs文件夹,进而打开__init__.py文件加入以下内容。

register (
id= 'GridWorld-v0',
entry_point='gym.envs.classic_control:GridEnv', 
max_episode_steps=200, reward_threshold=100.0,
)

id:是为了调用所构建的环境的时候起的名字
entry_point:是环境文件所在的位置,本例的文件放在D:\anaconda3\lib\site-packages\gym\envs\classic_control中

2.2 放入库中

      在D:\anaconda3\lib\site-packages\gym\envs\classic_control目录下的__init__.py文件中加入以下内容

from gym.envs.classic_control.grid_mdp import GridEnv

grid_mdp:是训练环境的文件名

GridEnv:是该文件下的类。

2.3 测试

在项目中新建main.py

import gym
import numpy as np
import time
import sys

env = gym.make('GridWorld-v1') # 导入自己的环境

env.reset()   # 初始化本场游戏的环境
env.render()    # 更新并渲染游戏画面
time.sleep(10)
env.close()
sys.exit()


参考文献

1.构建自己的gym训练环境 巨详细_gym自定义环境-CSDN博客

2.建立自己的gym环境并调用_gym 连续 环境-CSDN博客 

3.随机种子如何理解?_王摇摆的博客-CSDN博客 

你可能感兴趣的:(人工智能)