非線性優化庫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更先進的方法構建和計算代價函數。

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