【优化算法】梯度之上:基于 Jacobian 和 Hessian 矩阵的优化算法

上篇说的,仅仅基于梯度的优化算法称为 一阶优化算法(first-order optimization algorithms), 比如最典型的 梯度下降法;很多时候,仅仅使用一阶的梯度信息效果是不够优良的,还需要考虑梯度的梯度, 也就是 二阶优化算法(second-order optimization algorithms), 二阶优化算法基于的是 Hessian 矩阵, 比较典型的方法如 牛顿法。

先来回顾一下 梯度,Jacobian 矩阵 和 Hessian 矩阵 的关系。开始!
二阶导数(second derivative),即导数的导数,表达的是一阶导数如何随着输入的变化而变化。一阶导数,表征的是曲线的斜率, 同理我们可以认为二阶导数,表征的是曲线(或曲面)的曲率. 借助物理来理解,就是函数表征的是位移和时间的对应关系,一阶导数就是速度,二阶导数就是加速度。

  • 对于一个一次函数而言,比如 y = k x , 其一阶导数就是常数 k , 而二阶导数就是 0 , 或者说匀速直线运动,速度恒定,没有加速度。
  • 对于一个二次函数而言,比如自由落体运动 y = 1 2 g x 2 , 其一阶导数就是 x t , 二阶导数就是常数 g , 也就是说有随 x 变化的斜率和固定的曲率,或者说有固定的加速度然后有随时间变化的速度。

回到优化算法中,我们之前使用的梯度下降法,相当于以当前的速度匀速直线前进一个 δ x 时间,作为估计的 y ^ , 当然这个和真实的 y 肯定是有差距的。二阶导数信息就可以用来预知这个差距的大小:

  • 如果二阶导数/曲率 0 , 也就是没有加速度,匀速直线运动,那么我们用梯度进行预测就是很准确的。
  • 如果二阶导数/曲率 为负, 也就是减速运动,那么我们用梯度进行预测的值就会比真实值大。
  • 如果二阶导数/曲率 为正, 也就是加速运动, 那么我们用梯度进行预测的值就会比真实值小。

对于多元函数,二阶函数有很多,我们将这些导数合并成为 Hessian 矩阵。由于微分算子在任何二阶偏导连续的点处都可以交换,因此 Hessian 矩阵在这些点上是对称的。在深度学习背景中,我们遇到的大多数的 Hessian 矩阵基本都是对称的。而由于Hessian 矩阵是实对称的,我们可以将其分解为一组实特征值和一组特征向量的正交基。那么在特定方向 d 上的 二阶导数就可以写成 d T H d 。 当 d H 的一个特征向量时,这个方向的二阶导数就是对应的特征值。对于其他的方向 d , 方向二阶导数就是所有特征值的加权平均,权重 ( 0 , 1 ) ,且与 d 夹角越小的特征向量的权重越大。最大特征值确定最大二阶导数,最小特征值确定最小二阶导数。

下面我们定量的来看一下,通过二阶导数如何衡量一个梯度下降步骤表现的有多好。我们在当前点 x ( 0 ) 处做函数 f ( x ) 的近似二阶泰勒展开

f ( x ) f ( x ( 0 ) ) + ( x x ( 0 ) ) T g + 1 2 ( x x ( 0 ) ) T H ( x x ( 0 ) )
, 其中 g 是梯度, H x ( 0 ) 处的Hessian矩阵。如果我们引入参数学习率 ε , 那么新的点 x 将会是 x ( 0 ) ε g 。 带入上式,可得
f ( x ( 0 ) ε g ) f ( x ( 0 ) ) ε g T g + 1 2 ε 2 g T H g
.

其中有三项,

  • 函数的原始值
  • 函数斜率导致的预期改善
  • 函数曲率导致的校正

当最后一项太大时,函数值是可能向上移动的。

  • g T H g 为 0 或者负数时候,近似的泰勒级数增加表明增加 ε 将永远使 f 下降。在理论上,这种情况下我们应该把步长尽量调大,然而在实践中,泰勒级数不会在 ε 很大的时候依然保持准确,因此在这个情况下我们必须采取更具启发式的选择。
  • g T H g 为正数时,通过计算可得,使得近似泰勒级数下降最多的最优步长是
    ε = g T g g T H g

