找回密码
 立即注册
首页 业界区 业界 最小二乘问题详解9:使用Ceres求解非线性最小二乘 ...

最小二乘问题详解9:使用Ceres求解非线性最小二乘

挚魉 1 小时前
1 引言

在上一篇文章《最小二乘问题详解8:Levenberg-Marquardt方法》中,笔者使用 Eigen 实现了求解非线性最小二乘问题的 Levenberg-Marquardt 方法。不过在实际的工程实践中,更多的是使用像 Ceres Solver 这样成熟的、专门用于求解大规模非线性最小二乘问题的库。不过,因为有着极强的专业性,像 Ceres Solver 这样的库使用起来并不容易。如果是初次接触这方面知识的读者,非常建议先读一读本系列的前置文章。
2 实例

如果要构建安装 Ceres Solver,可以参考文章《CMake构建学习笔记30-Ceres Solver库的构建》。Ceres Solver 的构建过程还是挺麻烦的,推荐直接找预编译版本,比如 GISBasic3rdParty。
还是求解与《最小二乘问题详解8:Levenberg-Marquardt方法》一样的最小二乘问题,模型函数为:\(f(x; \boldsymbol{\theta}) = \exp(a x^2 + b x + c)\),具体代码如下:
[code]#include #include #include #include #include #include using namespace std;// 残差计算结构体(用于自动微分)struct ExpModelResidual {  ExpModelResidual(double x, double y) : x_(x), y_(y) {}  // 模板 operator() 支持自动微分  template   bool operator()(const T* const a, const T* const b, const T* const c,                  T* residual) const {    // 计算指数部分: a*x^2 + b*x + c    T exponent = (*a) * T(x_) * T(x_) + (*b) * T(x_) + (*c);    // 防止 exp 溢出(Ceres 内部对梯度也有保护,但这里加一层更稳)    const T kMaxExp = T(300.0);    if (exponent > kMaxExp) exponent = kMaxExp;    if (exponent < -kMaxExp) exponent = -kMaxExp;    T y_pred = ceres::exp(exponent);    residual[0] = T(y_) - y_pred;    return true;  } private:  const double x_;  const double y_;};int main() {  // ========================  // 1. 真实参数  // ========================  double a_true = 0.05, b_true = -0.4, c_true = 1.0;  cout
您需要登录后才可以回帖 登录 | 立即注册