手动编写环境是一件很耗时间的事情,所以如果可以直接使用比人编写好的环境,可以节约我们很多时间。OpenAI gym就是这样一个模块,他提供给我们很多优秀的模拟环境。我们的各种强化学习算法都能使用这些环境。之前的环境都是用tkinter
来手动编写,或者想玩玩更厉害的,像OpenAI一样,使用pyglet模块来编写。
OpenAI gym官网:https://gym.openai.com/
我们可以先看看OpenAI gym有哪些游戏: 有2D的:
也有3D的:
本次将会以CartPole和MountainCar两个经典例子来给大家说明。
笔者电脑是Ubuntu16.04,可以直接复制下面代码安装:
1# python 2.7, 复制下面
2$ pip install gym
3
4# python 3.5, 复制下面
5$ pip3 install gym
如果没有报错那就安装好gym(基本款),可以玩以下游戏:
algorithmic
toy_text
classic_control
(这个需要pyglet模块)如果你想玩gym提供的全套游戏,则使用以下代码:
1# python 2.7, 复制下面
2$ pip install gym[all]
3
4# python 3.5, 复制下面
5$ pip3 install gym[all]
这个游戏的目的是让小车尽量不偏离中心以及棍子尽量垂直,我们可以看下面的示例图,经过训练后小车就会尽量呆在中间棍子也基本保持垂直。
我们还是采用DQN的方式来实现RL,完整代码最后会给我的github链接。
1import gym
2from RL_brain import DeepQNetwork
3
4env = gym.make('CartPole-v0') #定义使用gym库中的哪一个环境
5env = env.unwrapped #还原env的原始设置,env外包了一层防作弊层
6
7print(env.action_space) #查看这个环境可用的action有多少个
8print(env.observation_space) #查看这个环境中可用的state的observation有多少个
9print(env.observation_space.high) #查看observation最高取值
10print(env.observation_space.low) #查看observation最低取值
11
12RL = DeepQNetwork(n_actions=env.action_space.n,
13 n_features=env.observation_space.shape[0],
14 learning_rate=0.01, e_greedy=0.9,
15 replace_target_iter=100, memory_size=2000,
16 e_greedy_increment=0.001,)
17
18total_steps = 0
19
20
21for i_episode in range(100):
22 #获取回合i_episode第一个observation
23 observation = env.reset()
24 ep_r = 0
25 while True:
26 env.render()#刷新环境
27
28 action = RL.choose_action(observation)#选行为
29
30 observation_, reward, done, info = env.step(action)#获取下一个state
31
32 # x是车的水平位移,所以r1是车越偏离中心,得分(reward)越少
33 # theta是棒子离垂直的角度,角度越大,越不垂直。所以r2是棒越垂直,分(reward)越高
34 # 总reward是r1和r2的结合,既考虑位置也考虑角度,这样DQN学习更有效率
35 x, x_dot, theta, theta_dot = observation_
36
37 r1 = (env.x_threshold - abs(x))/env.x_threshold - 0.8
38 r2 = (env.theta_threshold_radians - abs(theta))/env.theta_threshold_radians - 0.5
39 reward = r1 + r2
40
41 #保存这一组记忆
42 RL.store_transition(observation, action, reward, observation_)
43
44 ep_r += reward
45 if total_steps > 1000:
46 RL.learn()
47
48 if done:
49 print('episode: ', i_episode,
50 'ep_r: ', round(ep_r, 2),
51 ' epsilon: ', round(RL.epsilon, 2))
52 break
53
54 observation = observation_
55 total_steps += 1
56
57RL.plot_cost()
这是更为典型的RL cost曲线:
小车经过谷底的震荡,慢慢地就可以爬到山顶拿旗子了。
代码和上面差不多,只是定义的reward不同:
1import gym
2from RL_brain import DeepQNetwork
3
4env = gym.make('MountainCar-v0')
5env = env.unwrapped
6
7print(env.action_space)
8print(env.observation_space)
9print(env.observation_space.high)
10print(env.observation_space.low)
11
12RL = DeepQNetwork(n_actions=3, n_features=2, learning_rate=0.001, e_greedy=0.9,
13 replace_target_iter=300, memory_size=3000,
14 e_greedy_increment=0.0002,)
15
16total_steps = 0
17
18
19for i_episode in range(10):
20
21 observation = env.reset()
22 ep_r = 0
23 while True:
24 env.render()
25
26 action = RL.choose_action(observation)
27
28 observation_, reward, done, info = env.step(action)
29
30 position, velocity = observation_
31
32 # 车开的越高reward越大
33 reward = abs(position - (-0.5)) # r in [0, 1]
34
35 RL.store_transition(observation, action, reward, observation_)
36
37 if total_steps > 1000:
38 RL.learn()
39
40 ep_r += reward
41 if done:
42 get = '| Get' if observation_[0] >= env.unwrapped.goal_position else '| ----'
43 print('Epi: ', i_episode,
44 get,
45 '| Ep_r: ', round(ep_r, 4),
46 '| Epsilon: ', round(RL.epsilon, 2))
47 break
48
49 observation = observation_
50 total_steps += 1
51
52RL.plot_cost()
出来的cost曲线是这样的: