背景说明
作者最近使用processing的一个重要目标就是为学生的编程学习设计具体的应用场景,最近突然发现有一个包已经提供了部分功能,所以探索一下。这个包就是我们今天的主人公:Gym。
Gym是用于开发和比较强化学习算法的python包,但是我们也完全可以使用它来作为我们自己程序的应用背景,并提供可视化。简单的说,就是我们使用自己写的小程序,而不是强化学习算法,来尝试完成其中的任务,并把完成任务的过程可视化。
它的具体的训练场景 包括了从文字游戏,电子游戏,物理引擎(box2D)或专业物理引擎(MuJoCo)中的控制训练,而且还支持自定义训练场景。Gym中基于box2D的场景页
这篇文章和processing已经没有直接关系了,但是却和趣味编程的关系很大。所以就也放在这个专栏下面了,请各位理解~
编程环境搭建
作者推荐在使用Anaconda和Pycharm软件的条件下,安装python以及Gym就可以啦,网上相关的资源很多,大家可以找到后学习实践一下~
官方入门代码解析
示例1:这是使用Gym的程序的最基本框架。可以看出还是非常易懂的。注释是我自己加的。场景大概就是一个倒立摆了:一个能水平运动的小车上倒立了一个摆,控制目标是保持这个摆的稳定以及让车子的位置在一定范围内。
import gym # 导入包
env = gym.make('CartPole-v0') # 构建一个名字叫“CartPole-v0”的Gym场景
env.reset() # 初始化场景
for _ in range(200): #
env.render() # 画出当前场景情况
env.step(env.action_space.sample()) # 给环境中Agent一次命令,并让环境演化一步
env.close() # 关闭环境程序运行截图
示例2:
import gym
env = gym.make('CartPole-v0')
for i_episode in range(20):
observation = env.reset() # 得到环境给出的初始反馈
for t in range(100):
env.render()
print(observation)
action = env.action_space.sample() # 产生一个允许范围内的随机行动
observation, reward, done, info = env.step(action) # 得到该次行动的反馈
if done:
print("Episode finished after {} timesteps".format(t+1))
break
env.close()
这段代码相比上个代码稍显复杂,但是却才是真正意义上完整了。其中的关键代码是:
observation, reward, done, info = env.step(action)
可以看出 env.step() 有四个返回值,分别代表着 反馈,奖励,是否结束,其他信息 。
如果结束了(相当于Gym根据你使用的环境的规则判断你的这次行动已经失败并停止环境的更新)就开始下一个循环,并初始化环境,重新开始(所以说这次程序框架才是真正完整了)。
需要注意,每个环境所返回的observation的具体含义是不同的。关于这个环境的具体返回信息,我查询了:该模型的首页, 以及该模型的源码中的注释。
当然,把Gym当作一个普通的python包而对其进行探索,是有普适的方法的。常见的技巧有:使用dir(), help(), type(), 查询文档以及阅读源码。
制作人工智障
初代智障:
import gym
env = gym.make('CartPole-v0')
t_all = []
for i_episode in range(20):
observation = env.reset()
for t in range(100):
env.render()
cp, cv, pa, pv = observation
if pa >= 0 :
action = 1
else:
action = 0
observation, reward, done, info = env.step(action)
if done:
# print("Episode finished after {} timesteps".format(t+1))
t_all.append(t)
break
env.close()
print(sum(t_all)/len(t_all))
程序中得到的反馈中的变量 pa 代表了棍子倾斜的角度。这个程序的基本思路是:如果杆子向右歪了,那我们的小车就向右走。如果向左歪了,我们就向左走。
需要注意的是,初始时候,杆子角度为零,必须先走一下,让系统进入不稳定状态,后续程序才能顺利执行。
我们还是用了一个列表 t_all 来保存每次我们程序坚持的时间,并在最后给出了平均值,便于评价Agent的智力水平。对该程序一次测试得到的结果是:40.55(每次运行的结果会稍有不同)。相比随机反应的结果:21.05,已经有了很大提升了。
改进版人工智障
根据误差越大,反应越大的原则,我们可以看出上一个程序是没有体现这个原则的。对应的最大的问题是:可能在棍子基本直立的时候,我们的车子猛地就动了,属于矫枉过正。为了避免这个问题,我们让Agent在棍子角度很小的时候,交替左右运动(基本相当于不动,因为这个场景只允许车子向左或者向右动,所以只能这样处理啦~)。
import gym
env = gym.make('CartPole-v0')
t_all = []
action_bef = 0
for i_episode in range(20):
observation = env.reset()
for t in range(100):
env.render()
cp, cv, pa, pv = observation
if abs(pa)<= 0.1:
action = 1 -action_bef
elif pa >= 0:
action = 1
elif pa <= 0:
action = 0
observation, reward, done, info = env.step(action)
action_bef = action
if done:
# print("Episode finished after {} timesteps".format(t+1))
t_all.append(t)
break
env.close()
print(sum(t_all)/len(t_all))
这次程序的平均坚持时间是86.0,又是一次飞跃哇~
当然程序中的角度阈值 0.1 是经过很多次的测试得到的。该值太大的时候,程序运行效果会很差。
下面就让我们通过视频看一下改进版人工智障的风采吧:改进版人工智障https://www.zhihu.com/video/1161341786474815488
从视频中可以看出我们的程序已经有点自动纠正倾斜的感觉了呢~