码字不易,转载请注明出处~
tags: optimizer;AdaGrad
本文来源于下面博客:
https://medium.com/konvergen/an-introduction-to-adagrad-f130ae871827
前面讲到梯度下降法以及带动量的梯度下降法、NAG等,它们的一个共同的特点是都包含学习率 η \eta η这个参数,而这个参数的选择属于超参数的范围。个人感觉超参数包含了两方面的内容:1. 参数需要人工调整,不是一次设置之后系统自动处理;2. 对全局的影响相当大,不同的取值在一定程度上影响整体的效果。然而超参数的麻烦之处在于,它是需要人不断调整试优的,或大或小都可能导致网络无法达到最优解。更麻烦的是,对于神经网络而言,它本身需要解决的是一个高维的非凸优化问题,维度高达上百万维,极有可能在不同的维度上,某个参数比较适合而在另外一些维度上面,该参数就可能不适合了。对于学习率,面临的就是这种情况。因此,我们希望最好的情况是学习率能够根据网络训练样本的变化而自动调整,这样就省去了很多人为的工作,更重要的是,这样也许能够使网络自己找到最好的优化方向,而不是去地毯式搜索。
AdaGrad
该算法应对的就是在高维空间中,网络学习率在各个维度上面应该如何变化这个问题。公式如下:
(1)
θ
t
+
1
=
θ
t
−
η
ε
I
+
d
i
a
g
(
G
t
)
⋅
g
t
\theta_{t+1}=\theta_t-\frac{\eta}{\sqrt{\varepsilon I+diag(G_t)}}\cdot g_t\tag{1}
θt+1=θt−εI+diag(Gt)η⋅gt(1)
式中,
θ
\theta
θ是需要更新的权重参数,
η
\eta
η是初始化学习率,
ε
\varepsilon
ε是为了避免除0引入的因子,
I
I
I是单位矩阵,
g
t
g_t
gt是在t时刻所计算得到的梯度,公式如下:
(2)
g
t
=
1
n
∑
i
=
1
n
∇
θ
L
(
x
(
i
)
,
y
(
i
)
,
θ
t
)
g_t=\frac{1}{n}\sum_{i=1}^{n}\nabla_\theta L(x^{(i)}, y{(i)}, \theta_t)\tag{2}
gt=n1i=1∑n∇θL(x(i),y(i),θt)(2)
最关键的是
G
t
G_t
Gt矩阵,它表示到t时刻为止,所有之前和现在所累积的梯度信息,公式如下:
(3)
G
t
=
∑
τ
=
1
t
g
τ
g
τ
T
G_t=\sum_{\tau=1}^{t}g_\tau g_{\tau}^{T}\tag{3}
Gt=τ=1∑tgτgτT(3)
看着有点累人,感觉每次计算都要计算一个大矩阵。实际上,也的确如此。如果每次使用
G
t
G_t
Gt进行计算,那么势必会有很大的计算量,更何况还要进行矩阵的开方运算。所以,如果我们仅仅计算对角化的
G
t
G_t
Gt,情况就会好很多,毕竟对角阵有很好的性质,所有的操作都可以应用到每一个对角元素上面而无需增加额外的运算负担。这样就可以很容易进行参数更新了。
[
θ
t
+
1
(
1
)
θ
t
+
1
(
2
)
⋮
θ
t
+
1
(
m
)
]
=
[
θ
t
1
)
θ
t
(
2
)
⋮
θ
t
(
m
)
]
−
η
(
[
ε
0
⋯
0
0
ε
⋯
0
⋮
⋮
⋱
⋮
0
0
⋯
ε
]
+
[
G
t
(
1
,
1
)
0
⋯
0
0
G
t
(
2
,
2
)
⋯
0
⋮
⋮
⋱
⋮
0
0
⋯
G
t
m
,
m
]
)
−
1
/
2
⋅
[
g
t
(
1
)
g
t
(
2
)
⋮
g
t
(
m
)
]
\begin{bmatrix} \theta_{t+1}^{(1)} \\ \theta_{t+1}^{(2)} \\ \vdots \\ \theta_{t+1}^{(m)}\end{bmatrix}=\begin{bmatrix} \theta_t^{1)} \\ \theta_t^{(2)} \\ \vdots \\ \theta_t^{(m)}\end{bmatrix}-\eta {\begin{pmatrix}{\begin{bmatrix}&\varepsilon &0 &\cdots &0 \\ &0 &\varepsilon &\cdots &0 \\ &\vdots &\vdots &\ddots &\vdots \\ &0 &0 &\cdots &\varepsilon \end{bmatrix}}+\begin{bmatrix}&G_t^{(1, 1)} &0 &\cdots &0\\ &0 &G_t^{(2, 2)} &\cdots &0 \\ &\vdots &\vdots &\ddots &\vdots \\ &0 &0 &\cdots &G_t^{m, m} \end{bmatrix}\end{pmatrix}}^{-1/2} \cdot \begin{bmatrix} &g_t^{(1)}\\ &g_t^{(2)} \\&\vdots \\&g_t^{(m)} \end{bmatrix}
⎣⎢⎢⎢⎢⎡θt+1(1)θt+1(2)⋮θt+1(m)⎦⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎡θt1)θt(2)⋮θt(m)⎦⎥⎥⎥⎥⎤−η⎝⎜⎜⎜⎛⎣⎢⎢⎢⎡ε0⋮00ε⋮0⋯⋯⋱⋯00⋮ε⎦⎥⎥⎥⎤+⎣⎢⎢⎢⎡Gt(1,1)0⋮00Gt(2,2)⋮0⋯⋯⋱⋯00⋮Gtm,m⎦⎥⎥⎥⎤⎠⎟⎟⎟⎞−1/2⋅⎣⎢⎢⎢⎢⎡gt(1)gt(2)⋮gt(m)⎦⎥⎥⎥⎥⎤
还是看起来挺复杂的,其实只需要关注的是学习率更新这部分内容,所有可以进行适当的简化,就可以得到如下的式子:
[
θ
t
+
1
(
1
)
θ
t
+
1
(
2
)
⋮
θ
t
+
1
(
m
)
]
=
[
θ
t
1
)
θ
t
(
2
)
⋮
θ
t
(
m
)
]
[
η
ε
+
G
t
(
1
,
1
)
0
⋯
0
0
η
ε
+
G
t
(
2
,
2
)
⋯
0
⋮
⋮
⋱
⋮
0
0
⋯
η
ε
+
G
t
(
m
,
m
)
]
⋅
[
g
t
(
1
)
g
t
(
2
)
⋮
g
t
(
m
)
]
\begin{bmatrix} \theta_{t+1}^{(1)} \\ \theta_{t+1}^{(2)} \\ \vdots \\ \theta_{t+1}^{(m)} \end{bmatrix}= \begin{bmatrix} \theta_t^{1)} \\ \theta_t^{(2)} \\ \vdots \\ \theta_t^{(m)} \end{bmatrix} \begin{bmatrix} &\frac{\eta}{\sqrt{\varepsilon+G_t^{(1,1)}}} &0 &\cdots &0 \\ &0 &\frac{\eta}{\sqrt{\varepsilon+G_t^{(2,2)}}} &\cdots &0 \\ &\vdots &\vdots &\ddots &\vdots \\ &0 &0 &\cdots &\frac{\eta}{\sqrt{\varepsilon+G_t^{(m,m)}}}\end{bmatrix} \cdot \begin{bmatrix} &g_t^{(1)}\\ &g_t^{(2)} \\ &\vdots \\&g_t^{(m)} \end{bmatrix}
⎣⎢⎢⎢⎢⎡θt+1(1)θt+1(2)⋮θt+1(m)⎦⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎡θt1)θt(2)⋮θt(m)⎦⎥⎥⎥⎥⎤⎣⎢⎢⎢⎢⎢⎢⎡ε+Gt(1,1)η0⋮00ε+Gt(2,2)η⋮0⋯⋯⋱⋯00⋮ε+Gt(m,m)η⎦⎥⎥⎥⎥⎥⎥⎤⋅⎣⎢⎢⎢⎢⎡gt(1)gt(2)⋮gt(m)⎦⎥⎥⎥⎥⎤
最终,可以得到AdaGrad的表达式如下:
(4)
[
θ
t
+
1
(
1
)
θ
t
+
1
(
2
)
⋮
θ
t
+
1
(
m
)
]
=
[
θ
t
1
)
θ
t
(
2
)
⋮
θ
t
(
m
)
]
[
η
ε
+
G
t
(
1
,
1
)
g
t
(
1
)
η
ε
+
G
t
(
2
,
2
)
g
t
(
2
)
⋮
η
ε
+
G
t
(
m
,
m
)
g
t
(
m
)
]
\begin{bmatrix} \theta_{t+1}^{(1)} \\ \theta_{t+1}^{(2)} \\ \vdots \\ \theta_{t+1}^{(m)} \end{bmatrix}= \begin{bmatrix} \theta_t^{1)} \\ \theta_t^{(2)} \\ \vdots \\ \theta_t^{(m)} \end{bmatrix} \begin{bmatrix} &\frac{\eta}{\sqrt{\varepsilon+G_t^{(1,1)}}}g_t^{(1)} \\ &\frac{\eta}{\sqrt{\varepsilon+G_t^{(2,2)}}}g_t^{(2)}\\ &\vdots \\ &\frac{\eta}{\sqrt{\varepsilon+G_t^{(m,m)}}}g_t^{(m)}\end{bmatrix} \tag{4}
⎣⎢⎢⎢⎢⎡θt+1(1)θt+1(2)⋮θt+1(m)⎦⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎡θt1)θt(2)⋮θt(m)⎦⎥⎥⎥⎥⎤⎣⎢⎢⎢⎢⎢⎢⎢⎡ε+Gt(1,1)ηgt(1)ε+Gt(2,2)ηgt(2)⋮ε+Gt(m,m)ηgt(m)⎦⎥⎥⎥⎥⎥⎥⎥⎤(4)
对比之前文章中的随机梯度下降法:
(5)
[
θ
t
+
1
(
1
)
θ
t
+
1
(
2
)
⋮
θ
t
+
1
(
m
)
]
=
[
θ
t
1
)
θ
t
(
2
)
⋮
θ
t
(
m
)
]
[
η
g
t
(
1
)
η
g
t
(
2
)
⋮
η
g
t
(
m
)
]
\begin{bmatrix} \theta_{t+1}^{(1)} \\ \theta_{t+1}^{(2)} \\ \vdots \\ \theta_{t+1}^{(m)} \end{bmatrix}= \begin{bmatrix} \theta_t^{1)} \\ \theta_t^{(2)} \\ \vdots \\ \theta_t^{(m)} \end{bmatrix} \begin{bmatrix} &\eta g_t^{(1)} \\ &\eta g_t^{(2)} \\ &\vdots \\ &\eta g_t^{(m)} \\ \end{bmatrix} \tag{5}
⎣⎢⎢⎢⎢⎡θt+1(1)θt+1(2)⋮θt+1(m)⎦⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎡θt1)θt(2)⋮θt(m)⎦⎥⎥⎥⎥⎤⎣⎢⎢⎢⎢⎡ηgt(1)ηgt(2)⋮ηgt(m)⎦⎥⎥⎥⎥⎤(5)
可以看到,这里相当于每次在进行参数更新的时候,将
η
\eta
η缩放了
1
(
ε
+
G
t
)
\frac{1}{\sqrt(\varepsilon+G_t)}
(ε+Gt)1倍,而且由于
G
t
G_t
Gt每次都累加梯度,因此是发生变化的。这就看上去仿佛学习率是发生变化的。虽然事实上只是梯度
g
t
g_t
gt之前的因子发生了变化,我觉得这里应该理解为,学习率不变,只不过给学习率乘以了一个变化的变量,因此看上去好像学习率发生了变化。当然,如果把梯度之前的乘子看做是学习率,那理解为学习率变化也没什么问题。所以,AdaGrad的做法就是这样。
实际上,(3)中的公式也不太好理解,如果写成下面这样或许更直白易懂:
(6)
G
t
(
i
,
i
)
=
∑
τ
=
1
t
(
g
τ
(
i
)
)
2
G_t^{(i,i)}= \sum_{\tau=1}^{t}(g_\tau^{(i)})^2\tag{6}
Gt(i,i)=τ=1∑t(gτ(i))2(6)
那么参数的更新过程就可以写作:
(7)
θ
t
+
1
=
θ
t
−
η
ε
+
∑
g
t
2
⨀
g
t
\theta_{t+1}=\theta_t-\frac{\eta}{\sqrt{\varepsilon +\sum{g_t^2}}}\bigodot g_t\tag{7}
θt+1=θt−ε+∑gt2η⨀gt(7)
式中的矩阵乘积用了
⨀
\bigodot
⨀。之所以(3)写成那样,主要是为了理解实际上真实发生的是矩阵的的操作,而且缩放因子中的
G
G
G代表的是对角矩阵。
AdaGrad的特点
算法对于稀疏的数据所表现的性能更好,对于经常出现的特征,我们希望他们他们的学习率更新不要太快,而对不常出现的特征,则希望学习率更新快一些,从而能够让网络学习到的特征更好。但由于一般我们在网络学习之初就对每一次梯度进行了累积,所以当网络训练到一定程度的时候(不一定收敛),很容易导致网络没法继续学习,因为此时的学习率接近0。而这个问题需要进行进一步改进,也就是下面其他的自适应学习率方法所做的工作。
参考
- J. Duchi, E. Hazan, Y. Singer, “Adaptive Subgradient Methods for Online Learning and Stochastic Optimization” (2011)
- I. Goodfellow, Y. Bengio, A. Courville, “Deep Learning” (2016)