非线性优化库Ceres学习笔记4(解析求导)

解析导数

在有些情况下,不使用AutoDiffCostFunction,例如我们用近似的方式计算导数,而不是用AutoDiff的链式法则,我们需要自己的残差和Jacobin计算。这时我们定义一个CostFunction或者SizedCostFunction的子类。

#include <vector>
#include "ceres/ceres.h"
#include "glog/logging.h"

using ceres::CostFunction;
using ceres::SizedCostFunction;
using ceres::Problem;
using ceres::Solver;
using ceres::Solve;

// A CostFunction implementing analytically derivatives for the
// function f(x) = 10 - x.
class QuadraticCostFunction : 
public SizedCostFunction<1 /* number of residuals */,
                         1 /* size of first parameter */> {
 public:
  virtual ~QuadraticCostFunction() {}

  virtual bool Evaluate(double const* const* parameters,
                        double* residuals,
                        double** jacobians) const {
    double x = parameters[0][0];

    // f(x) = 10 - x.
    residuals[0] = 10 - x;

    if (jacobians != NULL && jacobians[0] != NULL) {
      jacobians[0][0] = -1;
    }

    return true;
  }
};

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);

  // 初始化待优化变量
  double x = 0.5;
  const double initial_x = x;

  // 构建问题
  Problem problem;

  // 设置残差函数
  CostFunction* cost_function = new QuadraticCostFunction;
  problem.AddResidualBlock(cost_function, NULL, &x);

  // 构建求解器
  Solver::Options options;
  // 输出到cout
  options.minimizer_progress_to_stdout = true;
  // 优化信息
  Solver::Summary summary;
  // 开始计算
  Solve(options, &problem, &summary);

  std::cout << summary.BriefReport() << "\n";
  std::cout << "x : " << initial_x
            << " -> " << x << "\n";

  return 0;
}

The jacobians array is optional, Evaluate is expected to check when it is non-null, and if it is the case then fill it with the values of the derivative of the residual function.

QuadraticCostFunction::Evaluate parameters作为输入,residuals作为残差输出和Jacobians作为雅可比矩阵的输出。jacobians是可选的,Evaluate is expected to check when it is non-null, and if it is the case then fill it with the values of the derivative of the residual function.在这个例子中,残差函数是线性的,故而Jacobian是常量。

除非有一个很好的管理Jacobian的理由,否则建议使用AutoDiffCostFunctionNumericDiffCostFunction

CMakeLists.txt文件

cmake_minimum_required(VERSION 2.8)
project(ceres)
find_package(Ceres REQUIRED)
include_directories(${CERES_INCLUDE_DIRS})
add_executable(use_ceres main.cpp)

target_link_libraries(use_ceres ${CERES_LIBRARIES})

有关衍生工具的更多信息

到目前为止,计算导数是使用Ceres的最复杂的部分,并且根据情况,用户可能需要更复杂的计算导数的方法。本节仅介绍如何将衍生物提供给Ceres。

当你熟悉了NumericDiffCostFunctionAutoDiffCostFunction的使用后,建议在考虑下DynamicAutoDiffCostFunction, CostFunctionToFunctorNumericDiffFunctor以及 ConditionedCostFunction更先进的方法构建和计算代价函数。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章