1、写在前面
还记得以前刚开始学习AI的时候,遇到了梯度下降算法,一直对很多概念搞不清楚,包括后来很长的一段时间也不是很明白梯度下降的实现原理,看了很多博客文章都是一知半解,总是有很多疑惑不能搞清楚,而且绝大多数的文章都是生涩的数学公式推理,对于像我这样的数学渣渣来说,理解梯度下降的确有难度,所以前段时间又重新回顾了一下梯度下降算法,结合网上不同来源的资料的学习总结,写了这篇博客,希望对同样刚刚接触梯度下降算法的朋友有所帮助,当然这里只是为了更好的理解梯度下降算法,所以基本上没有书面用语,也希望看到这篇文章的朋友能够指出我理解错误的地方。
2、什么是梯度
说到梯度,都是一些生动的上山下山的例子,不过原谅我看了很多次,依然不能够理解梯度下降算法原理。首先给出百度百科的解释:梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模),那么要怎样来理解这句话呢,我们先来看看一个简单的例子:
y
=
x
2
y=x^2
y=x2,求导得
y
=
2
x
y=2x
y=2x,
z
=
x
2
+
y
2
z=x^2+y^2
z=x2+y2,求偏导得(
z
1
=
2
x
z_1=2x
z1=2x,
z
2
=
2
y
z_2=2y
z2=2y), 一次类推到多元函数,简单的理解这个向量就是梯度。
3、梯度下降算法的作用
我想如果对于第一次学习梯度下降算法的朋友来说,可能和我当初一样,不知道梯度下降是干什么用的,虽然很多地方都说是求最优解的,还有很多其他解释都还不太明白到底是什么,我最开始学习的时候是在学习线性回归算法的时候接触的梯度下降,我相信很多人在步入机器学习的大门的时候都是从回归算法开始的吧,我还误以为梯度下降算法和回归、KNN之类的机器学习算法一样呢。我们还是以最容易理解的线性归回为例,我们知道在回归算法当中有一个损失函数(损失函数不细说了),例子如下:
假设标签:
y
y
y,
预测值:
f
(
x
)
=
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
+
θ
3
x
3
f(x)=θ_0x_0+θ_1x_1+θ_2x_2+θ_3x_3
f(x)=θ0x0+θ1x1+θ2x2+θ3x3
那么我们就可以得到该样本的平方损失函数:
L
(
y
,
f
(
x
)
)
=
1
2
(
y
−
f
(
x
)
)
2
L(y,f(x))=\frac 12(y-f(x))^2
L(y,f(x))=21(y−f(x))2
我们可以看到这就是一个关于
θ
0
,
θ
1
,
θ
2
,
θ
3
θ_0,θ_1,θ_2,θ_3
θ0,θ1,θ2,θ3的2次函数,为了模型效果更好,也就是要让我们的损失函数值越小,最终就转化为了一个求解这个多元2次函数的极值,就像我们求
y
=
x
2
y=x^2
y=x2得最小值的时候,我们另其导函数为0,就可以求得
y
=
x
2
y=x^2
y=x2最小时
x
x
x的取值是0一样的。但是为什么不直接用这种梯度的方式来求解最优解呢?主要是因为在实际的机器学习当中,特征的维度都是很大的,直接计算的话要求穷逆矩阵,计算量太大,所以才有了梯度下降算法。
4、梯度下降的计算过程
为了简单起见,我们以一条2个特征维度的数据为例,来看看梯度下降的计算过程。
则该样本的假设函数:
f
(
x
)
=
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
f(x)=θ_0x_0+θ_1x_1+θ_2x_2
f(x)=θ0x0+θ1x1+θ2x2,
损失函数:
J
(
θ
)
=
1
2
(
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
−
y
)
2
J(θ)=\dfrac 12(θ_0x_0+θ_1x_1+θ_2x_2-y)^2
J(θ)=21(θ0x0+θ1x1+θ2x2−y)2,
梯度:
Δ
=
<
(
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
−
y
)
∗
x
0
,
(
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
−
y
)
∗
x
1
,
(
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
−
y
)
∗
x
2
>
\Delta=<(θ_0x_0+θ_1x_1+θ_2x_2-y)*x_0,(θ_0x_0+θ_1x_1+θ_2x_2-y)*x_1,(θ_0x_0+θ_1x_1+θ_2x_2-y)*x_2>
Δ=<(θ0x0+θ1x1+θ2x2−y)∗x0,(θ0x0+θ1x1+θ2x2−y)∗x1,(θ0x0+θ1x1+θ2x2−y)∗x2>,令
x
0
x_0
x0恒等于1,其实
θ
0
θ_0
θ0就是我们的截距项,假设这样一条样本数据,真实值是10,特征向量是
(
1
,
2
,
2
)
(1,2,2)
(1,2,2),则梯度为:
Δ
=
<
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
−
y
,
(
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
−
y
)
∗
2
,
(
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
−
y
)
∗
2
>
\Delta=<θ_0x_0+θ_1x_1+θ_2x_2-y,(θ_0x_0+θ_1x_1+θ_2x_2-y)*2,(θ_0x_0+θ_1x_1+θ_2x_2-y)*2>
Δ=<θ0x0+θ1x1+θ2x2−y,(θ0x0+θ1x1+θ2x2−y)∗2,(θ0x0+θ1x1+θ2x2−y)∗2>当然了
x
0
x_0
x0是我们添加的特征维度。搞明白以上公式以后我们来实际实现一遍梯度下降的过程。
第一步:随机初始化 θ θ θ值
θ
0
=
(
0
,
0
,
0
)
\boldsymbol\theta^0=(0,0,0)
θ0=(0,0,0),则损失函数值:
J
(
0
,
0
,
0
)
=
1
2
(
0
+
0
+
0
−
10
)
2
=
50
J(0,0,0)=\dfrac 12(0+0+0-10)^2=50
J(0,0,0)=21(0+0+0−10)2=50,
梯度:
Δ
0
=
<
0
+
0
+
0
−
10
,
(
0
+
0
+
0
−
10
)
∗
2
,
(
0
+
0
+
0
−
10
)
∗
2
>
=
<
−
10
,
−
20
,
−
20
>
\Delta^0=<0+0+0-10,(0+0+0-10)*2,(0+0+0-10)*2>=<-10,-20,-20>
Δ0=<0+0+0−10,(0+0+0−10)∗2,(0+0+0−10)∗2>=<−10,−20,−20>
第二步:进行梯度下降
设置步长
α
=
0.2
\alpha=0.2
α=0.2,当然了实际当中不可能取这么大的值。
θ
0
=
(
0
,
0
,
0
)
,
Δ
0
=
<
−
10
,
−
20
,
−
20
>
\theta^0=(0,0,0),\Delta^0=<-10,-20,-20>
θ0=(0,0,0),Δ0=<−10,−20,−20>,
J
(
θ
0
)
=
1
2
(
0
+
0
+
0
−
10
)
2
=
50
J(\theta^0)=\dfrac 12(0+0+0-10)^2=50
J(θ0)=21(0+0+0−10)2=50,
θ
1
=
θ
0
−
α
∗
Δ
0
=
(
0
,
0
,
0
)
−
0.2
∗
(
−
10
,
−
20
,
−
20
)
=
(
2
,
4
,
4
)
,
Δ
1
=
<
8
,
16
,
16
>
\theta^1=\theta^0-\alpha*\Delta^0=(0,0,0)-0.2*(-10,-20,-20)=(2,4,4),\Delta^1=<8,16,16>
θ1=θ0−α∗Δ0=(0,0,0)−0.2∗(−10,−20,−20)=(2,4,4),Δ1=<8,16,16>
J
(
θ
1
)
=
1
2
(
2
+
8
+
8
−
10
)
2
=
32
J(\theta^1)=\dfrac 12(2+8+8-10)^2=32
J(θ1)=21(2+8+8−10)2=32,
θ
2
=
θ
1
−
α
∗
Δ
1
=
(
1
,
2
,
2
)
−
0.2
∗
(
8
,
16
,
16
)
=
(
−
0.6
,
−
1.2
,
−
1.2
)
,
Δ
2
=
<
8.8
,
17.6
,
17.6
>
\theta^2=\theta^1-\alpha*\Delta^1=(1,2,2)-0.2*(8,16,16)=(-0.6,-1.2,-1.2),\Delta^2=<8.8,17.6,17.6>
θ2=θ1−α∗Δ1=(1,2,2)−0.2∗(8,16,16)=(−0.6,−1.2,−1.2),Δ2=<8.8,17.6,17.6>
J
(
θ
2
)
=
1
2
(
−
0.6
−
2.4
−
2.4
−
10
)
2
=
38.72
J(\theta^2)=\dfrac 12(-0.6-2.4-2.4-10)^2=38.72
J(θ2)=21(−0.6−2.4−2.4−10)2=38.72,
到了这一步,我们发现损失值变大了,说明我们的已经过了极小值点,所以我们把
α
\alpha
α值设置小一点。令
α
\alpha
α=0.01。
第三步:再次进行梯度下降
θ
0
=
(
0
,
0
,
0
)
,
Δ
0
=
<
−
10
,
−
20
,
−
20
>
\theta^0=(0,0,0),\Delta^0=<-10,-20,-20>
θ0=(0,0,0),Δ0=<−10,−20,−20>,
J
(
θ
0
)
=
1
2
(
0
+
0
+
0
−
10
)
2
=
50
J(\theta^0)=\dfrac 12(0+0+0-10)^2=50
J(θ0)=21(0+0+0−10)2=50,
θ
1
=
θ
0
−
α
∗
Δ
0
=
(
0
,
0
,
0
)
−
0.05
∗
(
−
10
,
−
20
,
−
20
)
=
(
0.5
,
1
,
1
)
,
Δ
1
=
<
−
5.5
,
−
11
,
−
11
>
\theta^1=\theta^0-\alpha*\Delta^0=(0,0,0)-0.05*(-10,-20,-20)=(0.5,1,1),\Delta^1=<-5.5,-11,-11 >
θ1=θ0−α∗Δ0=(0,0,0)−0.05∗(−10,−20,−20)=(0.5,1,1),Δ1=<−5.5,−11,−11>
J
(
θ
1
)
=
1
2
(
0.5
+
2
+
2
−
10
)
2
=
15.13
J(\theta^1)=\dfrac 12(0.5+2+2-10)^2=15.13
J(θ1)=21(0.5+2+2−10)2=15.13,
θ
2
=
θ
1
−
α
∗
Δ
1
=
(
0.5
,
1
,
1
)
−
0.05
∗
(
−
5.5
,
−
11
,
−
11
)
=
(
0.075
,
1.55
,
1.55
)
,
Δ
2
=
<
−
3.725
,
−
7.45
,
−
7.45
>
\theta^2=\theta^1-\alpha*\Delta^1=(0.5,1,1)-0.05*(-5.5,-11,-11)=(0.075,1.55,1.55),\Delta^2=<-3.725,-7.45,-7.45>
θ2=θ1−α∗Δ1=(0.5,1,1)−0.05∗(−5.5,−11,−11)=(0.075,1.55,1.55),Δ2=<−3.725,−7.45,−7.45>
J
(
θ
2
)
=
1
2
(
0.075
+
2
+
2
−
10
)
2
=
6.94
J(\theta^2)=\dfrac 12(0.075+2+2-10)^2=6.94
J(θ2)=21(0.075+2+2−10)2=6.94,
如此反复迭代下去,那什么时候停止呢?我们可以设置一个超参数
ξ
=
0.5
\xi=0.5
ξ=0.5(当然实际中
ξ
\xi
ξ值很小,例如 1e-5),也就是说当前步骤的梯度值与前一步骤的梯度值的距离小于
ξ
\xi
ξ的时候,停止计算。例如上面的
Δ
0
=
<
−
10
,
−
20
,
−
20
>
\Delta^0=<-10,-20,-20>
Δ0=<−10,−20,−20>,
Δ
1
=
<
−
5.5
,
−
11
,
−
11
>
\Delta^1=<-5.5,-11,-11 >
Δ1=<−5.5,−11,−11>,
∣
Δ
0
−
Δ
1
∣
=
<
4.5
,
9
,
9
>
|\Delta^0-\Delta^1|=<4.5,9,9>
∣Δ0−Δ1∣=<4.5,9,9>,所以要继续进行迭代,知道梯度值都小于
ξ
\xi
ξ时停止迭代。
总结(更新)
通过上述的计算过程,我们可以发现,越到后面,下降的就越慢,由于上述计算过程只是我举的例子,所以可能只需要迭代几次就可以到达停止条件,但是在实际当中,梯度下降需要迭代很多次,才能够到达损失函数的极小值点,当然这是基于一条数据进行梯度下降的,这种方式就叫随机梯度下降(SGD),如果我们用所有数据,就叫批量梯度下降(BGD),如果我们取小部分数据,就叫小批量梯度下降(MBGD)。一般来说在机器学习当中优先考虑SGD,在某些情况下(全局存在多个相对最优解),SGD有可能跳出某些小的最优解,虽然速度会慢点,当然所说的慢是指在相同数量的样本数据下,跑完所有样本所花费的时间,参数的更新速度肯定是SGD快的,因为每跑一条样本数据都会更新一次。BGD是一定能够得到局部最优解的,而在回归中是一定能够得到全局最优解。由于SGD每次都是一条样本对参数进行更新,从而导致模型对异常样本非常敏感,直接的表现就是参数会异常波动,而如果使用BGD参数更新又非常的慢,所以才有了MBGD,既保证了训练速度,也保证了模型准确率。