最坏的情况下, g H 的最大特征值 λ m a x 对应的特征向量对齐,则最优步长是 1 λ m a x . 当我们要最小化的函数能用二次函数很好地近似的情况下, Hessian 的特征值决定了学习率的量级。

二阶导数还可以用来确定一个临界点是否是局部极大点,局部极小点 或者 鞍点。

  • f ( x ) = 0  &  f ( x ) > 0 时, x 是一个局部极小值点
  • f ( x ) = 0  &  f ( x ) < 0 时, x 是一个局部极大值点
  • f ( x ) = 0  &  f ( x ) = 0 时,很遗憾,不能确定唯一情况。 x 可能是一个鞍点或可能是一个平坦区域的一部分。

对于已知 f ( x ) = 0 , 进而求得二阶导数以更加具体的判断, 这就是所谓的 二阶导数测试(second derivative test).

在多维的情况下,我们需要检测函数的所有二阶导数。利用 Hessian 矩阵的特征值分解,我们可以将二阶导数测试扩展到多维情况。在临界点处 x f ( x ) = 0 , 我们通过检测 Hessian 的特征值来判断该临界点是一个局部极大点,局部极小点 还是鞍点。

  • 当 Hessian 是正定的,即所有特征值都是正的, 则该临界点是局部极小点。类似于山脚下的小泉眼,往四面山上走都是上坡路,水从四面山上流进来。
  • 当 Hessian 是负定的,即所有特征值都是负的, 则该临界点是局部极大点。类似于山顶的火山喷发,往四面山上走都是下坡路,岩浆从山顶向四处流下。
  • 当 Hessian 的特征值,有正有负有零的时候,就不能准确判断了,但是也能提供一定的信息
    • 如果Hessian 的特征值中至少一个是正的,一个是负的,那么我们可以肯定 x f 某个横截面的局部极大值,确是另一个横截面的局部极小点,这就很有可能是鞍点了。
    • 当所有的非零特征值是同号的且至少有一个特征值是 0 时,这个检测就是不确定的。因为单变量的二阶导数测试在零特征值对应的横截面上是不确定的。

在多维情况下,单个点处每个方向上的二阶导数是不同的。 Hessian 的条件数衡量这些二阶导数的变化范围。当 Hessian的条件数很差时,梯度下降法也会表现的很差。因为此时,一个方向上的导数增加得很快,而在另外一个方向上增加得很慢。梯度下降法不会知道这层信息,所以它不知道应该优先搜索导数长期为负的反向。病态条件也导致很难选择合适的步长。步长必须足够小,以免冲过最小而向具有较强正曲率的方向上升。而通常这也意味着在其他较小的曲率上进展不明显。

我们可以利用 Hessian的信息来指导搜索,以解决这个问题。其中最简单的方法是牛顿法(Newton's method)另起一篇,单独介绍

最后,总结一下,

上面提到的优化算法适用于各种各样的函数,但几乎都没有理论保证。因为深度学习中使用的函数族是非常复杂的,所以深度学习算法往往缺少理论保证。在许多其他领域,优化的主要方法是为有限的函数族设计优化算法。

在深度学习的背景下,限制函数满足 Lipschitz连续(Lipschitz continuous) 或者其导数 Lipschitz连续可以获得一些保证。Lipschitez 连续函数的变化速度以 Lipschitz 常数(Lipschitz constant) 为界 :

x , y , | f ( x ) f ( y ) | x y 2
,
这个属性允许我们量化自己的假设: 梯度下降等算法导致的输入的微小变化将使输出只产生微小变化, 因此是很有用的。Lipschitz 连续性也是相当弱的约束, 并且深度学习中很多优化问题经过相对较小的修改后就能变得 Lipschitz连续。

最成功的特定优化领域或许是凸优化(Convex optimization). 凸优化通过更强的限制提供更多的保证。凸优化算法只对凸函数使用,即 Hessian 矩阵 处处半正定的函数。因为这些函数没有鞍点而且其所有局部极小点必然是全局最小点,所以表现良好。然而,深度学习中的大多数问题都不能表示成凸优化的形式。凸优化仅用作一些深度学习算法的子程序。凸优化中的分析思路岁证明深度学习算法的收敛性非常有用,然而一般来说,深度学习背景下凸函数的重要性大大减少。

猜你喜欢

转载自blog.csdn.net/baishuo8/article/details/81453954