优化:通过自动微分提供梯度,例如 PyAutoDiff

计算科学 优化
2021-12-23 05:43:13

证明由 AD 包(如 PyAutoDiff)获得的梯度和让求解器(如 BSGS)计算梯度之间有什么区别(例如在鲁棒性和速度方面)?这样做似乎很诱人:

from autodiff import gradient

def my_costfun(x):
    return f(x)

@gradient
    def g(x):
    return f(x)

真的那么简单吗?有 10 个参数的函数呢?

2个回答

如果成本函数复杂或参数较多,使用自动微分计算梯度会导致成本快速增长。通常不需要精确的梯度(尤其是远离最小值),因此其他策略可能要便宜得多。

免责声明:我将笼统地谈论 AD 包,而不是 PyAutoDiff。

有限的差异

优点:

  • 易于实施
  • 用于测试分析梯度程序或 AD 是否给出正确的结果
  • 如果您可以重新实现您的函数以获取复数输入,那么有一个技巧可以为您提供几乎精确的梯度
  • 非侵入式
  • 在许多情况下足够好的准确性

缺点:

  • 可能很吵;病态函数可能导致不准确的有限差分逼近
  • 对于使用从梯度派生的 Hessian 更新的准牛顿方法(例如,BFGS 类型方法),梯度中的噪声会传播到 Hessian。
  • 昂贵的:对于一个功能n变量,需要n功能评估
  • 选择商的分母中使用的差值的大小是一门艺术
  • 即使足够准确,噪声也会减慢优化方法的收敛速度。

自动微分

优点:

  • 返回几乎精确的梯度
  • 反向模式很便宜(“3-5x”理论上是函数评估,但在实践中,它是一个依赖于实现的倍数,上面有一个常数)
  • 可以分析非常复杂的函数
  • 避免可能耗时的梯度函数推导

缺点:

  • 前向模式很昂贵;与 # 个输入变量一起缩放
  • 实施自己令人发指;你绝对应该依赖图书馆
  • 该方法具有侵入性——它需要访问源代码
  • 源到源的翻译方法可以自动分析源代码,但会返回可笑的混淆代码;更重要的是,这些方法通常无法区分它们生成的代码,因此您通常仅限于 1 阶导数。
  • 运算符重载方法需要重写代码以使用重载运算符;这个过程可能很耗时