欢迎转载,转载请注明出处——知乎专栏“机器学习与控制论”。
读过DDPG论文[1]的同学几乎都会有一个问题,论文中使用Ornstein-Uhlenbeck噪声用于探索,比较难理解,参数又多,真的会比简单的高斯噪声等更有效吗?
由于大部分回答都没有说清楚甚至
完全相反地解释该部分,本文会尝试从噪声在强化学习中的应用背景、Ornstein-Uhlenbeck过程的定义、产生作用的原因、实验四部分阐述原因。
先放结论:相比于独立噪声,OU噪声适合于惯性系统,尤其是
时间离散化粒度较小的情况,此外,它可以保护实际系统,如机械臂。之所以大家觉得OU噪声没用,是因为强化学习benchmark都是仿真任务,而且往往都不用考虑时间离散化的问题。另外,即使遇到时间离散粒度小的问题,一般直接增大离散化粒度之后独立噪声也可以起到很好的效果。
1.DDPG中的探索噪声
我们知道,DDPG是典型的off-policy的方法,可叠加噪声的执行策略会独立于评估/学习的策略。也就是说,DDPG学习的策略是确定性策略,即确定性的Actor网络,而探索部分可以自定义探索噪声。
先不考虑文中的OU噪声,一提到噪声,首先想到的是简单又易于实现的高斯噪声。并且,确定性策略加上高斯噪声后,形式上就和REINFORCE等Actor-Critic的随机策略一致了。
(1)高斯噪声策略网络直接的输出,作为均值,叠加上高斯分布
即可。此时执行策略实际上就成了
。有需要的话,还可以进行截断。
action
显然,高斯噪声是
时序上不相关的,前一步和后一步选取动作的时候噪声都是独立的。前后两动作之间也只是通过状态使其独立。
其实TD3算法[2]中正是采用这种探索噪声,他们声称:
Unlike the original implementation of DDPG, we used uncorrelated noise for exploration as we found noise drawn from the Ornstein-Uhlenbeck (Uhlenbeck & Ornstein, 1930) process offered no performance benefits.
真的是这样吗?
(2)Ornstein-Uhlenbeck噪声DDPG中对引入OU噪声的说明如下图,即利用OU过程产生时序相关的探索,以提高在
惯性系统中的控制任务的探索效率。这里的惯性系统是指的
环境。另外一处,同样提到OU噪声是为了在
有momentum的环境中探索得更好。
先不谈控制理论,这个环境大概怎么理解呢?你可以想象为一个慢响应的环境,比如夏天在一个闷热的房间,你打开空调制冷10秒钟,温度不会马上降下来,
维持它原来的状态,还是很热。再比如说,控制一辆高速行驶的卡车,你踩一脚刹车,车子不会立马停下来。Deepmind说,这种情况下用OU noise比较好。
为什么?先来看看定义。
2.什么是Ornstein-Uhlenbeck过程
OU 过程是一种随机过程,微分方程[3]如下,形式上很简单。其连续形式为
其中是
均值,
和
都大于0,
是维纳过程(布朗运动)。
是状态,常见1维标量。
右边第二项是扰动,暂不考虑。其离散形式为
为什么说OU过程是均值回归?当
比均值
大的时候,下一步状态就会变小;反之,下一步状态会变大。也就是说,状态偏离的时候会被拉到靠近均值。
此外,不考虑维纳过程, 直接积分得到(3)式。
的作用就很明确了,其值越大,向均值靠近的速度就越快。而且是指数倍的靠近。
再考虑扰动项,维纳过程,每一段时间间隔内的增量,是服从高斯分布的。
则是维纳过程的参数,表示方差。在OU过程中,它也决定扰动的放大倍数。
数学形式上,维纳过程是
高斯白噪声的积分。
注意,和上面说的高斯噪声不一样,是
积分!也就是说,即使我们只考虑第二项维纳过程,得到的
每一步的噪声会是从0时刻开始高斯噪声的累加,建议自己画个图。
直观理解
这两个参数的影响,一图胜千言,其中
就是上面的
。
图片来自于[3]
代码很简单:
class
非常感谢 @pb博 的指出,以上代码不完善,默认公式(2)OU过程中
,但实际上这里进行前向差分计算,
的时候,直接取采样时间1s可能相对于原始OU过程会有较大误差,刚看了下OPENAI的baseline,
设为参数,的默认值是0.01s。
class OrnsteinUhlenbeckActionNoise(ActionNoise):
def __init__(self, mu, sigma, theta=.15, dt=1e-2, x0=None):
self.theta = theta
self.mu = mu
self.sigma = sigma
self.dt = dt
self.x0 = x0
self.reset()
def __call__(self):
x = self.x_prev + self.theta * (self.mu - self.x_prev) * self.dt + self.sigma * np.sqrt(self.dt) * np.random.normal(size=self.mu.shape)
self.x_prev = x
return x
def reset(self):
self.x_prev = self.x0 if self.x0 is not None else np.zeros_like(self.mu)
总结,作为强化学习的噪声,OU噪声和高斯噪声相比,有什么区别? 由(2)式可以看到,OU noise是自相关的,后一步的噪声受前一步的影响(且是马尔科夫的)。而第一部分阐述的高斯噪声,前后两步都是完全独立的。
OU过程mu=0,sigma=1,theta=0.15(上)、标准正态分布(下)
所以,从图上看,OU noise往往不会高斯噪声一样相邻的两步的值差别那么大,而是会绕着均值附近正向或负向探索一段距离,就像物价和利率的波动一样,这有利于在一个方向上探索。
参考quora的这个回答(
强烈建议配合该回答食用):
Imagine trying to swim by nervously shaking your arms and legs in every direction in some chaotic and out of sync manner. That wouldn’t be very efficient, would it?
3.什么时候可能有作用
两种情况:(1)惯性系统(环境)(2)保护实际机械臂/机器人对于之前提到的惯性系统,为什么自相关的OU噪声会比高斯噪声更有作用呢?
回到之前的例子,现在30°,学习控制空调温度到26°,产生了一系列的不相关的在0均值附近高斯噪声,比如开10秒制热,再开10秒制冷,这样反复地在原地振荡,产生的作用就被平均了。而OU噪声,会往制冷方向多探索几步,这样
积累的效果能探索到更低的温度。
quora的这个回答从机器人控制的角度进行了解释:
DDPG is mainly used for continuous control tasks, such as locomotion. In this setting, the actions aa often correspond to exerting forces so as to move a physical body. Forces directly translate to accelerations, so they need to be integrated twice to affect the position xx of the system that we wish to control.
mx¨=amx¨=a
x=1m∫∫ax=1m∫∫a
Yet, the integration operator is a low-pass filter, which means that any high-frequency present in the action aa will be dampened.
简单来说,机器人中我们控制的是力,力作用到物体的速度或位移,这个动态过程(环境)是一个
积分过程,积分过程正是常说的“
惯性系统”。
积分过程是典型的低通滤波,高斯噪声这种独立的噪声前后两步差别太大,会被过滤掉:
高斯噪声使得速度和位移的探索极为有限,而OU噪声由之前说的特点,则可以探索的更远:
DDPG中引用的这篇文献[4]从另一方面探讨了关于机器人控制中引入自相关噪声的问题:
作者推导公式得出的结论是:
The finer time discretization, the less significant each particular action is, and the more noise it should contain. That leads to excessively discontinuous control signal, inappropriate for robotic applications.
如果使用独立的噪声,当
时间离散的粒度越小,要维持同样的随机程度,则需要每一步
噪声幅度(方差)就要越大,这就会导致前后两步相差极其的远,
并不适合真实的机械臂。
文中声称,自相关的噪声能使得控制信号较为连续,可以在时间粒度小的时候,达到类似的效果,不过相比于采样时间大+独立噪声的方案,训练可能会慢些——其实也很好理解,采样时间较大的时候,即使是独立的噪声,动作带来的效果也很容易被验证,从而可以快速调整策略。而采样时间小的时候,自相关噪声
走连续的几步才能得到验证,调整的周期也更长。
所以!不要再抱怨OU噪声没用了,只是你们不合适而已。你的环境可能不是惯性环境,即使是,也可能不用考虑离散时间的问题,即使离散时间小了,往往也可以增大离散时间的粒度解决。另外,大多数人不会将强化学习用于实际系统,也就跑跑仿真维持生活的样子(围笑)。4.实验
我们设计实验看看两种不同的探索噪声,在不同的离散化时间粒度(采样时间)下的表现。
任务:设定值跟踪(setpoints tracking)任务,使得系统(环境)的输出达到预先设定的目标值。
环境是一阶系统(也是惯性系统),输入输出都是一维,传递函数如下:
方案:DDPG算法,
训练时配合两种探索噪声,分别是高斯噪声和Ornstein-Uhlenbeck噪声。其中,高斯噪声
,而OU过程参数
. 二者的scale基本一致。
状态、动作都是1维。奖赏可以认为就是绝对误差,即
设定值减输出取绝对值后的相反数。
训练140回合,注意reward图中展示的是回报(一个回合内的累积奖赏)。
结果: (1)采样时间=0.04s图1. OU噪声实验结果(采用时间=0.04s)
图2.高斯噪声实验结果(采用时间=0.04s)
我们可以看到,当采样时间较小的时候(0.04s),DDPG采用OU噪声的结果是会比高斯噪声更好的。简便起见,我只展示一个random seed结果,线下换了seed结果类似。
(2)采样时间=0.1s图3. OU噪声实验结果(采用时间=0.1s)
图3. 高斯噪声实验结果(采用时间=0.1s)
结果显示,当采样时间扩大到0.1s的时候,
高斯噪声完全也可以完成任务,甚至训练到后期每个回合内的累积奖赏比OU噪声略微高一点点。这样就印证了之前的分析。
5.结论
相比于独立噪声,OU噪声适合于惯性系统,尤其是
时间离散化粒度较小的情况,此外,它可以保护实际系统,如机械臂。之所以大家觉得OU噪声没用,是因为强化学习benchmark都是仿真任务,而且往往都不用考虑时间离散化的问题。另外,即使遇到时间离散粒度小的问题,一般直接增大离散化粒度之后独立噪声也可以起到很好的效果。
参考
- ^https://arxiv.org/abs/1509.02971
- ^https://arxiv.org/abs/1802.09477
- ^http://web.math.ku.dk/~susanne/StatDiff/Overheads1b
- ^http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.696.1149&rep=rep1&type=pdf