0

0

c++中如何使用Ceres Solver进行非线性优化? (最小二乘法实例)

尼克

尼克

发布时间:2026-01-15 13:34:41

|

286人浏览过

|

来源于php中文网

原创

Ceres Solver 的 CostFunction 是用于定义残差函数的接口,必须以 ∑ᵢ ‖fᵢ(x)‖² 形式表达优化问题;用户需实现 operator() 计算残差,支持自动/数值微分,参数块顺序与维度须严格匹配。

c++中如何使用ceres solver进行非线性优化? (最小二乘法实例)

什么是 Ceres Solver 的 CostFunction

Ceres 中的优化问题必须表达为残差(residual)形式,即最小化 ∑ᵢ ‖fᵢ(x)‖²。你不能直接写目标函数,而是要实现一个 CostFunction 子类或使用 AutoDiffCostFunction / NumericDiffCostFunction 包装计算逻辑。

最常用的是自动微分:你只提供残差计算的 operator(),Ceres 自动求导。关键点:

  • operator() 的第一个参数是参数块指针数组(const double* const*),第二个是残差输出(double*),返回 bool
  • 参数块顺序必须和 AddParameterBlock() 一致,且每个块大小要匹配
  • 残差维度(输出长度)和参数块维度(输入长度)在构造 AutoDiffCostFunction 时就固定,写错会导致段错误或收敛失败

如何构造并运行一个最小二乘优化问题?

以拟合曲线 y = a·exp(b·x) + c 为例,有 3 个待估参数 a, b, c,已知若干 (x_i, y_i) 数据点:

struct ExponentialResidual {
  ExponentialResidual(double x, double y) : x_(x), y_(y) {}
  template 
  bool operator()(const T* const a, const T* const b, const T* const c,
                  T* residual) const {
    residual[0] = y_ - (*a) * exp(*b * x_) - (*c);
    return true;
  }
 private:
  const double x_, y_;
};

// 构建问题 ceres::Problem problem; double a = 1.0, b = 0.1, c = 0.0; std::vector> data = {{0.0, 1.2}, {1.0, 3.1}, {2.0, 8.0}}; for (const auto& p : data) { ceres::CostFunction* cost_function = new ceres::AutoDiffCostFunction( new ExponentialResidual(p.first, p.second)); problem.AddResidualBlock(cost_function, nullptr, &a, &b, &c); }

// 配置并求解 ceres::Solver::Options options; options.linear_solver_type = ceres::DENSE_QR; options.minimizer_progress_to_stdout = true; ceres::Solver::Summary summary; ceres::Solve(options, &problem, &summary); printf("Final a=%f, b=%f, c=%f\n", a, b, c);

注意:AutoDiffCostFunction 表示:残差维度 1,三个参数块各占 1 维;若参数是向量(如旋转四元数),维度就得改成 4。

立即学习C++免费学习笔记(深入)”;

LangChain
LangChain

一个开源框架,用于构建基于大型语言模型(LLM)的应用程序。

下载

为什么优化不收敛或报 Check failed: is_valid

常见原因不是模型本身,而是数值或配置问题:

  • 初始值太离谱(例如 b 初始为 1e6 导致 exp(b*x) 溢出),改用合理量级初值(如对数尺度预估)
  • 残差函数里用了未定义行为:比如 log(x)x ≤ 0,或除零、sqrt 负数 —— 加 if (x 并返回 false 让 Ceres 跳过该残差
  • 没设置 options.max_num_iterations,而问题病态导致迭代太久,建议设为 100 左右先试
  • 用了 nullptr 作为损失函数(loss function),但数据含大离群点,应改用 new ceres::HuberLoss(0.1)

C++ 编译时链接失败:找不到 ceres::Problemceres::Solve

不是头文件没包含,而是链接阶段缺失库或顺序错误。确保:

  • 链接时包含 -lceres,且放在你的目标文件之后(如 g++ main.o -lceres -lglog -lgflags -lpthread -o app
  • 如果用 CMake,不要只写 find_package(Ceres),还要 target_link_libraries(your_target ${CERES_LIBRARIES}),且 ${CERES_LIBRARIES} 必须在你自己源文件编译目标之后
  • 确认安装的 Ceres 是带 Solver 支持的(非 minimal 版本),检查 ceres-config.cmake 中是否含 ceres_FOUNDCERES_SOLVER_LIBRARY

最易忽略的一点:Ceres 默认关闭 OpenMP 和 SuiteSparse,如果你的优化变量多于几百维,又没开 -DCERES_USE_EIGEN_SPARSE=ON-DCERES_USESuiteSparse=ON,它会静默退回到稠密求解器,速度骤降且内存爆炸 —— 这类问题不会报错,只会让你等十分钟还不出结果。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

738

2023.08.22

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

738

2023.08.22

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

523

2023.09.20

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

523

2023.09.20

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

98

2025.10.23

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1018

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

62

2025.10.17

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

4

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Java 教程
Java 教程

共578课时 | 46.2万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号