最优化问题中,牛顿法为什么比梯度下降法求解需要的迭代次数更少?

经常看到资料上这么写,谁能给出详细点的解释,比如在几何方面上的解释
关注者
2,216
被浏览
268,374

44 个回答

像@崔岩 说的那样,牛顿法是二阶收敛,梯度下降是一阶收敛,所以牛顿法就更快。如果更通俗地说的话,比如你想找一条最短的路径走到一个盆地的最底部,梯度下降法每次只从你当前所处位置选一个坡度最大的方向走一步,牛顿法在选择方向时,不仅会考虑坡度是否够大,还会考虑你走了一步之后,坡度是否会变得更大。所以,可以说牛顿法比梯度下降法看得更远一点,能更快地走到最底部。

根据wiki上的解释,从几何上说,牛顿法就是用一个二次曲面去拟合你当前所处位置的局部曲面,而梯度下降法是用一个平面去拟合当前的局部曲面,通常情况下,二次曲面的拟合会比平面更好,所以牛顿法选择的下降路径会更符合真实的最优下降路径。

wiki上给的图很形象,我就直接转过来了:

红色的牛顿法的迭代路径,绿色的是梯度下降法的迭代路径。

参考:

http://en.wikipedia.org/wiki/Newton's_method_in_optimization

多图预警


本文讲你肯定能懂的机器学习多维极值求解,主要讲梯度下降和牛顿法的区别应该能够完美的回答题主的问题


事先说明

本文面向学习过高等数学统计学和线性代数基础知识的本科生,并假设读者拥有基本的矩阵运算和求导运算的相关知识,类似梯度,方向导数、Hessian Matrix这些东西不懂也没关系,我会用尽可能通俗的语言说明运算中的意义。

那么从最简单的开始。


梯度下降算法


梯度是个啥?我想最开始接触梯度的各位是在方向导数那一章接触这一概念的,如果老师没怎么讲的话可能有些人还不知道梯度是个向量。当你学梯度的时候,所有的概念全都是在二元函数下的,well,也写想象力不是很丰富的同学可能不知道这是个啥。来,我们降维先。


多维条件下是曲面对函数的一阶偏导数向量<fx,fy>,那么在一维条件下梯度会是什么的?显然就木有偏导数了,只有一个东西,当然你也可以把它写成向量的形式<fx>,就是一个导数,只不过现在变成一维的了,所以方向只有俩,向左和向右。值为正的时候向右,值为负的时候向左,值大值小不影响方向只影响距离。


在二维条件下,因为有了两个偏导数,所以这个向量能表示一圈。如果你以前看过些文章或者视频或者什么ppt之类的东西,大概你会听说一种说法:“梯度是曲面中最陡峭的方向,这个方向是下降最快的方向。”实际上这种说法是不准确的,从一维的角度来看,“梯度”其实是上升最快的方向,比如\mathrm{y=}{\mathrm{x}}^{\mathrm{2}}\mathrm{-}\mathrm{3}x=2处的导数是1,方向向右,这个方向函数是增长的。同样二维也是如此。只不过大部分迭代公式中在梯度的前面会加一个负号,比如这个\theta = \theta -H^{-1}{\nabla }_{\theta }J(\theta )。所以也就直接认为它代表了下降最快的方向了。


直观上,你可以理解为,梯度就是一个和曲面等高线垂直的法线,冲着增高的那边。就像下图:



那么它相反的方向就是下降的方向啦,函数的极值点导数都是0的,也就是说,你沿着梯度方向一直走,如果最终收敛到一个点,那肯定就是一个极值点,如果不收敛,说明可能不存在极值点哈(这里因为有步长的涉及,在求解的时候会遇到明明有极值点却没有收敛的问题,后面会提到)。


举个例子,在一维下用梯度下降算法求解极值点的问题。这里我先举一个方便验算的例子,方便大家理解。


比如方程y=x^2-3求解极值点。当然你口算都能算出来,不要急着算结果,来理解一下梯度能干啥。


一阶导y'=2xx=1的时候我们开始迭代,沿着下降最快的方向左边一点一点移动。迭代公式x:= x-\alpha y'这里\alpha 就是步长,用来调节每一次移动的距离,你也可能听过一些\alpha 不能过大也不能过小的看起来只能靠经验的废话。如果你是刚刚入门,可能写点程序,然后不断试,但是实际上较优的\alpha 也是可以算的,只不过那又是另一门带有好多论文的学科了。



不同的\alpha 得到不一样的迭代效果,收敛或者震荡收敛,周期震荡或者直接发散,但是有的时候,算一遍\alpha 很费劲啊!这里例子简单,要是碰到TB级的数据那真的是要死了。这还能去试?这里简单的说一下怎么设置\alpha ,首先你要确定x是收敛的。所以公式x:= x-\alpha y'可以写成


{\begin{eqnarray}x&:=& x-2\alpha \\ &=&(1-2\alpha )x \end{eqnarray}}


为了收敛,其中-1<\left(1-2\alpha \right)<1,然后你就知道0<\alpha <1了。


