SciPy优化:Newton-CG与BFGS对比L-BFGS

时间:2017-02-23 19:24:04

标签: python optimization scipy newtons-method

我正在使用Scipy进行优化问题,我正在采用平顶网络和大小为NNxNN的连接,连接它的两侧(即使其周期性),并最小化能量函数,这样它就会卷起来形成一个圆柱体。 (见下面的链接。)

由于我有函数energy(xyz-position)并且它是渐变,我决定使用Scipy手册中推荐的三种方法 - Newton-CGBFGSL-BFGS-B - 并比较他们的表现。

我按如下方式调用优化函数,我只是根据大小写将'Newton-CG'替换为'BFGS''L-BFGS-B'

from scipy.optimize import minimize
res = minimize(energy, xyzInit, method='Newton-CG', jac = energy_der,  options={'disp': True}) 

我发现了以下一般行为(我给出了NN=9的输出数据,对应于3*9^2=243 - 维参数空间) -

  1. BFGS系统地未能找到正确的最小值(对于低NN),并且对于大NN而言根本没有收敛。有关最终结果,请参阅https://plot.ly/~apal90/162/

     NN=9
     Method: BFGS
     Warning: Desired error not necessarily achieved due to precision loss.
     Current function value: 204.465912
     Iterations: 1239
     Function evaluations: 1520
     Gradient evaluations: 1508
     Time taken for minimisation: 340.728140116
    
  2. Newton-CG找到了小NN(< = 8)的正确最小值,但从NN = 9开始,返回了一个不正确的最小值(即一端压扁的圆柱体),并且对于更高的值,甚至会收敛。注意:出于某些原因,这种行为因奇数NN而加剧。见https://plot.ly/~apal90/164/

     NN=9
     Method: Newton-CG
     Optimization terminated successfully.
     Current function value: 7.954412
     Iterations: 49
     Function evaluations: 58
     Gradient evaluations: 1654
     Hessian evaluations: 0
     Time taken for minimisation: 294.203114033
    
  3. 对于我测试的所有NN,L-BFGS-B找到了正确的最小值,而且速度太快了(最多NN=14)。见https://plot.ly/~apal90/160/

     NN=9
     Method: L-BFGS-B
     Time taken for minimisation: 36.3749790192
    
  4. 问题:为什么L-BFGS-B在这种情况下优于其他两种方法?特别是,为什么它优于BFGS,当两者都被认为是准牛顿方法(按照我的理解),以完全相同的方式工作。

    我对情况的看法:所有三种方法都在每个点x都进行二次近似。为此,它需要一个渐变和一个Hessian。如果没有给出Hessian,则必须通过算法计算。在我们的情况下,只显示渐变,这是由算法在数值上计算的每一步。更具体地说,我们需要的是Hessian的逆,这是一个非常昂贵的步骤,特别是在更高的维度。现在,Newton-CG明确地计算了这个逆Hessian,因此需要更长的时间。像BFGS和L-BFGS这样的准牛顿方法基于梯度计算Hessian的近似值(即曲率),该梯度在时间上更便宜,并且据推测也可以更好地估计关于点的曲率。因此,对于二次函数,Newton-CG收敛得更快,而对于非二次函数,准牛顿函数收敛得更好。 L-BFGS是BFGS的低内存版本,每个步骤存储的内存比完整的NxN矩阵少得多,因此它比BFGS快。

    这个解释显示了Newton-CG和准牛顿方法之间的分歧。它没有解释的是算法无法找到真正的最小值,特别是BFGS和L-BFGS之间的差异,它们都应该以相同的方式起作用。

    我对长收敛时间的一般预感是系统关于最小值是非二次的(即平坦的),因此算法在收敛时振荡。除此之外,如果BFGS和L-BFGS真正以相同的方式工作,我相信Scipy算法的收敛容差水平之间必定存在一些差异。否则,BFGS和L-BFGS实际上不会以相同的方式工作,而后者可能更准确地计算Hessian。

    参考文献 -

    http://www.scipy-lectures.org/advanced/mathematical_optimization/#newton-and-quasi-newton-methods

    https://en.wikipedia.org/wiki/Newton%27s_method_in_optimization

    https://en.wikipedia.org/wiki/Quasi-Newton_method

    https://docs.scipy.org/doc/scipy-0.18.1/reference/optimize.minimize-bfgs.html#optimize-minimize-bfgs

    https://docs.scipy.org/doc/scipy-0.18.1/reference/optimize.minimize-lbfgsb.html#optimize-minimize-lbfgsb

1 个答案:

答案 0 :(得分:0)

您的问题缺少两个重要信息:能量函数和初始猜测。能量函数可以是凸/非凸,平滑/分段平滑/不连续的。因此,很难根据您的情况来完全回答您的问题。但是,我可以解释BFGS和L-BFGS-B之间的一些关键区别。

这两种方法都是解决非线性优化问题的迭代方法。它们都通过在每次迭代时使用函数的Hessian近似值来近似Newton方法。牛顿法的主要区别在于,它们没有在特定点上计算完整的Hessian,而是在先前的点上累积了梯度,并使用BFGS公式将它们汇总为Hessian的近似值。除非函数具有接近最佳值的二次泰勒展开式,否则不能保证Newton和BFGS方法收敛。

自给定初始猜测以来,原始BFGS方法会累积所有梯度。这种方法有两个问题。首先,内存可以无限期增加。其次,对于非线性问题,最初猜测时的Hessian通常不能代表解中的Hessian。因此,近似的Hessian将被偏置,直到在解决方案附近累积了足够的梯度为止。这可能会减慢收敛速度,但以我的经验,应该仍然可以针对具有单个局部最小值的能量函数使用良好的线搜索算法进行收敛。

L-BFGS与BFGS相同,但内存有限,这意味着一段时间后,旧的梯度将被丢弃,从而为新计算的梯度留出更多空间。这解决了存储器的问题,并且避免了初始梯度的偏差。但是,根据内存中保留的渐变数量,可能永远无法精确估计Hessian,并且可能成为偏差的另一个来源。这也会减慢收敛速度,但是同样,对于具有单个局部最小值的能量函数,它仍然应该与良好的线搜索算法收敛。

L-BFGS-B与L-BFGS相同,但是对输入变量有约束。 L-BFGS-B将停止优化域边界上的变量。由于您未指定任何约束,因此算法的这一方面不适用于您的问题。

我的假设是,您正在尝试使用距离解决方案较远的初始猜测来解决一个平滑但非凸的问题,并且最终得出的是局部最小值。由于您提到的是从平面配置开始的,所以如果您以奇异性开头会导致退化的Hessian,这可能会给其余的优化带来麻烦,我不会感到惊讶。在您的情况下,BFGS和L-BFGS之间的唯一区别是,每次迭代将计算出略有不同的梯度,并且L-BFGS方法最终将遵循导致全局最小值的路径。