AdaDelta算法
提出动机
除了RMSProp算法以外,AdaDelta算法的提出也是为了解决AdaGrad算法在迭代后期较难找到有用解的问题。
算法
AdaDelta算法也像RMSProp算法一样,使用了小批量随机梯度 g t g_t gt按元素平方的指数加权移动平均变量 s t s_t st,这里的 ρ \rho ρ类似RMSProp中的 γ \gamma γ。但有意思的是,AdaDelta算法没有学习率这一超参数。另外,AdaDelta算法还维护一个额外的状态变量 Δ x t \Delta x_t Δxt,其元素同样在时间步0时被初始化为0。
对每次迭代做如下改动
s
t
=
ρ
s
t
−
1
+
(
1
−
ρ
)
g
t
∘
g
t
g
t
′
=
Δ
x
t
−
1
+
ϵ
s
t
+
ϵ
∘
g
t
x
t
=
x
t
−
1
−
g
t
′
Δ
x
t
=
ρ
Δ
x
t
−
1
+
(
1
−
ρ
)
g
t
′
∘
g
t
′
s_t = \rho s_{t-1} + (1-\rho) g_t \circ g_t \\\\ g_t' = \sqrt{\frac{\Delta x_{t-1}+\epsilon}{s_t+\epsilon}} \circ g_t\\\\ x_t = x_{t-1} - g_t' \\\\ \Delta x_{t} = \rho \Delta x_{t-1} + (1-\rho) g_t' \circ g_t'
st=ρst−1+(1−ρ)gt∘gtgt′=st+ϵΔxt−1+ϵ∘gtxt=xt−1−gt′Δxt=ρΔxt−1+(1−ρ)gt′∘gt′
可以看到,如不考虑
ϵ
\epsilon
ϵ的影响,AdaDelta算法与RMSProp算法的不同之处在于使用
Δ
x
t
−
1
\sqrt{\Delta x_{t−1}}
Δxt−1来替代超参数
η
\eta
η。
ρ
\rho
ρ的取值一般在
[
0.9
,
0.99
]
[0.9,0.99]
[0.9,0.99]。
代码实现
def init_adadelta_states(dim=2):
s_w = np.zeros((dim, 1))
s_b = np.zeros(1)
delta_w = np.zeros((dim, 1))
delta_b = np.zeros(1)
return (s_w, delta_w), (s_b, delta_b)
def adagrad(params, states, hyperparams, eps=1e-5):
rho = hyperparams['rho']
for p, (s,delta) in zip(params, states):
s[:] += rho * s + (1 - rho) * p.grad * p.grad
g = (math.sqrt(delta + eps) / (math.sqrt(s + eps)) * p.grad
p[:] -= g
delta[:] = rho * delta + (1 - rho) * g * g