Ceres Solver 中文文档
  • 😜Ceres Solver 中文文档
  • Why Ceres ?
  • Installation
  • Tutorial
    • Non-linear Least Squares
      • Introduction
      • Hello World
      • Derivatives
        • Numeric Derivatives
        • Analytic Derivatives
        • More About Derivatives
      • Powell’s Function
      • Curve Fitting
      • Robust Curve Fitting
      • Bundle Adjustment
      • Other Examples
    • General Unconstrained Minimization
      • General Unconstrained Minimization
  • On Derivatives
    • Spivak Notation
    • Analytic Derivatives
    • Numeric Derivatives
    • Automatic Derivatives
    • Interfacing with Automatic Differentiation
    • Using Inverse & Implicit Function Theorems
  • Modeling Non-linear Least Squares
    • Introduction
    • Main Class Interface
      • CostFunction
      • SizeCostFunction
      • AutoDiffCostFunction
      • DynamicAutoDiffCostFunction
      • NumericDiffCostFunction
      • DynamicNumericDifferCostFunction
      • CostFunctionToFunctor
      • DynamicCostFunctionToFunctor
      • ConditionedCostFunction
      • GradientChecker
      • NormalPrior
      • LossFunction
      • Manifold
      • AutoDIffManifold
      • Problem
      • EvaluatationCallback
      • Rotation
      • Cubic Interpolation
        • CubicInterpolator
        • BiCubicInterpolator
  • Solveing Non-linear Least Squares
    • Introduction
    • Trust Region Methodd
    • Line Search Methods
    • Linear Solvers
    • Mixed Precision Solves
    • Preconditioners
    • Ordering
    • Main Class Interfaces
      • Solver::Options
      • ParameterBlockOrdering
      • IterationSummary
      • IterationCallback
      • CRSMatrix
      • Solver::Summary
  • Covariance Estimation
    • Introduction
    • Gauge Invariance
    • Covariance
    • Rank of the Jacobian
      • Options
      • Covariance
      • GetCovarianceBlock
      • GetCovarianceBlockInTangentSpace
    • Example Usage
Powered by GitBook
On this page
  1. Tutorial
  2. Non-linear Least Squares

Hello World

PreviousIntroductionNextDerivatives

Last updated 1 year ago

我们尝试找到如下函数的最小值

12(10−x)2\frac{1}{2}(10-x)^221​(10−x)2

貌似这个问题太简单了哈,最小值点在 x=10x=10x=10 处取得,但是计算机不是人,我们只能通过程序的方式来让他求解,这就是 Ceres 要做的事。接下来我们就来通过 Ceres 来求解该问题。

第一步是编写一个 functor 来评估函数 f(x)=10−xf(x)=10-xf(x)=10−x

struct CostFunctor {
   template <typename T>
   bool operator()(const T* const x, T* residual) const {
     residual[0] = 10.0 - x[0];
     return true;
   }
};

上述最重要的部分是 operator() 这个重载函数,它是一个模板函数,它所有的输入和输出类型都是某种类型 T。在这里使用模板则允许 Ceres 调用 CostFunctor::operator<T>() ,当只需要残差值时使用 T=double,当同时需要雅可比时使用特殊类型 T=Jet (这个类型是 Ceres 为什么能够进行自动求导的关键)。在 Derivatives 中,也就是后文的导数章节,我们将更详细地讨论向 Ceres 提供导数的各种方法。

一旦我们有了计算残差的方法,就可以利用它去构建一个非线性最小二乘法问题,并使用 Ceres 解决它。

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

  // The variable to solve for with its initial value.
  double initial_x = 5.0;
  double x = initial_x;

  // Build the problem.
  Problem problem;

  // Set up the only cost function (also known as residual). This uses
  // auto-differentiation to obtain the derivative (jacobian).
  CostFunction* cost_function =
      new AutoDiffCostFunction<CostFunctor, 1, 1>();
  problem.AddResidualBlock(cost_function, nullptr, &x);

  // Run the solver!
  Solver::Options options;
  options.linear_solver_type = ceres::DENSE_QR;
  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;
}

AutoDiffCostFunction 将一个CostFunctor作为输入,自动对其进行微分,并给出一个 CostFunction 接口。

iter      cost      cost_change  |gradient|   |step|    tr_ratio  tr_radius  ls_iter  iter_time  total_time
   0  4.512500e+01    0.00e+00    9.50e+00   0.00e+00   0.00e+00  1.00e+04       0    5.33e-04    3.46e-03
   1  4.511598e-07    4.51e+01    9.50e-04   9.50e+00   1.00e+00  3.00e+04       1    5.00e-04    4.05e-03
   2  5.012552e-16    4.51e-07    3.17e-08   9.50e-04   1.00e+00  9.00e+04       1    1.60e-05    4.09e-03
Ceres Solver Report: Iterations: 2, Initial cost: 4.512500e+01, Final cost: 5.012552e-16, Termination: CONVERGENCE
x : 0.5 -> 10

Footnotes

  1. 实际上,求解器运行了三次迭代,通过观察第三次迭代中线性求解器返回的值,它发现参数块的更新太小,于是宣布收敛。Ceres 只在迭代结束时打印显示,一旦检测到收敛就会终止,这就是为什么你在这里只看到两次迭代而不是三次。

编译并运行 将会得到如下结果

xxx 的初始值设置为 0.50.50.5(),经过两轮迭代后为 101010,细心的读者会发现,这是一个线性问题,一次线性求解就足以得到最优值,然而 Ceres 求解器的默认配置是针对非线性问题的,为了简单起见,我们在本例中没有更改,不过,使用 Ceres 只进行一次迭代也确实可以得到这个问题的解。我们将在讨论 Ceres 的收敛性和参数设置时更详细地讨论这些问题。

examples/helloworld.cc
examples/helloworld.cc
Ceres 的英文文档这里写的 555,貌似是个笔误