实际上\alpha如果控制在0\frac{1}{2}之间会收敛更快,因为震荡收敛总会造成一些重复计算。


二维上的梯度下降能干啥呢?


还是举一个简单的例子,这里直接连数据都是最简单的。你有两个点(4,4),(6,5),你想画一条线使得线和两个点之间的距离平方和最小,当然你也可以口算出来,但是我们依然是为了看一下作用,直接写公式对于一些人来说真的会蒙。


设直线的方程为y=kx+b


目标函数J\left(k,b\right)={\left(kx_1+b-y_1\right)}^2+(kx_2+b-y_1)^2


偏导数


{\begin{eqnarray}J_k\left(k,b\right)&=&2\left(kx_1+b-y_1\right)x_1+2\left(kx_2+b-y_2\right)x_2 \\ J_b\left(k,b\right)&=&2\left(kx_1+b-y_1\right)+2\left(kx_2+b-y_2\right)\end{eqnarray}}


迭代公式

\left[ \begin{array}{c} k \\ b \end{array} \right]:= \left[ \begin{array}{c} k \\ b \end{array} \right]-\alpha \left[ \begin{array}{c} J_k\left(k,b\right) \\ J_b(k,b) \end{array} \right]

同样这里可以计算一下\alpha的范围


对于k

{\begin{eqnarray}k&:=&k-\alpha [2\left(kx_1+b-y_1\right)x_1-2\left(kx_2+b-y_2\right)x_2] \\ &=&k-2\alpha k\left(x^2_1+x^2_2\right)-2\alpha \left[x_1\left(b-y_1\right)+x_2\left(b-y_2\right)\right] \\ &=&[1-2\alpha \left(x^2_1+x^2_2\right)]k-2\alpha \left[x_1\left(b-y_1\right)+x_2\left(b-y_2\right)\right] \end{eqnarray}}

然后-1<1-2\alpha \left(x^2_1+x^2_2\right)<1得到0<\alpha <\frac{1}{\left(x^2_1+x^2_2\right)}


同样如果在不允许震荡的情况下0<\alpha <\frac{1}{2}*\frac{1}{\left(x^2_1+x^2_2\right)}

对于b

{\begin{eqnarray}b&:=&b-2\alpha \left(kx_1+b-y_2\right)-2\alpha \left(kx_2+b-y_2\right)\\ &=&(1-4\alpha )b-2\alpha \left(kx_1+kx_2-y_1-y_2\right) \end{eqnarray}}

这里求得允许0<\alpha <\frac{1}{2}并且在\left(0,\ \frac{1}{4}\right)区间内不会震荡,梯度计算方向在二维曲面震荡起来长啥样啊。来来来画个图。开始震荡的部分我想我得给他个特写。



不过瘾?来看这个



大致知道啥意思就行了哈。

在不震荡的情况下就显得特别简洁了。一条线走回去。



当然教科书上数学书上肯定不会这么写例子,为了公式的简洁,最后改为:


对于已知的一系列点x=\left[x_1,x_2,\dots ,x_n\right],\ y=\left[y_1,y_2,\dots ,y_n\right]

目标函数J\left(\theta \right)={\frac{1}{2}{\sum}}^n_{i=1}{\left(f\left(x_i;\theta \right)-y_i\right)}^2

其中的f\left(\theta ;x_i\right)就是我们上面写的kx+b了,\theta 则表示所有参数的集合。咦?公式多了个\frac{1}{2}是哪来的?在这里实际上这个值是多少都无所谓,因为两个偏导数都带着这个\frac{1}{2}不影响梯度方向,只影响步长,而步长又可以由\alpha 调节,我们可以理解为,加了它,导数写起来好看^_^。就像下面这样。


\[\frac{\partial \left(J\right)}{\partial \left(\theta \right)}={\mathit{\sum}}^n_{i=1}\left(f\left(\theta ;x_i\right)-y_i\right)\frac{\partial \left(\theta ;x_i\right)}{\partial \left(\theta \right)}\]


迭代公式


\[\theta :=\theta -\alpha \frac{\partial \left(J\right)}{\partial (\theta )}\]

\theta 就是上面写到的\left[ \begin{array}{c} k \\ b \end{array} \right]一个列向量

牛顿法


提到牛顿法的时候,你可能在小的时候听说过,一个用来迭代求零点的方法,稍微提一下。


如果你要求解\sqrt3小学初中的时候你可能知道随便取一个大于0的数和一个小于0的数,然后不断地二分得到逼近于0的点,后来你可能知道这个利用了零点定理。你可以写一个同样的方程y=x^2-3y=0x的值。取x_{left}=1\ \ \ x_{right}=2然后不断的试值,唔~~还是来画图吧。



你也可以看到他们的迭代过程,当然这个不叫牛顿法,这个叫二分法,比较low哈,看到没,震荡了,震荡收敛慢。



