文章目录
梯度下降
在机器学习-李宏毅(2019) Machine Learning 01笔记中介绍过梯度下降法
Review:梯度下降
在回归问题的第三步中,需要解决下面的最优化问题:
θ
∗
=
arg
min
θ
L
(
θ
)
\theta^* = \arg \min_{\theta} L(\theta)
θ∗=argθminL(θ)
- L :loss function(损失函数)
-
θ
\theta
θ :parameters(参数(们))
假设 \thetaθ 有里面有两个参数 θ 1 \theta_1 θ1, θ 2 \theta_2 θ2随机选取初始值:
θ 0 = [ θ 1 0 θ 2 0 ] \theta^{0} = \begin{bmatrix} \theta^{0}_{1} \\ \theta ^{0}_{2} \end{bmatrix} θ0=[θ10θ20]
然后按图下所示的公式。迭代计算偏微分得到新的参数:分别计算初始点处,两个参数对
L
L
L 的偏微分,然后
θ
0
\theta^0
θ0减掉
η
\eta
η 乘上偏微分的值,得到一组新的参数。同理反复进行这样的计算。黄色部分为简洁的写法,
▽
L
(
θ
)
\triangledown L(\theta)
▽L(θ) 即为梯度。需要记住的是,梯度是一个向量。
Tip1:调整学习率
小心翼翼调整学习率
上左图表示四种大小的learning rate在loss function上的表现,learning rate从小到大依次为:蓝、红、绿、黄。可以看出,蓝色下降的较慢,但是给足够多的时间也可能到达最低点;红色刚刚好,又比蓝色快一点又能到达最低点。绿色下降太快,错过了最低点。黄色的学习率特别大,更离谱,更新参数的时候只会发现损失函数越更新越大。
如果参数超过两个,也就是三维以上后,无法得到左图这种可视化的loss function,但是可以得到右图。右图是不同学习率的情况下,参数更新和loss function值的关系。可以看到蓝色的损失函数的下降速度比较慢,也就是说找最低点的效率较低;绿色损失函数的下降速度比蓝色的要快,但是找到的最低点比蓝色曲线找到的要大,也就是跳过了最低点;黄色曲线就离谱,loss越来越大了;红色曲线是刚刚好,速度又快,又找到了最低点。
在找学习率的时候,要把右图画出来进行比较。
自适应学习率
-
举一个简单的思想:随着次数的增加,通过一些因子来减少学习率
-
通常刚开始,初始点会距离最低点比较远,所以使用大一点的学习率
-
update好几次参数之后呢,比较靠近最低点了,此时减少学习率
-
比如 η t = η t t + 1 \eta^t =\frac{\eta^t}{\sqrt{t+1}} ηt=t+1ηt, t t t是次数。随着次数的增加, η t \eta^t ηt减小
-
-
学习率不能是一个值通用所有特征,不同的参数需要不同的学习率
Adagrad算法
每个参数的学习率都把它除上之前微分的均方根。解释:
普通的梯度下降为:
w
t
+
1
←
w
t
−
η
t
g
t
w^{t+1} \leftarrow w^t -η^tg^t
wt+1←wt−ηtgt
η
t
=
η
t
t
+
1
\eta^t =\frac{\eta^t}{\sqrt{t+1}}
ηt=t+1ηt
-
w
w
w 是众多参数中的一个,
η
t
η^t
ηt是
w
w
w的学习率(每个参数都有自己的学习率,每一个参数都要分开来考虑)
Adagrad 可以做的更好:
w t + 1 ← w t − η t σ t g t w^{t+1} \leftarrow w^t -\frac{η^t}{\sigma^t}g^t wt+1←wt−σtηtgt
g t = ∂ L ( θ t ) ∂ w g^t =\frac{\partial L(\theta^t)}{\partial w} gt=∂w∂L(θt) - σ t \sigma^t σt :之前参数的所有微分的均方根,对于每个参数都是不一样的。
Adagrad举例
下图是
w
w
w的更新过程
将 Adagrad 的式子进行化简:
Adagrad存在的矛盾
在 Adagrad 中,有两个地方存在梯度。一个梯度在分子上,所以越大的时候,步伐应该越大,但下面分母也有梯度,又导致当梯度越大的时候,步伐会越小。
下图是一个直观的解释:
下面给一个正式的解释:
考虑一个一元二次函数 y = a x 2 + b x + c y = ax^2+bx+c y=ax2+bx+c。并且算出其斜率函数的绝对值。
假设初始点 x 0 x_0 x0,易知最低点为 − b 2 a -\dfrac {b}{2a} −2ab,理论上讲最佳的步伐就是 x 0 x_0 x0到最低点 − b 2 a -\dfrac {b}{2a} −2ab之间的距离 ∣ x 0 + b 2 a ∣ |x_0+\dfrac {b}{2a}| ∣x0+2ab∣,这样就直接一步到位了,也可以写成 ∣ 2 a x 0 + b 2 a ∣ |\dfrac {2ax_0+b}{2a}| ∣2a2ax0+b∣。而刚好分子 ∣ 2 a x 0 + b ∣ |2ax_0+b| ∣2ax0+b∣就是二次函数y在 x 0 x_0 x0处斜率的绝对值。
这样可以认为,一阶导的绝对值越大,那么理想的步长就应该也越大,当前点离最低点的距离也就越大。一阶导和理想步长成正比。
结论1-1:梯度越大,当前位置就跟最低点的距离越远。
这也之前的直觉是一样的,越陡的位置,离最低点可能越远。
但是这个结论在多个参数时就不一定成立了。
多参数下结论不一定成立
下面考虑两个参数: w 1 w_1 w1和 w 2 w_2 w2,颜色代表损失函数的值。如果只考虑 w 1 w_1 w1,即平行于 w 1 w_1 w1轴做一条线(图中的蓝线),得到右上的曲线。a点处, w 1 w1 w1对L的微分值比较大,其距离最低点也更远。
再同时考虑
w
2
w_2
w2,得到绿色的线。c点处,
w
2
w_2
w2对L的微分值比较大。
但是如果跨参数比较,用a处
w
1
w1
w1对L的微分值和c处
w
2
w_2
w2对L的微分值作比较,是得不到有效结果的。
所以结论1-1是在没有考虑跨参数对比的情况下,才能成立的。所以还不完善。
之前说到的最佳距离
∣
2
a
x
0
+
b
2
a
∣
\left | \frac{2ax_0+b}{2a} \right |
∣∣2a2ax0+b∣∣ ,还有个分母
2
a
2a
2a 。对function进行二次微分刚好可以得到:
∂
2
y
∂
x
2
=
2
a
\frac{\partial ^2y}{\partial x^2} = 2a
∂x2∂2y=2a
所以最好的步伐应该是和一次微分(一阶导数)的绝对值成正比和二次微分(二阶导数)成反比的:
∣
一
次
微
分
∣
二
次
微
分
\frac{|一次微分|}{二次微分}
二次微分∣一次微分∣
观察到a处,
w
1
w_1
w1对L的二次微分是比较小的,在b处,
w
2
w_2
w2对L的二次微分是比较大的。但是a处,
w
1
w_1
w1对L的一次微分也是比较小的,b处
w
2
w_2
w2对L的一次微分也是比较大的。如果要考虑a和c哪个点离得最低点近,应该用上述公式分别得到一个值去进行比较。
Adagrad 进一步的解释
再回到之前的 Adagrad,Adagrad采用的分子中有一项就是一次微分本身,但是分母却不是二次微分,感觉这个分母是用来代替二次微分的,但是为什么要这样做呢?并且这样做是否有效呢?
为什么要这样:
在实际情况中,确实可以直接计算二次微分并直接拿来做分母,但是往往计算二次微分会占用大量时间。Adagrad的思路是能不能在不增加计算量的前提下,还能估算出二次微分是多少。
为什么可以这样:
如下图所示,左边是一个二次微分比较小的曲线,右边是一个二次微分比较大的曲线。其下方是各自一次微分的曲线。如果单取一个点,比如让左边取a点,右边取c点,在不能直接算二次微分的情况下,得不到任何可以和二次微分有关的信息,单看一次微分,反而a点处的值比c点的要大。
但是如果在一个区域内取多个点,就可以看出一些趋势:蓝色曲线所代表的
w
1
w_1
w1对L的一次微分值一般是比较小的,而绿色曲线所代表的
w
2
w_2
w2对L一次微分值会大不少。
总结一下,这样做是用比较参数过去的在一个区域内的一次微分的均方根的大小来取代比较参数二次微分的大小。
Tip2:随机梯度下降法
之前回归的梯度下降:
L
=
∑
n
(
y
^
n
−
(
b
+
∑
w
i
x
i
n
)
)
2
L=\sum_n(\hat y^n-(b+\sum w_ix_i^n))^2
L=n∑(y^n−(b+∑wixin))2
θ
i
=
θ
i
−
1
−
η
▽
L
(
θ
i
−
1
)
\theta^i =\theta^{i-1}- \eta\triangledown L(\theta^{i-1})
θi=θi−1−η▽L(θi−1)
而随机梯度下降法更快:
损失函数不需要处理训练集所有的数据,只随机选取一个例子
x
n
x^n
xn,只算当前这个点的loss值:
L
n
=
(
y
^
n
−
(
b
+
∑
w
i
x
i
n
)
)
2
L^n=(\hat y^n-(b+\sum w_ix_i^n))^2
Ln=(y^n−(b+∑wixin))2
θ
i
=
θ
i
−
1
−
η
▽
L
n
(
θ
i
−
1
)
\theta^i =\theta^{i-1}- \eta\triangledown L^n(\theta^{i-1})
θi=θi−1−η▽Ln(θi−1)
(但是为什么这样可行,以及在代码上的区别还不知道,马克一下后面搞清楚)
Tip3:特征缩放
比如有个函数:
y
=
b
+
w
1
x
1
+
w
2
x
2
y=b+w_1x_1+w_2x_2
y=b+w1x1+w2x2
两个输入的分布的范围很不一样,建议把他们的范围缩放,使得不同输入的范围是一样的。本例中就是把
x
2
x_2
x2缩小。
这样做的原因是:
下图左边是
x
1
x_1
x1的scale比
x
2
x_2
x2要小很多(
x
1
x_1
x1取的1、2……比起
x
2
x_2
x2取的100、200来说非常小)所以当
w
1
w_1
w1和
w
2
w_2
w2做同样的变化时,
w
1
w_1
w1对
y
y
y 的变化影响是比较小的,
x
2
x_2
x2对
y
y
y 的变化影响是比较大的。
坐标系中是两个参数的error surface(现在考虑左边蓝色),因为
w
1
w_1
w1对 yy 的变化影响比较小,所以
w
1
w_1
w1对损失函数的影响比较小,
w
1
w_1
w1 对损失函数有比较小的微分,所以
w
1
w_1
w1 方向上是比较平滑的。同理
x
2
x
x_2x
x2x对 yy 的影响比较大,所以
x
2
x_2
x2对损失函数的影响比较大,所以在
x
2
x_2
x2 方向有比较尖的峡谷。
上图右边是两个参数scaling比较接近,右边的绿色图就比较接近圆形。
对于左边的情况,上面讲过这种狭长的情形不过不用Adagrad的话是比较难处理的,两个方向上需要不同的学习率,同一组学习率会搞不定它。而右边情形更新参数就会变得比较容易。左边的梯度下降并不是向着最低点方向走的,而是顺着等高线切线法线方向走的。但绿色就可以向着圆心(最低点)走,这样做参数更新也是比较有效率。而且右图的情况下,我觉得初始化参数的时候压力就会小一点,不管什么样的参数值在开始梯度下降后都是会向着圆心走。而对于左图,如果参数初始化选的有点歪,那么梯度下降的时候方向会一直调整,这样一来选初始化的参数就有些压力。
怎么做缩放?
方法非常多,这里举例一种常见的做法:
上图每一列都是一个例子,里面都有一组特征。
对每一个维度 i i i(绿色框)都计算平均数,记做 m i m_i mi;还要计算标准差,记做 σ i \sigma _i σi。
然后用第 rr 个例子中的第 i i i 个输入,减掉平均数 m i m_i mi,然后除以标准差 σ i σ \sigma _iσ σiσ,得到的结果是所有的维数都是 0 0 0,所有的方差都是 1 1 1。
梯度下降的理论基础
问题
当用梯度下降解决问题:
θ ∗ = arg min θ L ( θ ) \theta^∗= \underset{ \theta }{\operatorname{arg\ min}} L(\theta) θ∗=θarg minL(θ) 每次更新参数 θ \theta θ,都得到一个新的 θ \theta θ,它都使得损失函数更小。即:
L
(
θ
0
)
>
L
(
θ
1
)
>
L
(
θ
2
)
>
⋅
⋅
⋅
L(\theta^0) >L(\theta^1)>L(\theta^2)>···
L(θ0)>L(θ1)>L(θ2)>⋅⋅⋅
上述结论正确吗?
结论是不正确的。。。
数学理论
比如在
θ
0
\theta^0
θ0处,可以在一个小范围的圆圈内找到损失函数细小的
θ
1
\theta^1
θ1,不断的这样去寻找。
接下来就是如何在小圆圈内快速的找到最小值?
泰勒展开式
先介绍一下泰勒展开式
定义
若 h ( x ) h(x) h(x) 在 x = x 0 x=x_0 x=x0点的某个领域内有无限阶导数(即无限可微分,infinitely differentiable),那么在此领域内有:
h
(
x
)
=
∑
k
=
0
∞
h
k
(
x
0
)
k
!
(
x
−
x
0
)
k
=
h
(
x
0
)
+
h
′
(
x
0
)
(
x
−
x
0
)
+
h
′
′
(
x
0
)
2
!
(
x
−
x
0
)
2
+
⋯
\begin{aligned} h(x) &= \sum_{k=0}^{\infty }\frac{h^k(x_0)}{k!}(x-x_0)^k \\ & =h(x_0)+{h}'(x_0)(x−x_0)+\frac{h''(x_0)}{2!}(x−x_0)^2+⋯ \end{aligned}
h(x)=k=0∑∞k!hk(x0)(x−x0)k=h(x0)+h′(x0)(x−x0)+2!h′′(x0)(x−x0)2+⋯
当
x
x
x 很接近
x
0
x_0
x0时,有
h
(
x
)
≈
h
(
x
0
)
+
h
′
(
x
0
)
(
x
−
x
0
)
h(x)≈h(x_0)+{h}'(x_0)(x−x_0)
h(x)≈h(x0)+h′(x0)(x−x0) ,上式就是函数
h
(
x
)
h(x)
h(x) 在
x
=
x
0
x=x_0
x=x0点附近关于 xx 的幂函数展开式,也叫泰勒展开式。
举例:
图中4条蓝色线是把依次将第一项、前两项、前三项、前四项作图,橙色线是
s
i
n
(
x
)
sin(x)
sin(x)。
多变量泰勒展开式
回到之前如何快速在圆圈内找到最小值。基于泰勒展开式,在
(
a
,
b
)
(a,b)
(a,b) 点的红色圆圈范围内,可以将损失函数用泰勒展开式进行简化:
将问题进而简化为下图:
不考虑s的话,可以看出剩下的部分就是两个向量
(
△
θ
1
,
△
θ
2
)
(\triangle \theta_1,\triangle \theta_2)
(△θ1,△θ2)和
(
u
,
v
)
(u,v)
(u,v)的内积,那怎样让它最小,就是和向量
(
u
,
v
)
(u,v)
(u,v) 方向相反的向量。并且
∣
(
△
θ
1
,
△
θ
2
)
∣
|(\triangle \theta_1,\triangle \theta_2)|
∣(△θ1,△θ2)∣越大,这个值越小(因为是负值)。
然后将u和v带入。
发现最后的式子就是梯度下降的式子。但这里用这种方法找到这个式子有个前提,泰勒展开式给的损失函数的估算值是要足够精确的,而这需要红色的圈圈足够小(也就是学习率足够小)来保证。所以理论上每次更新参数都想要损失函数减小的话,即保证式
L
(
θ
)
≈
s
+
u
(
θ
1
−
a
)
+
v
(
θ
2
−
b
)
L(θ)≈s+u(θ_1−a)+v(θ_2−b)
L(θ)≈s+u(θ1−a)+v(θ2−b)成立的话,就需要学习率足够足够小才可以。
所以实际中,当更新参数的时候,如果学习率没有设好,是有可能上式是不成立的,所以导致做梯度下降的时候,损失函数没有越来越小。
上式只考虑了泰勒展开式的一次项,如果考虑到二次项(比如牛顿法),在实际中不是特别好,会涉及到二次微分等,多很多的运算,性价比不好。
梯度下降的限制
容易陷入局部极值 还有可能卡在不是极值,但微分值是0的地方 还有可能实际中只是当微分值小于某一个数值就停下来了,但这里只是比较平缓,并不是极值点
参考:梯度下降