一、简介
梯度下降法是机器学习中最为基础和常用的算法之一,其核心思想是通过求梯度的方法来找到代价函数的最小值,从而解决相应的拟合或者分类问题。而要想理解梯度下降算法,首先应该了解什么是代价函数。
二、代价函数
代价函数本质来说就是用来表示拟合函数的理想输出与实际输出之间的差距的一种函数。也就是说差距越大,算法学习的代价也就越大,所以梯度下降法的本质也就是不断地优化代价函数。
1、平方差代价函数
解决回归问题中常用的一种代价函数,我习惯称它为平方差代价函数,它的形式其实十分简单,如下:
J
(
θ
)
=
1
m
∑
i
=
1
m
[
1
2
(
h
θ
(
x
)
−
y
)
2
]
J(\theta)=\frac{1}{m}\sum_{i=1}^m[\frac{1}{2}(h_\theta(x)-y)^2]
J(θ)=m1i=1∑m[21(hθ(x)−y)2]
其中m问样本数量,而
h
θ
(
x
)
h_\theta(x)
hθ(x)为我们拟合的实际输出,而
y
y
y代表我们期望的输出。看着这个形式是不是很像误差的计算呢!
平方差代价函数的问题在于,它在运用在Logistic算法时,会出现局部最优解的情况,所以在我们运用梯度下降法进行优化时有时会很不幸地陷入最优解,影响我们的拟合效果。为什么平方差代价函数会有局部最优解呢?这在于
h
θ
(
x
)
h_\theta(x)
hθ(x)这一项,在Logistic算法中,
h
θ
(
x
)
h_\theta(x)
hθ(x)是要套在一个Sigmoid函数中的,也就是激活函数,Sigmoid函数的表达式如下:
S
i
g
m
o
i
d
(
x
)
=
1
1
+
e
−
x
Sigmoid(x)= \frac{1}{1+e^{-x}}
Sigmoid(x)=1+e−x1
它的图像为:
在这个函数的作用下,平方差代价函数的图像便不再是一个单纯的凸函数,而是可能成为下面的这种情况:
所以产生了许多局部最优解。
2、交叉熵代价函数
为了让梯度下降算法能够很好地找到代价函数的全局最优解,我们采用一种性能比较好的代价函数,它就是交叉熵代价函数。
它的表达式为:
J
(
θ
)
=
{
−
l
o
g
(
h
θ
(
x
)
)
i
f
y
=
1
−
l
o
g
(
1
−
h
θ
(
x
)
)
i
f
y
=
0
J(\theta)=\left\{ \begin{aligned} &-log (h_\theta(x)) \qquad if\quad y=1 \\ &-log(1-h_\theta(x))\qquad if\quad y=0 \end{aligned} \right.
J(θ)={−log(hθ(x))ify=1−log(1−hθ(x))ify=0
这个表达式其实也还不算复杂,而且有一种更简洁的书写方式就是把分段函数合在一个式子里写,如下:
J
(
θ
)
=
−
(
1
−
y
)
l
o
g
(
1
−
h
θ
(
x
)
)
−
y
l
o
g
(
h
θ
(
x
)
)
J(\theta)=-(1-y)log(1-h_\theta(x))-ylog (h_\theta(x))
J(θ)=−(1−y)log(1−hθ(x))−ylog(hθ(x))
当y=1时,这个式子的第一项为零,也就变成了分段函数的第一段。当y=0时,第二项为0,也就变成了分段函数的第二段。
考虑到m个样本的情况,我们把代价函数写成如下的形式:
J
(
θ
)
=
−
1
m
∑
i
=
1
m
[
(
1
−
y
)
l
o
g
(
1
−
h
θ
(
x
)
)
+
y
l
o
g
(
h
θ
(
x
)
)
]
J(\theta)=-\frac{1}{m}\sum_{i=1}^m[(1-y)log(1-h_\theta(x))+ylog (h_\theta(x))]
J(θ)=−m1i=1∑m[(1−y)log(1−hθ(x))+ylog(hθ(x))]
这个函数的图像就很好的变成了凸函数,如下:
这样我们就免受局部最优解的干扰了,可以开开心心地使用梯度下降算法了!
三、梯度下降算法
梯度下降算法的核心在于梯度两个字,而求梯度的意思实际上就是对代价函数求偏导,然后用我们求得的导数去更新我们的拟合参数。
假如我们现在要拟合一条斜线:
h
θ
(
x
)
=
θ
0
+
θ
1
x
h_\theta(x)=\theta_0+\theta_1x
hθ(x)=θ0+θ1x
我们给出我们拟合的初值:
θ
0
=
0
,
θ
1
=
0
\theta_0=0,\theta_1=0
θ0=0,θ1=0
代价函数再写一遍:
J
(
θ
)
=
1
m
∑
i
=
1
m
[
1
2
(
h
θ
(
x
)
−
y
)
2
]
J(\theta)=\frac{1}{m}\sum_{i=1}^m[\frac{1}{2}(h_\theta(x)-y)^2]
J(θ)=m1i=1∑m[21(hθ(x)−y)2]
因为有两个参数,所以代价函数里面也有两个参数。
我们第一步要做的就是对这个代价函数进行求导运算了:
∂
J
∂
θ
j
=
1
m
∑
i
=
1
m
[
(
h
θ
(
x
)
)
−
y
)
x
]
\frac{\partial J}{\partial \theta_j}=\frac{1}{m} \sum_{i=1}^m[(h_\theta(x))-y)x]
∂θj∂J=m1i=1∑m[(hθ(x))−y)x]
这里的
x
x
x代表相应样本的输入,
y
y
y代表相应样本的期望输出,这个导数的计算其实就是一个偏导数的计算,要知道
h
θ
(
x
)
=
θ
0
+
θ
1
x
h_\theta(x)=\theta_0+\theta_1x
hθ(x)=θ0+θ1x,所以代价函数中含有两个参数,需要进行对两个参数的偏导。
两个参数就可以以下面的规则更新了:
θ
0
=
θ
0
−
α
∂
J
∂
θ
0
,
θ
1
=
θ
1
−
α
∂
J
∂
θ
1
\theta_0 =\theta_0 - \alpha \frac{\partial J}{\partial \theta_0}, \theta_1 =\theta_1 - \alpha \frac{\partial J}{\partial \theta_1}
θ0=θ0−α∂θ0∂J,θ1=θ1−α∂θ1∂J
其中
α
\alpha
α代表学习率,可以看到,学习率越大,参数更新的幅度越大,拟合学习的速度也就越快。但是学习率并不是越大越好,不合适的学习率可能导致代价函数的值增大甚至无法收敛的情况发生。
如果我们把
θ
0
,
θ
1
\theta_0,\theta_1
θ0,θ1的图像画出来你会发现,形状很像一个碗:
而我们的梯度下降的过程也就是我们不断走向碗底的过程:
而如果学习率过大的话,会出现先面的情况: