程式語言:Python
- Package:
- numpy
- namedtuple
簡介:Ornstein Uhlenbeck Process 常用於 DDPG
$$
\begin{align*}
X_{n+1} &= X_n + \theta (\mu - X_n)\Delta t + \sigma \Delta W_n \\
W_{t_{n+1}}-W_{t_n} &= \Delta W_n \sim N(0,\Delta t) = \sqrt{\Delta t} \space N(0,1) \\
\\
\mathbb{E}(X_t)&=X_0e^{-\theta t}+\mu(1-e^{-\theta t})\\
cov(X_s,X_t)&=\frac{\sigma^2}{2\theta}(e^{-\theta|t-s|}-e^{-\theta|t+s|})\\
\end{align*}
$$
- 隨機且連續的過程,但長時間來看會徘徊於 \(\mu\)
- 參數意義
- \(\theta\):拉回到 \(mu\) 的力道,值越大越會在 \(\mu\) 旁徘徊,也就是漂移越小
- \(\mu\):中心平均值
- \(\Delta t\):變化的時間間隔
- \(\sigma\):隨機的強度,值越大隨機範圍越大
- DDPG 可用的參數,習慣範圍落在 [-1, 1] 之間,再乘上動作最大值
import numpy as np
from collections import namedtuple
class OrnsteinUhlenbeckNoise:
"""
A Ornstein Uhlenbeck action noise, this is designed to aproximate brownian motion with friction.
Based on http://math.stackexchange.com/questions/1287634/implementing-ornstein-uhlenbeck-in-matlab
:param dim: (tuple) the dimension of the noise
:param mu: (float) the mean of the noise
:param theta: (float) the rate of mean reversion, affect converge
:param sigma: (float) the scale of the noise, affect random
:param dt: (float) the timestep for the noise
"""
def __init__(self, dim, mu=0, theta=0.15, sigma=0.2, dt=1.0):
self.dim = dim
self.mu = mu
self.theta = theta
self.sigma = sigma
self.dt = dt
self.X = np.ones(self.dim) * self.mu
def reset(self):
self.X = np.ones(self.dim) * self.mu
def __call__(self):
drift = self.theta * (self.mu - self.X) * self.dt
random = self.sigma * self._delta_wiener()
self.X = self.X + drift + random
return self.X
def _delta_wiener(self):
return np.sqrt(self.dt) * np.random.randn(self.dim)
if __name__ == "__main__":
Parameter = namedtuple("Parameter", ["theta", "mu", "dt", "sigma"])
pars = [
# theta
Parameter(1, 0, 1, 1),
Parameter(1e-2, 0, 1, 1),
# mu
Parameter(1, 0, 1, 1),
Parameter(1, 10, 1, 1),
# dt
Parameter(1, 0, 1, 1),
Parameter(1, 0, 1e-2, 1),
# sigma
Parameter(1, 0, 1, 1),
Parameter(1, 0, 1, 1e-2),
# DDPG
Parameter(0.15, 0, 1, 0.2),
Parameter(0.15, 0, 1e-2, 0.3),
]
t = np.linspace(0, 10000, 10000)
ys = []
for par in pars:
noise = OrnsteinUhlenbeckNoise(
1, mu=par.mu, dt=par.dt, theta=par.theta, sigma=par.sigma
)
ys.append([noise() for _ in t])
import matplotlib.pyplot as plt
fig, ax = plt.subplots(nrows=len(ys), sharex=True)
fig.suptitle(
"$X_{n+1} = X_n + \\theta (\mu - X_n)\Delta t + \sigma \Delta W_n$", fontsize=16
)
for i, y in enumerate(ys):
ax[i].set_title(
f"$\\theta={pars[i].theta:.2f}, \mu={pars[i].mu:.2f}, \Delta t={pars[i].dt:.2f}, \sigma={pars[i].sigma:.2f}$"
)
ax[i].plot(t, y)
fig.subplots_adjust(top=0.85, hspace=0.9)
plt.show()
參考
Implementing Ornstein–Uhlenbeck in Matlab
Wiki Ornstein–Uhlenbeck process
留言
張貼留言