AI机动队
首发于AI机动队
梯度下降算法——深度学习花书第四章数值计算

梯度下降算法——深度学习花书第四章数值计算

第四章主要研究的是优化问题。我们机器学习的目标常常是使某个目标函数(objective function)或损失函数(cost function)尽量小,即找到一个 x^{*} = argminf(x). 对于有的问题我们可能可以得到解析解,但对于大多数问题,我们可能无法得到解析解,这时候就需要一些数值计算的方法使我们逐渐逼近最优解,这一章里就主要讲了利用一阶导数的梯度下降算法和利用二阶导数的牛顿方法,另外还有研究在给定某些限制条件下的条件极值的解法,Ian在这一章有些解释可能略过了,在这里我加入了自己的理解使其更易懂。

梯度下降算法

首先,回顾一下基本概念,对于函数 y=f(x) ,我们通常用 f'(x) \frac{dy}{dx} 来表示其导数。导数代表了f(x)在x处的斜率,即假如我们将x改变一个小量 \varepsilon ,则 f(x+\epsilon) \approx f(x) + \epsilon * f'(x)

梯度下降算法(gradient descent)就是我们想要寻找f(x)的最小值,假设我们初始位置是 x ,那我们下一次想要找的新的x的位置为 x' = x - \alpha f'(x) ,其中 \alpha > 0 。由此我们可以得到 f(x')-f(x) = -\alpha [f'(x)]^2 <= 0 f(x')相对于f(x)是变小的,所以我们可以通过这种更新方式逐步逼近f(x)的最小值。比如对于一个简单的二次函数 f(x)=\frac{1}{2} x^2 ,其导数为 f'(x)=x , 在x>0时,f'(x)也大于零,所以新的位置应往左边走,使f(x)更小,对于x<0时,f'(x)小于零,因此新的位置应往右边走,最终我们会得到在x=0时有最小值f(x)=0。


我们可以看出无论f'(x) 是大于零还是小于零, f(x')-f(x) 都小于零,即我们在逼近更小值。而当f'(x)等于零的时候是一个比较有意思的情况,我们发现f(x')与f(x)的值相同,这个点称作临界点(critical point),它可能是局域最大点(local maximum)如果f(x)比其它周围的值都高,也可能是局域最小点(local minimum)如果f(x)比其他周围的值都低,也可能是鞍点(saddle point)即既不是局域极大点也不是极小点,如下图所示:

前面我们提到了局域,我们还定义如果某一点对于我们所研究的域内所有的点都是最小值,则称其为全局最小点(global minimum)。 通常我们在深度学习模型里可能找到的是很多局域最小点而很难找到全局最小点,尤其是对于具有很多维度的优化问题,这个时候我们一般就取一个非常小的局域最小点,而不一定非要强求找到全局最小点。

上面我们主要定义了标量的导数,我们也可以将其推广到相对于矢量的导数,称作梯度(gradient)。假设我们有函数 f: R^n \rightarrow R 我们定义其偏导数(partial derivative) \frac{\partial}{\partial x_i} f(x) 为f(x)在矢量x所在点相对于 x_i 坐标的f(x)的变化率,我们可以用一个矢量来表示相对于所有坐标的导数,标记为 ∇_xf(x) 。而梯度下降算法的公式就可以表示为 x' = x - \alpha ∇_xf(x) ,其中 \alpha 是学习率(learning rate),表示了每次步进的幅度。通常我们将其选为一个较小的常数,但直观上讲,当初始时我们可能离极值点比较远,我们可以用比较大的学习率,而接近于极值点时我们需要较小的学习率否则f(x)就可能来回波动而收敛很慢,因此后面章节(第八章)会提到一些其他的optimizer例如Adagrad, Adam等不断更新学习率的方法。

雅可比矩阵,海森矩阵与牛顿逼近法

有的时候我们的映射函数可能输入和输出均是矢量,即 f: R^m \rightarrow R^n ,这时候为表示所有输出与输入各坐标的偏导数,我们就需要雅可比矩阵(Jacobian matrix), J\in R^{n\times m} ,其中 J_{i,j} = \frac{\partial}{\partial x_j}f(x)_i

