在选择 BFGS 和共轭梯度进行优化时,我应该考虑哪些因素?我试图拟合这些变量的函数是指数函数;然而,实际的目标函数包括集成等,如果有帮助的话,成本会非常高。
BFGS 与共轭梯度法
如果您使用有限内存 变体而不是全存储 BFGS ,则 BFGS 的相关成本可能会更符合 CG 。这将计算最后一次的 BFGS 更新通过一系列 rank-one 更新有效地更新,而不需要存储超过最后一个解决方案和梯度。
根据我的经验,具有大量更新的 BFGS 存储的信息与当前解决方案相距太远,无法真正用于逼近非滞后雅可比行列式,如果存储太多,实际上可能会失去收敛性。出于这些原因,BFGS 的“无记忆”变体看起来很像非线性共轭梯度(参见其中一个描述的最终更新)。因此,如果您愿意做 L-BFGS 而不是 BFGS,那么内存问题就会消失并且方法是相关的。轶事证据表明重新启动是一个棘手的问题,因为它有时是不必要的,有时是非常必要的。
您在两者之间的选择也很大程度上取决于您感兴趣的问题。如果您有资源,您可以针对您的问题尝试两者并决定哪个效果更好。例如,我个人不使用这些算法进行优化,而是关心非线性方程组的解。对于这些,我发现 NCG 效果更好,并且更容易执行非线性预处理。BFGS 更健壮。
坦率地说,我最喜欢处理这类事情的方法是N-GMRES。如果您的梯度评估非常昂贵,则尤其如此,因为根据我的经验,它通过在最后解决一个小的最小化问题为您带来最大的收益迭代构建一个新的、低残差的解决方案。
JM 对存储的看法是正确的。BFGS 需要一个近似的 Hessian,但您可以使用单位矩阵对其进行初始化,然后只要您有可用的梯度信息,最好是通过分析而不是通过有限差分来计算近似 Hessian 的秩二更新。BFGS 是一种准牛顿方法,与 CG 相比,收敛的步骤更少,并且“卡住”的趋势更小,需要轻微的算法调整才能实现每次迭代的显着下降。
相反,CG 需要矩阵向量乘积,如果您可以计算方向导数(同样,解析或使用有限差分),这可能对您有用。方向导数的有限差分计算将比 Hessian 的有限差分计算便宜得多,因此如果您选择使用有限差分构建算法,只需直接计算方向导数即可。然而,这种观察并不真正适用于 BFGS,它将使用梯度信息的内积来计算近似 Hessians。
就收敛速度而言,如果是问题中决策变量的数量,则 CG 迭代大约等于牛顿法的一步。BFGS 是一种准牛顿方法,但同样的观察应该成立;除非有几个 CG 方向有很多下降,然后在几次 CG 迭代后,您重新启动它,否则您可能会在更少的迭代中使用 BFGS 获得收敛。如果矩阵向量产品很便宜并且您的问题太大以至于存储 Hessian 变得困难或不可能,则类似 CG 的方法会更便宜。BFGS 涉及更多的向量-向量乘积来更新其近似 Hessian,因此每次 BFGS 迭代会更昂贵,但您需要更少的乘积来达到局部最小值。
如果您知道存储不会成为问题,我会针对您的应用程序的一个小测试问题比较这两种算法。在不知道您的问题的具体细节的情况下,我的猜测是 BFGS 会更快,但您应该真正测试这两种算法,以更好地了解哪种算法效果更好。
最后,关于自动微分:对 Fortran ( DAEPACK )的内部自动微分 (AD) 工具有一些经验,我可以告诉您,AD 工具通常很挑剔。他们可能不一定能够区分他们自己生成的代码。有两种类型的广告工具:
- 源到源广告工具
- 运算符重载 AD 工具
源到源工具本质上是经过修改的编译器,它获取您编写的源代码,对其进行解析,并自动生成新的源代码,以计算源代码中函数的梯度。运算符重载 AD 工具要求您在源代码中使用重载的 AD 运算符,以便计算导数,这需要您付出额外的努力来使用 AD 计算分析导数。
在低维中,一个良好实现的 BFGS 方法通常比 CG 更快、更健壮,特别是在函数离二次函数不是很远的情况下。
BFGS 和 CG 都不需要关于凸性的任何假设;只有初始的 Hessian 近似值(对于 BFGS)resp。预条件子(对于 CG)必须是正定的。但是这些总是可以选择为单位矩阵,在低维中没有太大的危害。另请参阅https://scicomp.stackexchange.com/a/3213/1117
在没有编程梯度的情况下,使用数值梯度是一种很大的浪费,尤其是当函数值很昂贵时。相反,应该使用无导数算法。有关最近的一项调查,请参阅Rios 和 Sahinidis 2013及其随附网页。