import gym
env = gym.make('CartPole-v0')
env.reset()
env.render()
def _reset()
self.state = self.np_random.uniform(low=-0.05, high=0.05, size=(4,))
# 利用均匀随机分布初试化环境的状态
self.steps_beyond_done = None
# 设置当前步数为None
return np.array(self.state)
# 返回环境的初始化状态
def _render(self, mode=’human’, close=False):
if close:
…. #省略,直接看关键代码部分
if self.viewer is None:
from gym.envs.classic_control
import rendering
#这一句导入rendering模块,利用rendering模块中的画图函数进行图形的绘制
#如绘制600*400的窗口函数为:
self.viewer = rendering.Viewer(screen_width, screen_height)
#其中screen_width=600,screen_height=400
#创建小车的代码为:
l,r,t,b = -cartwidth/2,
cartwidth/2, cartheight/2, -cartheight/2
axleoffset =cartheight/4.0
cart = rendering.FilledPolygon([(l,b), (l,t), (r,t), (r,b)])
#其中rendering.FilledPolygon为填充一个矩形。
#创建完cart的形状,接下来给cart添加平移属性和旋转属性。将车的位移设置到cart的平移属性中,cart就会根据系统的状态变化左右运动。
其输入是动作a,输出是:下一步状态,立即回报,是否终止,调试项。该函数描述了智能体与环境交互的所有信息,是环境文件中最重要的函数。在该函数中,一般利用智能体的运动学模型和动力学模型计算下一步的状态和立即回报,并判断是否达到终止状态。
def _step(self, action):
assert self.action_space.contains(action), "%r (%s) invalid"%(action,
type(action))
state = self.state
x, x_dot, theta, theta_dot = state #系统的当前状态
force = self.force_mag if action==1 else -self.force_mag #输入动作,即作用到车上的力
costheta = math.cos(theta) #余弦函数
sintheta = math.sin(theta) #正弦函数
#以下是车摆的动力学方程式,即加速度与动作之间的关系。
temp = (force + self.polemass_length * theta_dot * theta_dot * sintheta) / self.total_mass
thetaacc = (self.gravity * sintheta - costheta* temp) / (self.length *
(4.0/3.0 - self.masspole * costheta * costheta / self.total_mass)) #摆的角加速度
xacc = temp - self.polemass_length * thetaacc * costheta / self.total_mass #小车的平移加速
x = x + self.tau * x_dot
x_dot = x_dot + self.tau * xacc
theta = theta + self.tau * theta_dot
theta_dot = theta_dot + self.tau * thetaacc #积分求下一步的状态
self.state = (x,x_dot,theta,theta_dot)
import gym
import time
env = gym.make('CartPole-v0') #创造环境
observation = env.reset() #初始化环境,observation为环境状态
count = 0
for t in range(100):
action = env.action_space.sample() #随机采样动作
observation, reward, done, info = env.step(action) #与环境交互,获得下一步的时刻
if done:
break
env.render() #绘制场景
count+=1
time.sleep(0.2) #每次等待0.2s
print(count) #打印该次尝试的步数
参考gym中经典的CartPole环境代码CartPole.py,我们逐步构建自定义环境。
将要创建的是一个在二维水平面上移动的小车。该二维区域长宽各20单位。区域中心为坐标原点,也是小车要到达的目的地。
动作:小车每次只能选择不动或向四周移动一个单位。
状态:小车的横纵坐标。
奖励:小车到达目的地周围有+10的奖励;每移动一个单位有-0.1的奖励,这表示我们希望小车尽量以较少的时间(移动次数)到达终点;小车移动到区域外的奖励为-50。
首先新建一个Car2D.py的文件,需要import的包如下:
import gym
from gym import spaces
import numpy as np
声明一个Car2DEnv的类,它是gym.Env的子类。它一般包括的内容如下:
The minimal required interface for an environment is composed of the __init__
, reset
, step
, render
and close
routines.
class Car2DEnv(gym.Env):
metadata = {
'render.modes': ['human', 'rgb_array'],
'video.frames_per_second': 2
}
def __init__(self):
self.action_space = None
self.observation_space = None
pass
def step(self, action):
return self.state, reward, done, {}
def reset(self):
return self.state
def render(self, mode='human'):
return None
def close(self):
return None
必须实现的内容:
__init__()
:将会初始化动作空间与状态空间,便于强化学习算法在给定的状态空间中搜索合适的动作。gym提供了spaces方法,详细内容可以help查看;
step()
:用于编写智能体与环境交互的逻辑,它接受action的输入,给出下一时刻的状态、当前动作的回报、是否结束当前episode及调试信息。输入action由__init__()函数中的动作空间给定。我们规定当action为0表示小车不动,当action为1,2,3,4时分别是向上、下、左、右各移动一个单位。据此可以写出小车坐标的更新逻辑;
reset()
:用于在每轮开始之前重置智能体的状态。
不是必须实现的但有助于调试算法的内容:
metadata、render()、close()是与图像显示有关的,我们不涉及这一部分。
完整的Car2D.py代码如下
# -*- coding: utf-8 -*-
import gym
from gym import spaces
import numpy as np
class Car2DEnv(gym.Env):
metadata = {
'render.modes': ['human', 'rgb_array'],
'video.frames_per_second': 2
}
def __init__(self):
self.xth = 0
self.target_x = 0
self.target_y = 0
self.L = 10
self.action_space = spaces.Discrete(5) # 0, 1, 2,3,4: 不动,上下左右
self.observation_space = spaces.Box(np.array([self.L, self.L]), np.array([self.L, self.L]))
self.state = None
def step(self, action):
assert self.action_space.contains(action), "%r (%s) invalid"%(action, type(action))
x, y = self.state
if action == 0:
x = x
y = y
if action == 1:
x = x
y = y + 1
if action == 2:
x = x
y = y - 1
if action == 3:
x = x - 1
y = y
if action == 4:
x = x + 1
y = y
self.state = np.array([x, y])
self.counts += 1
done = (np.abs(x)+np.abs(y) <= 1) or (np.abs(x)+np.abs(y) >= 2*self.L+1)
done = bool(done)
if not done:
reward = -0.1
else:
if np.abs(x)+np.abs(y) <= 1:
reward = 10
else:
reward = -50
return self.state, reward, done, {}
def reset(self):
self.state = np.ceil(np.random.rand(2)*2*self.L)-self.L
self.counts = 0
return self.state
def render(self, mode='human'):
return None
def close(self):
return None
if __name__ == '__main__':
env = Car2DEnv()
env.reset()
env.step(env.action_space.sample())
print(env.state)
env.step(env.action_space.sample())
print(env.state)
https://www.zhihu.com/collection/581976137
https://www.zhihu.com/question/58126239