有的时候我们可能还需要求某一个函数的二阶导数,对于 f: R^n \rightarrow R ,其对于 x_j 求偏导后再对 x_i 求偏导可以表示为 \frac{\partial}{\partial x_i \partial x_j}f ,对于所有的i,j的偏导数的组合,我们可以用海森矩阵(Hessian matrix)H(f)(x)表示,其中 H(f)(x)_{i,j} = \frac{\partial^2}{\partial x_i \partial x_j}f(x) ,我们可以将其看做梯度的雅可比矩阵。

那么二阶导数代表了什么意义呢?它可以看做是曲线斜率随输入的变化,是一种对曲线曲率的测量,对于一维情况,假如二阶导数为零,那么该曲线曲率为零,即为一条直线,如果二阶导数为正,那么曲线就是一个下凹函数,如果二阶导数为负,则曲线为上凸函数,如下图所示:

二阶导数可以告诉我们梯度下降算法的效果。我们将函数f(x)对于当前点 x^{(0)} 做二阶泰勒展开,可以得到 f(x) \approx f(x^{(0)}) + (x-x^{(0)})^T g + \frac{1}{2} (x-x^{(0)})^T H(x-x^{(0)}) ,其中g是导数,H为Hessian matrix。假设学习率是 \alpha ,则新的点是 x^{(0)}-\alpha g ,有 f(x^{(0)}-\alpha g) \approx f(x^{(0)})-\alpha g^T g + \frac{1}{2} \alpha ^2g^THg ,可以看出右边的 -\alpha g^T g 是我们优化求极小值时的改善项,而最右一项为修正项,如果最右一项过大,那么我们就会沿着曲线上移,没有逼近极小点,而是远离了极小点。当 g^THg 是零或者负值,我们可以看出提高 \alpha 总会使f(x)变小,而当 g^THg 是正值时,如果 \alpha 选取的不合适,就可能使f(x)上升,如果我们将二级泰勒展开对于 \alpha 求导取零,即可得到最合适的学习率为 \alpha ^* = \frac{g^Tg}{g^THg}

二阶导数也可以用来判断一个临界点是否是极小值点,极大值点或是鞍点。在临界点 f'(x)=0 ,如果 f''(x)>0 ,如果我们向右移动则导数升高,向左移动则导数下降,直观地讲我们无论左移右移都在向曲线上坡方向走,所以该点是极小值点。同理,当 f''(x) < 0 ,则是极大值点。当 f''(x) = 0 ,则不确定,可能是鞍点,也可能是一个全平的区域。

以上是针对一维空间进行的讨论,我们也可以将其延伸到多维空间:当 ∇_xf(x) = 0 时,如果Hessian matrix 是正定矩阵(所有本征值都大于零),则是极小值点,如果是负定矩阵(所有本征值都小于零),则是极大值点,其余情况则为鞍点或是全平的区域。

对于多维空间,我们也可以看出一阶梯度下降算法的局限性,如果不同方向上的曲率不同,则某些方向上导数改变很快,而另一些方向上导数改变很小,由于梯度下降算法并没有考虑二阶梯度,它并不知道该选取哪个方向才能更快的到达极值点。同样的,如果不同方向的曲率不同,我们如何选取合适的学习率也成了一个难题,某些方向上曲率大,就会产生在曲线的两个山坡上来回振动而不能一直趋近山坳的现象,限制了我们只能选取很小的学习率,如下图所示:

为了解决这一缺陷,我们需要利用二阶导数,这就是牛顿方法。多维情况下的二阶泰勒展开为 f(x) \approx f(x^{(0)}) + (x-x^{(0)})^T ∇_xf(x^{(0)}) + \frac{1}{2} (x-x^{(0)})^T H(f)(x^{(0)})(x-x^{(0)})

