Ceres Solver中文详细易懂版学习笔记
1.Ceres Slover简介
Ceres Solver是谷歌开发的一种高效的非线性优化开源库,应用场景广泛,可以解决常见数据拟合,最小二乘,非线性最小二乘的问题,类似于图像处理中的OpenCv。
大多数人接触此库,往往是因为SLAM中的图优化,归根到底最后也是一个非线性的最小二乘问题,Ceres在数值处理方面有着更加广泛的应用。
本笔记主要参考官方教程,内容为官方教程的再理解和补充。
笔者将大多数学习理解都写入了代码的中文注释中,如有参考请细读。
官方教程链接:http://www.ceres-solver.org/nnls_tutorial.html.
官方网站:http://www.ceres-solver.org/
2.CeresSlover之Helloworld实现
不论是什么语言,经典的Helloworld总是必不可少的,在某种意义上,如果你的python或者java能输出Helloworld,那代表着你的环境配置和程序的基本使用已经完善,下面我们用一个非常简单的例子进行Ceres使用的Helloworld讲解。
2.1 目标问题
我们使用ceres求取下列函数的最小值(为方便教学,函数选取的非常简单):
1 2 ( 10 − x ) 2 \frac{1}{2}(10-x)^2 21(10−x)2
我们很容易算出这个最小值在x等于10处,但是简单的问题更适合用来说来用法。
2.2 代码实现
第一步:建立起f(x)= 10- x 的数学函数模型。
struct CostFunctor {
template <typename T>
//operators是一种模板方法,其假定所的输入输出都变为T的格式
bool operator()(const T* const x, T* residual) const
//其中x为带估算的参数,residual是残差
{
residual[0] = T(10.0) - x[0];//这里的T[10。0],可以将10 转换位所需的T格式,如double,Jet等
return true;
}
};
这样我们就建立起了一个残差的计算模型,接下来:
第二步:就要构建最小二乘的问题框架并解决它。
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
// 设置迭代的初值
double initial_x = 5.0;
double x = initial_x;
// 申明构建的问题,用Problem类
Problem problem;
// 设置好的残差计算的公式,使用auto-differentiation选项去获得导数(雅克比).
CostFunction* cost_function =
//注意:costFunctor是前面定义的f(x)=10-x。这里的第一个1是待测参量的维数,第二个1是每个待测参量的size
// 比如有两个参量。第一个为m,大小9;第二个c,大小为3。那么就是<CostFunctor, 2, 9,3>
new AutoDiffCostFunction<CostFunctor, 1, 1>(new CostFunctor);
problem.AddResidualBlock(cost_function, NULL, &x);
// 运行solver
Solver::Options options;//为Solver的设置参数类,使用options可以对Solver类型使用方法等进行设置
options.linear_solver_type = ceres::DENSE_QR;//使用得是稠密的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;
}
本部分的官方参照代码在examples/helloworld.cc
笔者在ubuntumate 18.04下进行验证,结果为:
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
如果你得到同样的结果,那么说明环境的配置和基础使用已经OK
2.3 Helloworld小结
学习完本部分后,依托着简单的函数,我们可以大致总结出ceres解决的问题的框架和步骤:
1.建立constFuntions 1
2.设置初值,构建出最小二乘问题(使用Probolem类)
3.构建solver,设置使用的方法如线性最小二乘等
4.输出程序结果
3.ceres在powell法上的实现
接下来介绍一个较为复杂的问题,鲍威尔优化算法。有兴趣的可以查询其算法细节,本文主要是针对ceres的使用。
参数为 x = [ x 1 , x 2 , x 3 , x 4 ] x=[x_1,x_2,x_3,x_4] x=[x1,x2,x3,x4],具体的函数为:
f 1 ( x ) = x 1 + 10 x 2 f 2 ( x ) = 5 ( x 3 − x 4 ) f 3 ( x ) = ( x 2 − 2 x 3 ) 2 f 4 ( x ) = 1 0 ( x 1 − x 4 ) 2 F ( x ) = [ f 1 ( x ) , f 2 ( x ) , f 3 (