梯度下降回顾
在前篇文章中介绍的机器学习三步走第三步中,我们需要解决下面优化问题:
θ ∗ = a r g min θ L ( θ ) \theta^*=arg\,\min_{\theta}L(\theta) θ∗=argminθL(θ)
假设 θ \theta θ向量有两个属性 { θ 1 , θ 2 } \{\theta_1,\theta_2\} {θ1,θ2}
初始从 θ 0 \theta^0 θ0开始,
θ 0 = [ θ 1 0 θ 2 0 ] \theta^0 =\left[ \begin{matrix} \theta^0_1 \\ \theta^0_2 \end{matrix} \right] θ0=[θ10θ20]
接下来计算
[ θ 1 1 θ 2 1 ] = [ θ 1 0 θ 2 0 ] − η [ ∂ L ( θ 1 0 ) / ∂ θ 1 ∂ L ( θ 2 0 ) / ∂ θ 2 ] \left[ \begin{matrix} \theta^1_1 \\ \theta^1_2 \end{matrix} \right] = \left[ \begin{matrix} \theta^0_1 \\ \theta^0_2 \end{matrix} \right] -\eta \left[ \begin{matrix} \partial L(\theta_1^0) / \partial \theta_1 \\ \partial L(\theta_2^0) / \partial \theta_2\end{matrix} \right] [θ11θ21]=[θ10θ20]−η[∂L(θ10)/∂θ1∂L(θ20)/∂θ2]
这个步骤可以反复进行,再计算一次的话:
[
θ
1
2
θ
2
2
]
=
[
θ
1
1
θ
2
1
]
−
η
[
∂
L
(
θ
1
1
)
/
∂
θ
1
∂
L
(
θ
2
1
)
/
∂
θ
2
]
\left[ \begin{matrix} \theta^2_1 \\ \theta^2_2 \end{matrix} \right] = \left[ \begin{matrix} \theta^1_1 \\ \theta^1_2 \end{matrix} \right] -\eta \left[ \begin{matrix} \partial L(\theta_1^1) / \partial \theta_1 \\ \partial L(\theta_2^1) / \partial \theta_2\end{matrix} \right]
[θ12θ22]=[θ11θ21]−η[∂L(θ11)/∂θ1∂L(θ21)/∂θ2]
其中
η
\eta
η是初始学习率(learning rate)
上面的式子可以写得更加简洁:
∇
L
(
θ
)
=
[
∂
L
(
θ
1
)
/
∂
θ
1
∂
L
(
θ
2
)
/
∂
θ
2
]
\nabla L(\theta) = \left[ \begin{matrix} \partial L(\theta_1) / \partial \theta_1 \\ \partial L(\theta_2) / \partial \theta_2\end{matrix} \right]
∇L(θ)=[∂L(θ1)/∂θ1∂L(θ2)/∂θ2]
∇
L
(
θ
)
\nabla L(\theta)
∇L(θ)叫做梯度。
也就是说:
[ θ 1 1 θ 2 1 ] = [ θ 1 0 θ 2 0 ] − η [ ∂ L ( θ 1 0 ) / ∂ θ 1 ∂ L ( θ 2 0 ) / ∂ θ 2 ] ⟹ θ 1 = θ 0 − η ∇ L ( θ 0 ) \left[ \begin{matrix} \theta^1_1 \\ \theta^1_2 \end{matrix} \right] = \left[ \begin{matrix} \theta^0_1 \\ \theta^0_2 \end{matrix} \right] -\eta \left[ \begin{matrix} \partial L(\theta_1^0) / \partial \theta_1 \\ \partial L(\theta_2^0) / \partial \theta_2\end{matrix} \right] \Longrightarrow \theta^1 = \theta^0 - \eta \nabla L(\theta^0) [θ11θ21]=[θ10θ20]−η[∂L(θ10)/∂θ1∂L(θ20)/∂θ2]⟹θ1=θ0−η∇L(θ0)
红色箭头是梯度向量,蓝色箭头是移动的方向。
小心的调整学习率
每种颜色都是不同的学习率。
如果学习率刚刚好,就像红色箭头所示;如果过小则向蓝色箭头,显得步长太小了;
若太大则像绿色箭头,那么永远到不了低点;甚至还可以过大,导致像黄色箭头那样。
如果是参数是一维或二维我们还可以画出这种图,如果参数超过3就没办法了。
我们还可以通过参数的变化来观察损失的变化。
可以通过观察损失函数的下降速度
x轴是学习率,y轴是Loss函数的值
因此学习率的调整很重要,简单的原则是:
- 开始时由于远离目标,因此使用大一点的学习率
- 在几次更新后,靠近目标了,因此减小学习率
- 每个参数给不同的学习率
比如可以选择 η t = η / t + 1 \eta^t = \eta / \sqrt{t +1} ηt=η/t+1,其中 t t t是计算的次数,但是这样还不够。
接下来介绍一种比较好的梯度下降算法:Adagrad。
Adagrad
每个参数的学习率都除上之前算出来的微分值的均方根。
一般的梯度下降(批梯度下降,Vanilla Gradient descent)是这样的:
w
t
+
1
←
w
t
−
η
t
g
t
w^{t+1} \leftarrow w^t - \eta^t g^t
wt+1←wt−ηtgt 其中
w
w
w是某一个参数,因为在做adagrad时,每个参数都有不同的学习率。
所以我们分别考虑每个参数。
η
t
=
η
t
+
1
,
g
t
=
∂
L
(
θ
t
)
∂
w
\eta^t = \frac{\eta} {\sqrt{t +1}},g^t = \frac{\partial L(\theta ^t)}{\partial w}
ηt=t+1η,gt=∂w∂L(θt)
而Adagrad的做法是:
w t + 1 ← w t − η t σ t g t w^{t+1} \leftarrow w^t - \frac{\eta^t}{\sigma^t}g^t wt+1←wt−σtηtgt
σ t \sigma^t σt是过去所有微分值的均方根。这个值对每个参数而言都是不一样的,因此是参数独立的。
我们来举个例子,假设初值为 w 0 w^0 w0。
整个Adagrad的式子式是可以简化的:
再回头来看下批梯度下降算法:
批梯度下降算法是梯度越大,步伐就越大;
而Adagrad是分子上,梯度越大,步伐越大;分母上,梯度越大,步伐越小。这里是否感觉有些矛盾。
我们来考虑一个二次函数: y = a x 2 + b x + c y = ax^2 + bx + c y=ax2+bx+c,它的图像如下:
把上式对 x x x做微分并取绝对值,得
∣
∂
y
∂
x
∣
=
∣
2
a
x
+
b
∣
|\frac{\partial y}{\partial x}| = |2ax + b|
∣∂x∂y∣=∣2ax+b∣
它的图形为:
在二次函数上,假设初始点为 x 0 x_0 x0,最低点是 − b 2 a -\frac{b}{2a} −2ab此时如果想找到最好的步伐多少
其实 x 0 x_0 x0和 − b 2 a -\frac{b}{2a} −2ab之间的距离 ∣ x 0 + b 2 a ∣ |x_0 + \frac{b}{2a}| ∣x0+2ab∣,整理一下可得 ∣ 2 a x 0 + b ∣ 2 a \frac{|2ax_0 + b|}{2a} 2a∣2ax0+b∣
而 ∣ 2 a x 0 + b ∣ |2ax_0 + b| ∣2ax0+b∣就是 x 0 x_0 x0点的一次微分。
如果某点的微分值越大,则距离最低点越远;如果踏出去的步伐和微分大小成正比,则有可能是最好的步伐。
上面我们只考虑了一个参数,如果考虑多个参数上面的结论则不一定成立。
假设有两个参数,如果只考虑参数1,它的图像为:
其中a点的微分值大于b点,a点距离最低点更远。如果也考虑参数 w 2 w_2 w2,它的图像是绿色的那个:
那,如果同时考虑这两个参数,如果同时考虑a点对
w
1
w_1
w1的微分,c点对
w
2
w_2
w2的微分。
c点处的微分值比较大,a点处的微分值小于它,但是c离低点比a离低点更近。
我们再回头看下最好的微分 ∣ 2 a x 0 + b ∣ 2 a \frac{|2ax_0 + b|}{2a} 2a∣2ax0+b∣,发现它的分母上有个 2 a 2a 2a。
我们把函数做二次微分得: ∂ 2 y ∂ x 2 = 2 a \frac{\partial^2y}{\partial x^2} = 2a ∂x2∂2y=2a
也就是说,最好的步伐,它不仅和一次微分成正比,还和二次微分成反比。
那它和Adagrad的关系是什么?
我们再来看下adagrad: g t g^t gt就是一次微分,那么它的分母是怎么和二次微分关联的呢?(derivative,导数)
adagrad用一次微分来估计二次微分:
我们考虑二次微分较小的图形(图左)和二次微分较大的图形(图右)。
然后把它们一次微分 ( 一 次 微 分 ) 2 \sqrt{(一次微分)^2} (一次微分)2的图形考虑进来:
我们在一次微分图形上取很多个点,可以发现在二次微分较小的图形中,它的一次微分通常也较小。
而Adagrad中的
∑
i
=
0
t
(
g
i
)
2
\sqrt{\sum_{i=0}^t(g^i)^2}
∑i=0t(gi)2就反映了二次微分的大小。
通过Adagrad实现梯度下降的代码:
def gradient_descent():
x_data = [338, 333, 328, 207, 226, 25, 179, 60, 208, 606]
y_data = [640, 633, 619, 393, 428, 27, 193, 66, 226, 1591]
b = -120
w = -4
lr = 1 # 学习率
lr_b = 0 # b的学习率
lr_w = 0 # w的学习率
iteration = 10000 #迭代次数
for i in range(iteration):
b_grad = 0.0
w_grad = 0.0
for n in range(len(x_data)):
w_grad = w_grad - 2.0 * (y_data[n] - (b + w * x_data[n])) * x_data[n]
b_grad = b_grad - 2.0 * (y_data[n] - (b + w * x_data[n])) * 1.0
lr_b = lr_b + b_grad ** 2
lr_w = lr_w + w_grad ** 2
b = b - lr/np.sqrt(lr_b) * b_grad
w = w - lr/np.sqrt(lr_w) * w_grad
print(b,w)
随机梯度下降法
随机梯度下降法( Stochastic Gradient Descent)可以训练的更快。
上篇文章中说到回归的损失函数为:
L
=
∑
n
(
y
^
n
−
(
b
+
∑
w
i
x
i
n
)
)
2
θ
i
=
θ
i
−
1
−
η
∇
L
(
θ
i
−
1
)
L = \sum_{n}(\hat{y}^n -(b + \sum w_ix_i^n))^2 \\ \theta^i = \theta^{i-1} - \eta\nabla L(\theta^{i-1})
L=n∑(y^n−(b+∑wixin))2θi=θi−1−η∇L(θi−1)
损失考虑了所有的训练数据。
而随机梯度下降法,每次只取某一个训练数据 x n x^n xn出来:
而损失值只考虑现在的参数对该训练数据的的估测值减去实际值:
L n = ( y ^ n − ( b + ∑ w i x i n ) ) 2 θ i = θ i − 1 − η ∇ L n ( θ i − 1 ) L^n = (\hat{y}^n -(b + \sum w_ix_i^n))^2 \\ \theta^i = \theta^{i-1} - \eta\nabla L^n(\theta^{i-1}) Ln=(y^n−(b+∑wixin))2θi=θi−1−η∇Ln(θi−1)
并且计算梯度的时候也只计算只针对该训练数据 x n x^n xn计算。
左边看完20个训练数据才更新损失值,右边每看一个训练数据,就更新一次损失值。
特征缩放
假设要根据以下函数做回归
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要大,就需要把 x 2 x_2 x2的分布缩小,让它们一致。
举例来说
如果
x
1
x_1
x1的分布是1,2,… 而
x
2
x_2
x2的分布是 100,200,…
那么画出的损失值的图形是图左的样子;
如果进行缩放后,图形是正圆,很容易向着圆心走。可以极大提高算法的效率。
特征缩放的方法
对每个维度,计算该维度的均值 m i = ∑ x i r R m_i = \frac{\sum x^r_i}{R} mi=R∑xir和标准差 σ i = ∑ ( x i r − m i ) 2 R \sigma_i = \sqrt{\frac{\sum(x_i^r-m_i)^2}{R}} σi=R∑(xir−mi)2