基于Policy Gradient实现CartPole
http://chenrudan.github.io/blog/2016/09/04/cartpole.html
基于Policy Gradient实现CartPole
【转载请注明出处】chenrudan.github.io
8月的时候把David silver的强化学习课上了,但是一直对其中概念如何映射到现实问题中不理解,半个月前突然发现OpenAI提供了一个python库Gym,它创造了强化学习的environment,可以很方便的启动一个强化学习任务来自己实现算法(新智元OpenAI简介[1]),并且提供了不少可以解决的问题来练手https://openai.com/requests-for-research/。本文针对如何解决入门问题CartPole,来解释一下怎么将之前课上的算法转化成实现代码。这里强烈推荐一下官网的教程http://kvfrans.com/simple-algoritms-for-solving-cartpole/,因为这个作者只是个高中生T^T…
建了一个强化学习讨论qq群,有兴趣的可以加一下群号595176373或者扫描下面的二维码。
1. Gym库
它提供了一些函数接口,模拟了强化学习问题中environment,当向它传递一个动作,它相应会返回执行这个动作后的状态、奖赏等。
1
2
3
4
|
#启动某种环境
env = gym.make('CartPole-v0')
#针对传进来的动作返回状态observation等
observation, reward, done, info = env.step(action)
|
执行pip install gym即可安装,https://gym.openai.com/docs中有实例,复制代码运行即可检查是否安装成功。此外提供了env.monitor来记录下算法执行过程,它会保存为.mp4文件,然后上传到OpenAI网站上可以检查执行效率,上传可以通过执行代码中加入api_key(鉴别用户),我是直接把api_key写入了~/.bashrc文件中即”export OPENAI_GYM_API_KEY=”。
2. CartPole问题
CartPole的玩法如下动图所示,目标就是保持一根杆一直竖直朝上,杆由于重力原因会一直倾斜,当杆倾斜到一定程度就会倒下,此时需要朝左或者右移动杆保证它不会倒下来。我们执行一个动作,动作取值为0或1,代表向左或向右移动,返回的observation是一个四维向量,reward值一直是1,当杆倒下时done的取值为False,其他为True,info是调试信息打印为空具体使用暂时不清楚。如果杆竖直向上的时间越长,得到reward的次数就越多。
1
2
3
4
|
#从动作空间中采样一个动作
action = env.action_space.sample()
observation, reward, done, info = env.step(action)
print observation
|
结果是[-0.061586 -0.75893141 0.05793238 1.15547541]。
图1 CartPole示意图
3. 三种解法
目的是在不同状态下执行出合适的action,代码中要做的就是替换掉采样这一行,用policy来决定执行什么动作。也就是说此处需要决定policy的形式,官网给出了两种思路,已知policy的输入是当前所处的状态observation,输出是action的取值即0 or 1,observation是一个四维向量,如果对这个向量求它的加权和,就可以得到一个值,那么就可以根据加权和的符号来决定action,同样可以用sigmoid函数当成二分类问题。基于这两种policy可以得到下面三种解法,核心就在于通过改变加权的权重值就能改变policy。
3.1 Random Guessing Algorithm & Hill Climbing Algorithm
由于policy中权重也是一个四维向量,如果随机给四维向量赋值,有机会得到比较好的policy。首先先实现一个函数用来衡量给定的某组权重效果如何,函数返回值是这组权重下得到的奖赏,意义是杆维持了多长时间未倒下,代码如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
def evaluate_given_parameter_by_sign(env, weight):
#启动初始状态
observation = env.reset()
#这组参数返回的总reward
total_reward = 0.
for t in range(1000):
#这个渲染函数就是实时展示图1,如果隐藏,代码正常执行,但是不会显示图1了
env.render()
weighted_sum = np.dot(weight, observation)
#根据符号policy选出action
if weighted_sum >= 0:
action = 1
else:
action = 0
observation, reward, done, info = env.step(action)
total_reward += reward
if done:
break
return total_reward
|
然后要改变权重,这里试验了两种方法,一种是random guess,即随机给四维权重weight赋值,一种是hill climbing,即给当前最好的权重加上一组随机值,如果加上这组值持续时间变长了那么就更新最好的权重,如果没有变的更好就不更新。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
def random_guess():
env = gym.make('CartPole-v0')
np.random.seed(10)
best_reward = -100.0
for iiter in xrange(1000):
#####random guess随机初始化权重weight####
weight = np.random.rand(4)
#####
####hill climbing给best weight加随机值
weight = best_weight + np.random.normal(0, 0.01, 4)
#####
cur_reward = evaluate_given_parameter_by_sign(env, weight)
if cur_reward > best_reward:
best_reward = cur_reward
best_weight = weight
if best_reward == 1000:
break
print("XXX algorithm best reward", best_reward)
print("XXX algorithm best weight", best_weight)
|
3.2 Policy Gradient
上面的两种方法都是在随机的改变权重,针对这种参数非常少的情况确实能得到不错的效果,但是一旦参数数目增多,这种方式耗时非常大,一点也不实用。而第七课[2]讲解了两种Policy Gradient的方法,分别是Monte-Carlo Policy Gradient和Actor-Critic Policy Gradient。我们知道衡量policy好坏有三种方法,一是在某个状态下和该policy作用下能获得的值函数值,一是该policy作用下能获得的所有状态的期望值函数,一是在该policy作用下能获得的所有状态的期望immdiate reward,并且推导出了这三种方法的统一导数形式,即衡量policy的目标函数导数为▽θJ(θ)=Eπθ[▽θlogπθ(s,a)Qπθ(s,a)]▽θJ(θ)=Eπθ[▽θlogπθ(s,a)Qπθ(s,a)],这个式子也就是policy gradient。
根据题目的意思,此处的policy换成逻辑回归,即πθ(s,a)=11+e−wxπθ(s,a)=11+e−wx那么式子中▽θlogπθ(s,a)=(1−pi)∗(−x)▽θlogπθ(s,a)=(1−pi)∗(−x)。在第一种方法中用直接用immdiate reward代替Qπθ(s,a)Qπθ(s,a),所以在本例中就是直接取1。
首先定义一下选择action的函数,也就是利用sigmoid函数进行二分类。
1
2
3
4
5
6
7
8
|
def choose_action(weight, observation):
weighted_sum = np.dot(weight, observation)
pi = 1 / (1 + np.exp(-weighted_sum))
if pi > 0.5:
action = 1
else:
action = 0
return pi, action
|
由于Monte-Carlo方法中需要先基于某组参数算出一个episode,再基于这个episode来更新policy的参数,所以需要实现一个函数产生一个episode。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
def generate_episode(env, weight):
episode = []
pre_observation = env.reset()
t = 0
#generate 1 episodes for training.
while 1:
#env.render()
pi, action = choose_action(weight, pre_observation)
observation, reward, done, info = env.step(action)
#将这个episode的每一步产生的数据保存下来
episode.append([pre_observation, action, pi, reward])
pre_observation = observation
t += 1
if done or t > 1000:
break
return episode
|
从而可以实现第七课中Monte-Carlo的更新方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
def monte_carlo_policy_gradient(env):
learning_rate = -0.0001
best_reward = -100.0
weight = np.random.rand(4)
for iiter in xrange(1000):
cur_episode = generate_episode(env, weight)
for t in range(len(cur_episode)):
observation, action, pi, reward = cur_episode[t]
#根据第七课的更新公式
weight += learning_rate*(1-pi)*np.transpose(-observation)*reward
#衡量算出来的weight表现如何
cur_reward = evaluate_given_parameter_sigmoid(env, weight)
print 'Monte-Carlo policy gradient get reward', cur_reward
|
而针对Actor critic的方法,则是把值函数Qπθ(s,a)Qπθ(s,a)也当成observation的含参函数,且直接把observation的加权和当成值函数的取值,那么也就能由第七课的更新公式来同时更新值函数和policy的参数。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
def actor_critic_policy_gradient(env):
gamma = 1
p_weight = np.random.rand(4)
#值函数的权重
v_weight = np.random.rand(4)
p_learning_rate = -0.0001
v_learning_rate = -0.0001
done = True
for iiter in xrange(1000):
t = 0
while 1:
if done:
print 'start new training...'
print 'p_weight', p_weight
print 'v_weight', v_weight
pre_observation = env.reset()
pre_pi, pre_action = choose_action(p_weight, pre_observation)
pre_phi = pre_observation
pre_q = np.dot(v_weight, pre_phi)
#env.render()
observation, reward, done, info = env.step(pre_action)
pi, action = choose_action(p_weight, observation)
phi = observation
q = np.dot(v_weight, phi)
delta = reward + gamma*q - pre_q
p_weight += p_learning_rate*(1-pre_pi)*np.transpose(-pre_observation)*pre_q
v_weight += v_learning_rate*delta*np.transpose(pre_phi)
pre_pi = pi
pre_observation = observation
pre_q = q
pre_phi = phi
pre_action = action
t += 1
if done:
break
cur_reward = evaluate_given_parameter_sigmoid(env, p_weight)
print 'Actor critic policy gradient get reward', cur_reward
|
4.提交到OpenAI
上面的代码实现以后,就能够提交到OpenAI的网站上去评估效果如何,首先加上两行代码,变成下面的样子。
1
2
3
4
|
env = gym.make('CartPole-v0')
env.monitor.start('cartpole-hill/', force=True)
actor_critic_policy_gradient(env)
env.monitor.close()
|
这会将训练过程记录下来生成.mp4文件,如果像我这样将api_key写入~/.bashrc,就可以直接执行下面代码提交给OpenAI。
1
|
gym.upload('cartpole-hill')
|
最后在网站上就能看到如下的结果。
图2 结果提交成功图
5.小结
我的policy gradient是完全按照第七课的内容实现的,但是实际上效果还不够好,并且非常依赖初始值,初始值好就很快收敛,不好就会一直恶性循环。总之感觉这个网站还是很有意思的,值得去玩一玩,文中的代码在这里。
基于Policy Gradient实现CartPole的更多相关文章
- Policy Gradient
Policy Gradient是区别于Q-Learning为代表的value based的方法.policy gradient又可以叫reinforce算法(Williams, 1992). 如今的A ...
- Deep Learning专栏--强化学习之从 Policy Gradient 到 A3C(3)
在之前的强化学习文章里,我们讲到了经典的MDP模型来描述强化学习,其解法包括value iteration和policy iteration,这类经典解法基于已知的转移概率矩阵P,而在实际应用中,我们 ...
- 强化学习(十三) 策略梯度(Policy Gradient)
在前面讲到的DQN系列强化学习算法中,我们主要对价值函数进行了近似表示,基于价值来学习.这种Value Based强化学习方法在很多领域都得到比较好的应用,但是Value Based强化学习方法也有很 ...
- [Reinforcement Learning] Policy Gradient Methods
上一篇博文的内容整理了我们如何去近似价值函数或者是动作价值函数的方法: \[ V_{\theta}(s)\approx V^{\pi}(s) \\ Q_{\theta}(s)\approx Q^{\p ...
- 论文笔记之:SeqGAN: Sequence generative adversarial nets with policy gradient
SeqGAN: Sequence generative adversarial nets with policy gradient AAAI-2017 Introduction : 产生序列模拟数 ...
- 强化学习读书笔记 - 13 - 策略梯度方法(Policy Gradient Methods)
强化学习读书笔记 - 13 - 策略梯度方法(Policy Gradient Methods) 学习笔记: Reinforcement Learning: An Introduction, Richa ...
- 深度增强学习--Policy Gradient
前面都是value based的方法,现在看一种直接预测动作的方法 Policy Based Policy Gradient 一个介绍 karpathy的博客 一个推导 下面的例子实现的REINFOR ...
- 深度学习-深度强化学习(DRL)-Policy Gradient与PPO笔记
Policy Gradient 初始学习李宏毅讲的强化学习,听台湾的口音真是费了九牛二虎之力,后来看到有热心博客整理的很细致,于是转载来看,当作笔记留待复习用,原文链接在文末.看完笔记再去听一听李宏毅 ...
- Ⅶ. Policy Gradient Methods
Dictum: Life is just a series of trying to make up your mind. -- T. Fuller 不同于近似价值函数并以此计算确定性的策略的基于价 ...
随机推荐
- thinkphp5 邮件发送(qq邮箱为例)
一.首先需要你开启smtp 服务,登录qq邮箱,进入设置 -> 账户 注意: 开启后会生成授权码,一定要记下,两个都记下,登录邮件客户端需要.这里配置邮件发送也需要这个授权码 二. 下载phpm ...
- MQTT协议笔记之mqtt.io项目Websocket协议支持
前言 MQTT协议专注于网络.资源受限环境,建立之初不曾考虑WEB环境,倒也正常.虽然如此,但不代表它不适合HTML5环境. HTML5 Websocket是建立在TCP基础上的双通道通信,和TCP通 ...
- 使用Java对文件进行解压缩
最近在一个项目中需要对文件进行自动的解压缩,Java提供了这种支持,还是挺好用的. 工具包封装在java.util.zip中. 1.首先是多个文件压缩成一个ZIP文件 思路:用一个ZipOutputS ...
- AndroidStudio build.gradle 报错
Android Studio. I'm getting this kind of error during application run. Error:Execution failed for ta ...
- 百度地图api添加自定义控件
官网栗子:http://lbsyun.baidu.com/jsdemo.htm#b0_6 <!DOCTYPE html><html><head> <meta ...
- 百度地图API开发----手机地图做导航功能
第一种方式:手机网页点击打开直接进百度地图APP <a href="baidumap://map/direction?mode=[transit:公交,driving:驾车]& ...
- 05StuList.aspx(学生列表)
05StuList.aspx 加载学生列表(前天代码) <%@ Page Language="C#" AutoEventWireup="true" Co ...
- 转载:隐式Intent
一.隐式意图介绍 显式意图我们前面已经提到,形如: Intent intent = new Intent(); intent.setClass(this,Other.class); //此句表示显式意 ...
- Log4Net的简单使用
在前面的随笔中,已经异常处理过滤器中,我们已经将获取到的错误信息写到队列中去,然后又单独的线程对队列中的错误信息处理,将错误信息输出到制定的文件中,但是如果我们需要改变需求,打算将错误信息输出到数据库 ...
- TFIDF练习
直接上代码吧: """ 测试Demo """ import lightgbm as lgb import numpy as np from ...