第五章 Python 机器学习入门之梯度下降
目录
前面我们学习了代价函数,代价函数它可以反映我们的模型的好坏,我们可以通过代价函数让我们的模型更好。代价函数的作用就是衡量模型的预测值与y 的真实值之间的差异。
学习了代价函数,下一步那我们就要了解如何去获取代价函数的较小值,
当然我们可以手动获取等高线的图,然后自己一个一个的去试,最后找到合适的参数w,b的值,
但是这不是我们想要的,我们需要一个有效的算法,它可以自己去查找合适的参数w,b的值,给我们最合适的模型,使得代价函数 j 最小化。
这个有效的算法就是梯度下降 gradient descent 。梯度下降是机器学习最重要的算法之一。
梯度下降的变化不仅用于训练线性回归,像在一些先进的神经网络模型中等在很多方面都有应用。
一、梯度下降有什么用?
前面我们看到了代价函数的可视化,以及我们然后去找到最合适的参数w,b的值。
梯度下降这个算法可以帮我们,更系统的找到w 和 b的值,得到的结果是最小的代价函数 j(w ,b)
这里有w,b 的代价函数 j ,在我们看到的例子中,我们想最小化它,这是线性回归的代价函数。
但梯度下降其实是一种算法,它可以用来最小化任何函数,不仅仅是线性回归的代价函数。
我们这里只有两个参数w 和b ,实际上,梯度下降适用与各种函数,
如图所示,当我们使用的模型有多个参数时,梯度下降也是可以使用的,
例如我们有一个代价函数 j ( w1,w2,...wn, b ),我们的目标是使得代价函数 j ( w1,w2,...wn, b )最小化,我们可以应用梯度下降 gradient descent 来最小化这个代价函数j
我们要做的就是,对一些关于线性回归中w 和b 值的初步猜测,初始值是多少并不重要,所以一个常见的选择是吧它们都设置为0,
例如我们可以设置w = 0, b = 0,作为初始猜测值与梯度下降算法,
我们要做的就是不断地改变参数w 和 b,每次改变一点,以降低代价函数J(w,b)的值,直到j(w, b)稳定在或接近最小值。
我们应该注意,对于某些模型,代价函数的图形可能并不是U型的,有可能不止有一个可能的最低限度,
如图,这是一个相较复杂一点的曲面图例子,
我们来看看梯度下降 gradient descent 在做什么,图中的这个函数不是平方误差代价函数,对于线性回归函数,使用平方差代价函数,我们最后得到的图形总是像吊床的形状。
好了,说回我们的例子,图上的每一个点都代表着不同的w 和 b 的值,也就是代表着一个代价函数j(w,b),在某一点上,表面的高度就是代价函数的值,
对于梯度下降算法的理解,我们可以想象,我们是一个在图中顶上的小人,现在需要最快的下降,到图的底部。
梯度下降可以看成是帮助我们的工具,我们每走一步就进行了一步梯度下降,我们先环绕360度,找到最陡的地方(因为最陡的地方下降最快),朝着这个方向走一步。
然后以我们所在的位置为起点,继续走下一步。每走一步,我们都需要重新寻找最陡的方向,一直到最低处。
注意,我们起点位置是我们设定的,我们可以通过改变参数w,b 来改变起点的位置, 如果起点位置不同,到达的最低处可能不同。
如图,黑线和蓝线就是从两个起点,利用梯度下降,得到了两个最低点。这两个最低点都被称为局部极小 local minmal ,
我们从第一个起点进行梯度下降,不会到达第二条路线的最底处;同理,从第二个起点进行梯度下降,不会到达第一条路线的最底处,
下面,我们就来学习一下梯度下降是如何帮助我们下坡的,以及可以使得梯度下降算法工作的数学表达式,
梯度下降算法 gradient descent algorithm
公式一 :w = w - α* [dj(w,b)/dw]
这个表达式的意思就是通过获取w的当前值,并对它进行少量调整来更新参数w。
在等式中,"="的意思是给w 赋值,将= 右边赋值给左边。它是赋值运算符 ,给变量w 赋值。
α也被称为学习速率 learning rate ,learning rate 通常是0到1之间的一个正数。α的作用就是控制你下坡时的步幅,所以如果α特别大时,这相当于一个非常激进的梯度下降过程。
其中 dj(w,b)/dw 是代价函数的导数项,
公式二 : b = b - α* [dj(w,b)/db]
对于梯度下降算法,我们需要重复这两个步骤,直到算法收敛repeat until convergence ,也就是重复步骤,直到我们达到了一个局部最小值,在这个最小值下,参数w 和 b 不再随着步骤的增加的而改变很多。
还有一个关于如何正确使用梯度下降的细节,我们要同时更新参数w 和b ,
如图左边两个变量是同时更新的,而右边的写法并不是同时更新的,我们需要采用左边的写法。
下面,我们来学习梯度下降它在做什么,它有什么意义?
我们前面学习了gradient descent algorithm,
其中α是学习速率,它控制了我们在更新模型参数w和b 时迈出的步子大小,
dj(w,b)/dw 是一个导数 derivative,
那么这个导数和学习速率在干什么?它们相乘又有什么用呢?
我们先来看看公式中的导数有什么作用,
我们可以简化模型,将b赋值为0 ,那么公式中只有一个参数w 了,公式如上图。我们如何来调整参数w 来最小化代价函数呢?
当只有一个参数w 时,代价函数的图如下
我们来看看这里导数项 dj(w)/dw 含义,
如果起点在最低点的右边,导数项的值就是该点切线的斜率,可以看见此时斜率为正值,
那么带入公式,学习速率肯定为正值,w = w = w - α* [dj(w)/dw], w的值会减小,点会往左移动,重复步骤,最终会移动到最低点
看图下方的例子,如果起点在最低点的左边,导数项的值还是该点切线的斜率,不过它现在是负值了,
那么带入公式,学习速率肯定为正值,w = w = w - α* [dj(w)/dw], w的值会增加,点会往右移动,重复步骤,最终会移动到最低点
通过这两个例子,我们可以知道导数是有助于梯度下降,代价函数的值j,使其更接近最小值。
现在,我们先来看看公式中的α (learning rate)有什么作用,
学习速率α的选择会对我们实现梯度下降的效率产生很大的影响,
学习速率太大或者太小都会对梯度下降gradient descent产生不好的影响
当α太小too small时,我们可以通过梯度下降得到最低限度,但是我们需要很多步才能实现,也就是需要花费很多时间来完成,
当α太大too large时,如图,我们从最低点左边取个起始点,导数是负值,梯度下降往右边进行,可是如果α太大的话,我们会直接越过最低点,一步来到最低点右边,图中这个点的代价函数值变大了,并没有得到我们想要的结果
如果继续进行梯度下降处理,它会直接从最低点的右边一步来到左边,继续下去,我们会发现实际代价函数的值例最小值越来越远了。
所以总结一下,如果α太大时,梯度下降可能会超调,可能永远都达不到最小值。也可以认为梯度下降将无法收敛,最后可能会发散。
这里还有一个问题,如果我们已经找到了其中一个参数w的取值了,并且此时代价函数j(w) 在这个区域已经是最小值了local minimum,
那么梯度下降下一步会做什么呢?
我们来看下梯度下降gradient descent 的公式,
w = w - α*[d j(w) / dw]
其中 d j(w) / dw 这个导数的值可以看做该点切线的斜率,但是此时处于最低点,是一条直线,其斜率为0,故导数项值为0
所以w = w - α*[d j(w) / dw] 就可以写成w = w - α* 0 = w, 所以继续进行梯度下降,w 的值还是会保持不变。说明该点就是local minimum 局部最小值了
具体的说,如果w 当前值为5,而α是0,在进行一次迭代后 w = w - 0 , w 的值仍然为5.
所以当参数取得某值后,代价函数j 为局部最小值,那么这个时候我们在进行梯度下降 gradient descent ,它不会改变任何参数,而这个值就是我们需要的值。
当我们有固定的学习速率α时,导数项可能一开始很大 large,进行梯度下降,它会走较大的一步,
但是我们每走一步,导数项的绝对值都在减小,因为斜率在减小,所以更新的第二步会比第一步小
也就是说,当我们越接近最小值时,我们迈出的步骤就越小,直到我们达到local minimum 区域最小值,
总结一下,当我们接近当地最低值时,梯度下降将自动采用较小的步骤,因为当我们接近局部最小值时,导数derivative 会自动变小,也就是说更新步骤也会自动变小,即使α保持在某个固定值,这就是梯度下降算法,
我们可以使用它来尝试最小化任何代价函数,不仅仅是平方误差代价函数。
我们后面会学习在线性回归模型中使用梯度下降,我们取一个函数j ,把它设置为线性回归模型的代价函数,把梯度下降和代价函数放在一起,这将是我们的第一个学习算法,线性回归算法。
线性回归中的梯度下降 gradient descent for linear regression
前面我们学习了线性回归模型,代价函数和梯度下降算法,我们要把他们放在一起,用平方误差代价函数来表示带有梯度下降的线性回归模型
这将允许我们训练线性回归模型,使其与我们的训练数据符合一条直线,
图中左边是线性回归模型,右边是平方误差代价函数,下面是梯度下降算法,j(w, b )对于w,b 的导数为右边的公式,它们是用微积分推导出来的,看下图
代价函数j 对 w 的导数,将j(w,b)写成我们熟悉的形式,一步步的对w求偏导,就可以得到我们需要的结果,j 对 b 的导数同理,这里我们只有两个变量所以并不算很复杂。
将求导的结果带入梯度下降算法 gradient descent alogorithm,如图,我们重复执行着两步,直到收敛, 这里要注意,我们希望每个步骤上都同时更新w和 b ,这个我们前面说过。
之前我们看到了梯度下降中的一个问题,随着梯度下降的进行,不同的起点,也就是参数w 和b 不同的取值,可能会导致不同的局部最小值,而不是全局最小值,梯度下降会在局部最小值 local minimum 结束
当我们使用线性回归的平方误差代价函数时,它不会有多个局部最小值local minimum ,只有一个全局最小值global minimum,
它是一个凸函数,所以我们在一个凸函数上实习梯度下降时,只要我们的学习速率α选择适当,它会收敛到全局最小值global minimum
运行梯度下降 running gradient descent
左上角是模型和数据的图表,右上角是代价函数的等高线图,底下是代价函数的表面图,
通常w,b都被初始化为0,图中初始化为w = -0.1,b =900
所以模型就为f(x) = -0.1 * x + 900
现在我们代价函数从这一点出发,在这一点下往下走,往右走,当我们运行多次梯度下降,每次更新后代价函数的值都在下降,
参数w 和 b 的值沿着这个轨迹,线越来越符合数据,直到我们达到全局最小值global minimum ,
全局最小值对应的这条直线,点在等高线图的中心位置,黄色的直线,与数据相吻合,
这就是梯度下降,我们可以用它来拟合房子的价格,例如房子大小为1250平方英尺,价格大概在25万
batch gradient descent 批梯度下降,
指的是它在梯度下降的每一个步骤上,我们看的是所有的训练实例,而不仅仅是训练数据的子集。
所以在计算梯度下降时,当计算导数时,我们计算的是从i等于 1 到 m 的和,而批梯度下降是在每次更新时查看整个一批训练示例,
还有其他版本的梯度下降,不考虑整个训练集,他们是在每个更新步骤中查看训练数据的小子集,但是批梯度下降会批量生产线性回归的梯度下降。