在机器学习中,有很多的问题并没有解析形式的解,或者有解析形式的解但是计算量很大(譬如,超定问题的最小二乘解),对于此类问题,通常我们会选择采用一种迭代的优化方式进行求解。
这些常用的优化算法包括:
梯度下降法(Gradient Descent)
,
共轭梯度法(Conjugate Gradient)
,
Momentum
算法及其变体,
牛顿法和拟牛顿法(包括L-BFGS)
,
AdaGrad
,
Adadelta
,
RMSprop
,
Adam
及其变体,
Nadam
。
梯度下降法(Gradient Descent)
想象你在一个山峰上,在不考虑其他因素的情况下,你要如何行走才能最快的下到山脚?当然是选择最陡峭的地方,这也是
梯度下降法
的核心思想:它通过每次在当前梯度方向(最陡峭的方向)向前“迈”一步,来逐渐逼近函数的最小值。
在第
n
n
梯度下降法根据每次求解损失函数
L
L
SGD的优缺点
优点
:操作简单,计算量小,在损失函数是凸函数的情况下能够保证收敛到一个较好的全局最优解。
缺点
:
-
α
α
是个定值(在最原始的版本),它的选取直接决定了解的好坏,过小会导致收敛太慢,过大会导致震荡而无法收敛到最优解。
-
对于非凸问题,只能收敛到局部最优,并且没有任何摆脱局部最优的能力(一旦梯度为0就不会再有任何变化)。
PS:对于非凸的优化问题,我们可以将其转化为对偶问题,对偶函数一定是凹函数,但是这样求出来的解并不等价于原函数的解,只是原函数的一个确下界
Momentum
SGD中,每次的步长一致,并且方向都是当前梯度的方向,这会收敛的不稳定性:无论在什么位置,总是以相同的“步子”向前迈。
Momentum的思想就是模拟物体运动的惯性:当我们跑步时转弯,我们最终的前进方向是由我们之前的方向和转弯的方向共同决定的。Momentum在每次更新时,保留
一部分上次的更新方向
:
Δ
θ
n
=
ρ
Δ
θ
n
−
1
+
g
n
−
1
Δθn=ρΔθn−1+gn−1
为学习率,同SGD。
优点
:一定程度上缓解了SGD收敛不稳定的问题,并且有一定的摆脱局部最优的能力(当前梯度为0时,仍可能按照上次迭代的方向冲出局部最优点),直观上理解,它可以让每次迭代的“掉头方向不是那个大“。左图为SGD,右图为Momentum。
图片来源于《An overview of gradient descent optimization algorithms》
缺点
:这里又多了另外一个超参数
ρ
ρ
需要我们设置,它的选取同样会影响到结果。
Nesterov Momentum
Nesterov Momentum又叫做Nesterov Accelerated Gradient(NAG),是基于Momentum的加速算法。
通过上述,我们知道,在每次更新的时候,都在
ρ
Δ
θ
n
−
1
+
L
′
(
θ
n
)
ρΔθn−1+L′(θn)
,因此可以加快收敛。
图片来自Hinton在Coursera上DL课程的slides
蓝色的线代表原始的Momentum更新方向,在NAG中,我们先求解得到了这个方向,也即棕色的线,然后求解此处的梯度(红色的线),从而得到最终的前进方向。
共轭梯度法(Conjugate Gradient)
同样的,CG也在选取前进方向上,对SGD做了改动。它对性能有很大的提升,但是不适用高维数据,求解共轭的计算量过大。网上有很多讲CG的,但是个人感觉都是从某一篇文献里面摘出来的几个图,这里推荐一个专门讲解CG的
painless conjugate gradient
,讲的很细致。
不同于上述算法对前进方向进行选择和调整,后面这些算法主要研究沿着梯度方向走多远的问题,也即如何选择合适的学习率
α
α
。
Adagrad
即adaptive gradient,自适应梯度法。它通过记录每次迭代过程中的前进方向和距离,从而使得针对不同问题,有一套自适应调整学习率的方法:
Δ
θ
n
=
1
∑
n
−
1
i
=
1
g
i
+
ϵ
−−−−−−−−−√
g
n
−
1
Δθn=1∑i=1n−1gi+ϵgn−1
是为了防止0除,一般取1e-7。
优点
:解决了SGD中学习率不能自适应调整的问题
缺点
:
- 学习率单调递减,在迭代后期可能导致学习率变得特别小而导致收敛及其缓慢。
-
同样的,我们还需要手动设置初始
α
α
Adagrad-like
在
《No More Pesky Learning Rates》
一文中,提到另外一种利用了
二阶导
信息的类adagrad算法。它是由Schaul于2012年提出的,使用了如下形式的更新公式:
Δ
θ
n
=
1
|
d
i
a
g
(
H
n
)
|
∗
(
∑
n
−
1
i
=
n
−
t
g
i
)
2
∑
n
−
1
i
=
n
−
t
g
2
i
g
n
−
1
Δθn=1|diag(Hn)|∗(∑i=n−tn−1gi)2∑i=n−tn−1gi2gn−1
优点
:缓解了Adagrad中学习率单调递减的问题
缺点
:Hession矩阵的计算必须采用较好的近似解,其次t也成为了新的超参数需要手动设置,即我们需要保留参数前多少个梯度值用来缩放学习率。
Adadelta
Adadelta在
《ADADELTA: An Adaptive Learning Rate Method 》
一文中提出,它解决了Adagrad所面临的问题。定义:
R
M
S
[
g
]
n
=
E
[
g
2
]
n
+
ϵ
−−−−−−−−√
RMS[g]n=E[g2]n+ϵ
会因为累乘一个小于1的数而逐渐减小,即使用了一种自适应的方式,让
距离当前越远的梯度的缩减学习率的比重越小
。分子是为了单位的统一性,其实上述的算法中,左右的单位是不一致的,为了构造一致的单位,我们可以模拟牛顿法(一阶导\二阶导),它的单位是一致的,而分子就是最终推导出的结果,具体参考上面那篇文章。这样,也解决了Adagrad初始学习率需要人为设定的问题。
优点
:完全自适应全局学习率,加速效果好
缺点
:后期容易在小范围内产生震荡
RMSprop
其实它就是Adadelta,这里的RMS就是Adadelta中定义的RMS,也有人说它是一个特例,
ρ
=
0.5
ρ=0.5
,即仍然依赖于全局学习率。
Adam
Adam是Momentum和Adaprop的结合体,我们先看它的更新公式:
E
[
g
2
]
n
=
ρ
E
[
g
2
]
n
−
1
+
(
1
−
ρ
)
g
2
n
E[g2]n=ρE[g2]n−1+(1−ρ)gn2
它利用误差函数的一阶矩估计和二阶矩估计来约束全局学习率。
优点
:结合Momentum和Adaprop,稳定性好,同时相比于Adagrad,不用存储全局所有的梯度,适合处理大规模数据
一说,adam是世界上最好的优化算法,不知道用啥时,用它就对了。
详见
《Adam: A Method for Stochastic Optimization》
Adamax
它是Adam的一个变体,简化了二阶矩估计的取值:
E
[
g
2
]
n
=
max
(
|
g
n
|
,
E
[
g
2
]
n
−
1
∗
ρ
)
E[g2]n=max(|gn|,E[g2]n−1∗ρ)
θ
n
:=
θ
n
−
1
−
α
E
[
g
]
n
¯
E
[
g