讲牛顿法的时候,你可能还要明确一个概念dy\mathit{\Delta}y的区别。前者是切线带来的高度差,后者是函数上的高度差,只有当dx趋近于0的时候他俩才近似。而牛顿法就是用切线来快速逼近零点的,不会震荡呦,画图吧先。




看起来两步就收敛了啊,好厉害,怎么做到不震荡的呢它?

因为每一步迭代移动切线与x轴交叉点的距离



这个距离怎么算?可能你已经明白了\mathit{\Delta}y/\frac{\textrm{}y}{\textrm{}x},这里\frac{dy}{dx} 就是该点的一阶导数。因此迭代公式如下:


\[x:=x-\frac{y}{y'}\]


没错就是这么简单。


这里顺带一提,对于不同的方程起始点的选择也会影响迭代次数,如果有兴趣的话可以读一下这篇文章,看一下神奇的0x5f375a86,2次迭代求解,这里读两次不读二次^_^


那牛顿法和极值求解有关系?看起来牛顿法只能求零点啊? Naive~~,一阶导零点不就是函数的极值或者驻点?

算起来更简单,迭代公式如下


\[x:=x-\frac{y'}{y^{''}}\]


文章是用来解释高维极值求解的,如果你读到这里还是饶有兴致的话,那么恭喜你,你的高数肯定90+,接下来要上干货了。

对于高维函数,用牛顿法求极值也是这个形式,只不过这里的y^{''}y'都变成了矩阵和向量。而且你也可以想到,高维函数二阶导有多个,写成矩阵的形式就像这样

\[H=\left[ \begin{array}{ccc} f_{11} & \dots & f_{1n} \\ \vdots & \ddots & \vdots \\ f_{n1} & \dots & f_{nn} \end{array} \right]\]

这个矩阵就是传说中的Hessian矩阵,不是什么拼音的简写。

同样y'就变成了对所有参数的偏导数组成的向量

\[J\left(\theta \right)=\left[ \begin{array}{c} J_1 \\ \vdots \\ J_n \end{array} \right]\]

迭代公式


\[\theta :=\theta -H^{-1}J(\theta )\]


其中H^{-1}为Hessian 矩阵的逆

还是以上面的例子解,对就是只有两个点求直线的那个,这次我们把目标函数的\frac{1}{2}加上

{\begin{eqnarray}J_k\left(k,b\right)&=&{\mathit{\sum}}^n_{i=1}\left(kx_i+b-y_i\right)x_i \\ J_b\left(k,b\right)&=&{\mathit{\sum}}^n_{i=1}\left(kx_i+b-y_i\right)\end{eqnarray}}

{\begin{eqnarray}J_{kk}\left(k,b\right)&=&\left(x^2_1+x^2_2\right)=52 \\ J_{kb}\left(k,b\right)&=&\left(x_1+x_2\right)=10 \\ J_{bb}\left(k,b\right)&=&2\end{eqnarray}}

H=\left[ \begin{array}{cc} J_{kk} & J_{kb} \\ J_{kb} & J_{bb} \end{array}\right]

\[H^{-1}=\left[ \begin{array}{cc} \ 0.5 & -2.5 \\ -2.5 & 13 \end{array} \right]\]

迭代公式

\[\left[ \begin{array}{c} k \\ b \end{array} \right]:=\left[ \begin{array}{c} k \\ b \end{array} \right]-\left[ \begin{array}{cc} \ 0.5 & -2.5 \\ -2.5 & 13 \end{array} \right]\left[ \begin{array}{c} J_k\left(k,b\right) \\ J_b\left(k,b\right) \end{array} \right]\]

来看一下效果,看起来直接一步到位啊!!!所以牛顿法求解你们也应该知道多厉害了。



难道是我初始点选的就比较接近答案?换一个大一点的(100,100),依然非常快!



这么快的原因,可能跟方程有关,换了其他方程也许就不这样了。当然你读到这里也许会迫不及待的去找些自己想分析的数据,计算些参数,如果数据量少,几百个,没问题,几万个,还撑得住,要是直接从统计局或者人口普查中进行分析的话,算一个J_{kk}\left(k,b\right)可能都很慢,而且数超大。

简单的解决办法,有一种叫做批迭代的方法,不管是在梯度计算极值还是在牛顿计算极值上都是可行的,就是假设失去大部分点对准确度没有太大的影响,比如说3个在一条直线上的点,去掉一个也没什么关系,最后反正还是会拟合成同一个参数。批迭代就是在众多的点中随机抽取一些,进行迭代计算,再随机抽取一些再进行迭代。迭代的路径可能不完美,但是最终还是会找到我们想要的答案。


当然还有其他更帅的解决方法,祝如DFP,BFGS,Broyden。限于篇幅,下回再讲,私信知乎账号最爱麦丽素可以得到部分计算代码。


扩展阅读


一个Sqrt函数引发的血案

梯度下降法步长的取值范围

为什么不同教材中凸函数和凹函数的定义是不同的?

监督学习应用.梯度下降


欢迎各类奇葩怪咖加我微信FavorMylikes,嘻~~~