使f(x)相对于x的导数为零,可得更新公式 x^* = x^{(0)}-H(f)(x^{(0)})^{-1}∇_xf(x^{(0)}) ,牛顿方法会比梯度下降算法更快的到达极值点。

条件极值与KKT算法

有的时候,我们不仅仅是要在全域里求某个函数的极值点,而且是要在给定限制条件的集合中求条件极值。这时候我们可以利用KKT(全称是Karush-Kuhn-Tucker)算法将有限制条件的极值问题转化为无限制条件的极值问题,然后我们就可以用之前处理无限制条件的极值问题的方法来解决这个问题。KKT算法可以看做是是拉格朗日乘子法的一种推广形式。

假设我们要求f(x)的极值,其限制条件为 S=\left\{ x|\forall i, g^{(i)}(x)=0, \forall j, h^{(j)}(x)\leq0 \right\} ,其中 g^{(i)}(x) 为等式限制条件,  h^{(j)}(x) 为不等式限制条件。对于每一个限制条件,我们可以引入新的KKT乘子 \lambda _i\alpha _j ,来定义一个新的拉格朗日式子

L(x,\lambda,\alpha) = f(x) + \sum_{i}{\lambda _i g^{(i)}(x)} + \sum_{j}{\alpha _j h^{(j)}(x)}

我们可以将有限制条件的极小值问题转化为对拉格朗日式子的无条件的极小值问题,即求出

则其得到的极值点与目标是

的相同。

可以如此转化的原因是如果所有的限制条件都满足,即 \forall i, g^{(i)}(x)=0, \forall j, h^{(j)}(x)\leq0 则拉格朗日式子第二项 \sum_{i}{\lambda _i g^{(i)}(x)}=0 ,而由于 h^{(j)}(x)\leq0 ,第三项 \sum_{j}{\alpha _j h^{(j)}(x)} 最大值为零,得到

而假如有任意限制条件不满足,比如,某一 g^{(i)}(x)\ne 0 ,则我们可以选取与 g^{(i)}(x) 符号相同的无限大的 \lambda ,使得 L(x,\lambda,\alpha) = \infty ,对于某一 h^{(j)}(x)>0 ,我们则可以选取无限大的 \alpha ,使得 L(x,\lambda,\alpha) = \infty ,所以可以总结为如果任意限制条件不满足,则

由此我们也可以得出拉格朗日式子取极值的必要条件:

  • L(x,\lambda,\alpha) 的梯度得零。
  • \forall i, g^{(i)}(x)=0
  • \forall j, \alpha _{j}*h^{(j)}(x)=0


一个应用KKT的实例是对于线性最小二乘问题(linear least square),我们想要求在限制条件为 x^T x \leq 1f(x)=\frac{1}{2}||Ax-b||^2 的极小值。

我们可以将其转化为拉格朗日式子

L(x,\lambda)=f(x)+\lambda (x^T x -1)

而转化为解决 min_x max_{\lambda , \lambda\geq 0}L(x, \lambda) 的问题。

我们想使 L(x, \lambda) 相对于x最小化,则可以对拉格朗日式子求x的导数并另其得零而得到

A^T Ax-A^T b + 2\lambda x = 0

所以最优解 x^* = (A^TA+ 2\lambda I)^{-1}A^T b

那我们如何选取 \lambda 可以使 L(x, \lambda) 相对于 \lambda 最大化呢, 我们可以将 L(x, \lambda)\lambda 求偏导,得

\frac{\partial}{\partial \lambda}L(x,\lambda)=x^Tx - 1

可以发现当 x^Tx > 1 即x的范数大于1时,偏导大于零,所以我们应该增大 \lambda 使 L(x, \lambda) 增大,由于 \lambda 增大,我们可以看到x的最优解会相应的减小,即x需要有更小的范数。在机器学习中,我们常常要为防止过拟合而限制某些范数过大的项,就是利用这个方法,而\lambda 又称作正则项(regularization)系数。


至此,花书第四章数值计算总结完毕,这章中的梯度下降算法和KKT算法后面会常常用到。

编辑于 2018-06-30

文章被以下专栏收录