Ceres Solver 官方教程学习笔记(九)——自动微分法Automatic Derivatives

这篇文章翻译自官方教程Automatic Derivatives并且参考了少年的此间的博客文章Ceres-Solver学习笔记(5)

现在我们将讨论自动微分算法。它是一种可以快速计算精确导数的算法,同时用户只要做与数值微分法类似的工作。下面的代码片段实现了对Rat43(见前两节)的CostFunction

struct Rat43CostFunctor {
  Rat43CostFunctor(const double x, const double y) : x_(x), y_(y) {}

  template <typename T>  
  bool operator()(const T* parameters, T* residuals) const {
  //变化1
    const T b1 = parameters[0];
    const T b2 = parameters[1];
    const T b3 = parameters[2];
    const T b4 = parameters[3];
    residuals[0] = b1 * pow(1.0 + exp(b2 -  b3 * x_), -1.0 / b4) - y_;
    return true;
  }

  private:
    const double x_;
    const double y_;
};


CostFunction* cost_function =
      new AutoDiffCostFunction<Rat43CostFunctor, 1, 4>(    //变化2
        new Rat43CostFunctor(x, y));

我把对应的数值微分法代码贴在这里以供对比。

struct Rat43CostFunctor {
  Rat43CostFunctor(const double x, const double y) : x_(x), y_(y) {}

  bool operator()(const double* parameters, double* residuals) const {
    const double b1 = parameters[0];
    const double b2 = parameters[1];
    const double b3 = parameters[2];
    const double b4 = parameters[3];
    residuals[0] = b1 * pow(1.0 + exp(b2 -  b3 * x_), -1.0 / b4) - y_;
    return true;
  }

  const double x_;
  const double y_;
}

CostFunction* cost_function =
  new NumericDiffCostFunction<Rat43CostFunctor, FORWARD, 1, 4>(
    new Rat43CostFunctor(x, y));

注意,与数值微分法相比,在定义自动微分的Functor时,唯一的区别是对操作符operator()的设置。
在数值微差的情况下

//数值微分法
bool operator()(const double* parameters, double* residuals) const;

//自动微分法
template <typename T> bool operator()(const T* parameters, T* residuals) const;

这个变化有什么影响呢?下表比较了使用各种方法对Rat43进行计算残差和雅可比矩阵的时间。

CostFunction Time (ns)
Rat43Analytic 255
Rat43AnalyticOptimized 92
Rat43NumericDiffForward 262
Rat43NumericDiffCentral 517
Rat43NumericDiffRidders 3760
Rat43AutomaticDiff 129

我们可以使用自动微分(Rat43AutomaticDiff)来得到精确的微分。而这与编写数字微分的代码量相差不多,但比优化后的解析微分法只慢 40% 40 % 。 为了研究它的工作原理,必须要学习二元数(Dual number)射流(Jet)

二元数(Dual number)和射流(Jet)

阅读这一小节和下一节关于实现Jets的内容,与在Ceres求解器中使用自动微分没有直接关系。但是,在调试和推理自动微分的性能时,了解Jets的工作原理是非常有用的。

二元数是实数的一个延伸,类似于复数。复数则通过引入虚数来增加实数,比如 i i ,二元数引入了一个极小(infinitesimal)二元数单位,比如 ϵ ,且 ϵ2=0 ϵ 2 = 0 (平方后太小可以忽略)。一个二元数 a+vϵ a + v ϵ 包含两个分量,实分量 a a 和极小分量的 v 。令人惊喜的是,这个简单的变化带来了一种方便的计算精确导数的方法,而不需要复杂的符号表达式。
例如,考虑函数

f(x)=x2, f ( x ) = x 2 ,

然后

f(10+ϵ)=(10+ϵ)2=100+20ϵ+ϵ2=100+20ϵ(41)(42)(43) (41) f ( 10 + ϵ ) = ( 10 + ϵ ) 2 (42) = 100 + 20 ϵ + ϵ 2 (43) = 100 + 20 ϵ

观察 ϵ ϵ 的系数&#

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值