随手笔记——Ceres 求解曲线拟合问题

这里写目录标题

  • 说明
  • 步骤
  • 源代码

说明

Google Ceres 是一个广泛使用的最小二乘问题求解库。在 Ceres 中,只需按照一定步骤定义待解的优化问题,然后交给求解器计算即可。

步骤

  1. 定义每个参数块。
    参数块通常为平凡的向量,但是在 SLAM 里也可以定义成四元数、李代数这种特殊的结构。如果是向量,那么需要为每个参数块分配一个 double 数组,来存储变量的值。
  2. 定义残差块的计算方式。
    残差块通常关联若干个参数块,对它们进行一些自定义的计算,然后返回残差值。Ceres 对它们求平方和之后,作为目标函数的值。
  3. 残差块往往也需要定义雅可比的计算方式。
    在 Ceres 中,你可以使用它提供的“自动求导”功能,也可以手动指定雅可比的计算过程。如果要使用自动求导,那么残差块需要按照特定的写法来书写:残差的计算过程应该是一个带模板的括号运算符。
  4. 把所有的参数块和残差块加入 Ceres 定义的 Problem 对象中,调用 Solve 函数求解即可。
    求解之前,可以传入一些配置信息,例如迭代次数、终止条件等,也可以使用默认的配置。

源代码

#include <iostream>
#include <opencv2/core/core.hpp>
#include <ceres/ceres.h>
#include <chrono>using namespace std;// 代价函数的计算模型
struct CURVE_FITTING_COST {CURVE_FITTING_COST(double x, double y) : _x(x), _y(y) {}// 残差的计算template<typename T>bool operator()(const T *const abc, // 模型参数,有3维T *residual) const {residual[0] = T(_y) - ceres::exp(abc[0] * T(_x) * T(_x) + abc[1] * T(_x) + abc[2]); // y-exp(ax^2+bx+c)return true;}const double _x, _y;    // x,y数据
};int main(int argc, char **argv) {double ar = 1.0, br = 2.0, cr = 1.0;         // 真实参数值double ae = 2.0, be = -1.0, ce = 5.0;        // 估计参数值int N = 100;                                 // 数据点double w_sigma = 1.0;                        // 噪声Sigma值double inv_sigma = 1.0 / w_sigma;cv::RNG rng;                                 // OpenCV随机数产生器vector<double> x_data, y_data;      // 数据for (int i = 0; i < N; i++) {double x = i / 100.0;x_data.push_back(x);y_data.push_back(exp(ar * x * x + br * x + cr) + rng.gaussian(w_sigma * w_sigma));}double abc[3] = {ae, be, ce};// 构建最小二乘问题ceres::Problem problem;for (int i = 0; i < N; i++) {problem.AddResidualBlock(     // 向问题中添加误差项// 使用自动求导,模板参数:误差类型,输出维度,输入维度,维数要与前面struct中一致new ceres::AutoDiffCostFunction<CURVE_FITTING_COST, 1, 3>(new CURVE_FITTING_COST(x_data[i], y_data[i])),nullptr,            // 核函数,这里不使用,为空abc                 // 待估计参数);}// 配置求解器ceres::Solver::Options options;     // 这里有很多配置项可以填options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY;  // 增量方程如何求解options.minimizer_progress_to_stdout = true;   // 输出到coutceres::Solver::Summary summary;                // 优化信息chrono::steady_clock::time_point t1 = chrono::steady_clock::now();ceres::Solve(options, &problem, &summary);  // 开始优化chrono::steady_clock::time_point t2 = chrono::steady_clock::now();chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);cout << "solve time cost = " << time_used.count() << " seconds. " << endl;// 输出结果cout << summary.BriefReport() << endl;cout << "estimated a,b,c = ";for (auto a:abc) cout << a << " ";cout << endl;return 0;
}
  1. 定义残差块的类。方法是书写一个类(或结构体),并在类中定义带模板参数的 () 运算符,这样该类就成为了一个拟函数(Functor)。这种定义方式使得 Ceres 可以像调用函数一样,对该类的某个对象(比如 a)调用 a() 方法。事实上,Ceres 会把雅可比矩阵作为类型参数传入此函数,从而实现自动求导的功能。
  2. 程序中的 double abc[3] 即为参数块,而对于残差块,我们对每一个数据构造 CURVE_FITTING_COST 对象,然后调用 AddResidualBlock 将误差项添加到目标函数中。由于优化需要梯度,我们有若干种选择:(1)使用 Ceres 的自动求导(Auto Diff);(2)使用数值求导(Numeric Diff);(3)自行推导解析的导数形式,提供给 Ceres。因为自动求导在编码上是最方便的,于是我们使用自动求导。
  3. 自动求导需要指定误差项和优化变量的维度。这里的误差是标量,维度为 1;优化的是 a, b, c三个量,维度为 3。于是,在自动求导类 AutoDiffCostFunction 的模板参数中设定变量维度为 1、3。
  4. 设定好问题后,调用 Solve 函数进行求解。你可以在 options 里配置(非常详细的)优化选项。例如,可以选择使用 Line Search 还是 Trust Region、迭代次数、步长,等等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/2359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3,elementPlus和自己封装,点击 新增添加表单,删除表单,提交数据

ElementPlus下的form也有新增表单 如果你写H5等没找到合适的 自己也可以进行封装 实现3个代码讲解:1&#xff1a;ElementPlus的代码 2&#xff1a;自己书写的代码 3&#xff1a;自己把2的代码进行封装 1&#xff1a;ElementPlus的运行效果 点击提交 1&#xff1a;ElementPlus…

BrowserRouter刷新404解决方案

1、本地开发环境 在js脚本命令里加上 --history-api-fallback "scripts": {"serve": "webpack serve --config webpack.dev.js --history-api-fallback" }2、生产环境&#xff0c;可以修改 nglnx 配置&#xff1a; server {listen XXXX; //端口号…

Python教程(3)——python开发工具vscode的下载与安装

Python的开发工具有很多款&#xff0c;很多都是非常好用的&#xff0c;其中vscode作为其中一款Python的开发工具&#xff0c;是非常轻量级的&#xff0c;今天我们来介绍一下vs code的下载与安装。 vscode的下载与安装 首先需要到vscode的官网&#xff0c;这个谷歌或者百度一下…

Windows上传ios dsym到Bugly

首先下载符号表工具腾讯 Bugly SDK下载 (qq.com) dsym 可以在 wIndow-Organizer-找到版本 右键show In Finder buglyqq-upload-symbol.jar 在上面得文件同级目录下 进入cmd 输入一下命令 需要修改成你自己得信息 java -jar buglyqq-upload-symbol.jar -appid d83b04b3c3 -ap…

hadoop分布式系统复习题 选择题

1、以下哪一项不属于 Hadoop 可以运行的模式&#xff1f; 互联模式 2、下面哪个程序负责 HDFS 数据存储&#xff1f; Datanode 3、HDFS 中的 block 默认保存__3 _份。 4、配置Hadoop时&#xff0c;JAVA_HOME包含在哪一个配置文件中 hadoop-env.sh 。 5、 Hadoop fs中的-get和-p…

VSCode 注释后光标快速定位下一行

VSCode默认用 Ctrl / 注释一行时&#xff0c;光标停留在该行中。下面介绍如何注释后&#xff0c;光标会自动移动到下一行。 1.【View】 ->【Extensions】->【查找并安装Multi-command 扩展】 2.【File 】 -> 【Preferences 】->【Keyboard Shortcuts】&#xff08…

【人工智能】xAI——“X宇宙”又增添了一位新成员

个人主页&#xff1a;【&#x1f60a;个人主页】 &#x1f31e;热爱编程&#xff0c;热爱生活&#x1f31e; 文章目录 前言xAI团队成员做解开宇宙本质的AI 前言 有人问他&#xff0c;xAI公司是干啥的&#xff1f;马斯克的回答引用了其偶像、科幻作家道格拉斯・亚当斯的话&…

Python实现将pdf,docx,xls,doc,wps,zip,xlsx,ofd链接下载并将文件保存到本地

前言 本文是该专栏的第31篇,后面会持续分享python的各种干货知识,值得关注。 在工作上,尤其是在处理爬虫项目中,会遇到这样的需求。访问某个网页或者在采集某个页面的时候,正文部分含有docx,或pdf,或xls,或doc,或wps,或ofd,或xlsx,或zip等链接。需要你使用python自…

写给前端工程师的Dart教程(3):类的基础与命名构造函数

题解 | #删除链表峰值# 更多关于算法题解、软件开发面经、机器学习算法面经、各企业面试问题记录&#xff0c;关注Fintech砖&#xff0c;持续更新中。https://www.nowcoder.com/use 题解 | #牛群的重新分组# 链表模拟题 知识点链表模拟题意分析以k个结点为一组翻转链表, 剩下…

【运维小知识】(四)——linux常用命令

运维专栏&#xff1a;运维小知识 目录 1.&#x1f341;&#x1f341;用mv命令修改文件名 2.&#x1f343;&#x1f343;创建及删除文件夹即文件夹下所有文件 3.&#x1f342;&#x1f342;移动文件夹并重命名 4.&#x1f33f;&#x1f33f;复制文件 5.&#x1f344;&#x…

Python 算法基础篇之字符串操作:索引、切片、常用方法

Python 算法基础篇之字符串操作&#xff1a;索引、切片、常用方法 引言 1. 字符串的概念和创建2. 字符串的索引3. 字符串的切片4. 字符串的常用方法 a ) 查找子字符串 b ) 替换子字符串 c ) 拆分和连接字符串 总结 引言 字符串是一种常见的数据类型&#xff0c;在 Python 中对…

ARM微控制器 AM2432BSEFHIALXR、AM2432BSFFHIALV技术参数(32位MCU)

1、AM2432BSEFHIALXR 32位MCU采用293引脚FCCSP封装&#xff0c;工作频率最高可达800MHz。该微控制器专为需要结合处理和实时通信的工业应用而构建&#xff0c;例如远程I/O模块和电机驱动器。 核心处理器&#xff1a;ARM Cortex-M4F&#xff0c;ARM Cortex-R5F 内核规格&#xf…

pytest 禁用警告信息(忽略警告信息输出)

如图示例代码&#xff0c;提示test_001这个case 存在警告 新增pytest.ini 配置文件 [pytest] filterwarnings errorignore::UserWarning

携带时间戳主动写入数据到prometheus service(可乱序、go)

使用到的github公开项目 https://github.com/castai/promwrite Prometheus版本2.45.0 拉下来装依赖&#xff0c;然后使用 client_test.go t.Run(“write with custom options”, func(t *testing.T) 这个测试用例里面&#xff0c;删掉srv初始化的部分&#xff0c;这个是模拟一…

本地生活直播,和电商直播有什么不一样?

直播正在成为零售业的标配&#xff0c;当下最新的一条赛道是“本地生活直播”。 &#xff08;商家开始在美团等平台进行本地生活直播。摄影&#xff1a;李崧稷&#xff09; 今年618&#xff0c;在老牌电商平台拉着无数网店&#xff0c;拼尽全力想要堆高销量的时候&#xff0c;一…

微信小程序导入微信地址

获取用户收货地址。调起用户编辑收货地址原生界面&#xff0c;并在编辑完成后返回用户选择的地址。 1&#xff1a;原生微信小程序接口使用API&#xff1a;wx.chooseAddress(OBJECT) wx.chooseAddress({success (res) {console.log(res.userName)console.log(res.postalCode)c…

TensorFlow模块简介

TensorFLow框架内构建了很多高层次的API&#xff0c;可以显著减少编写程序的代码量&#xff0c;其中包含众多网络结构相关函数和数据载入、数据处理的方法。 tf.data.Dataset tf.data.Dataset是TensorFlow内置的数据输入模块&#xff0c;提供了专门用于数据输入的多种方法&am…

【Linux】进程间通信——管道/共享内存

文章目录 1. 进程间通信2. 管道匿名管道命名管道管道的特性管道的应用&#xff1a;简易的进程池 3. System V共享内存共享内存的概念共享内存的结构共享内存的使用代码实现 1. 进程间通信 进程间通信&#xff08;Inter-Process Communication&#xff0c;简称IPC&#xff09;是…

详细解析张雪峰老师对计算机专业的评价“进可攻,退可守”--【职场篇】

文章目录 张雪峰的评价计算机行业类的总结性指示就业面宽本科也不太卷的方向进可攻&#xff0c;退可守另一个就业出口--培训高校&#xff0c;大专&#xff0c;高职&#xff0c;科研机构&#xff0c;中小学计算机老师等等 就业总结导图持续学习&#xff0c;技术过人 总结 张雪峰…

你认为大数据的特点是什么?_光点科技

随着信息技术的迅猛发展&#xff0c;大数据已成为当今社会不可忽视的重要资源。它是指规模庞大且快速增长的数据集合&#xff0c;其中包含着宝贵的信息和见解。大数据的特点是多样而复杂的&#xff0c;它们塑造了我们的世界并深刻地影响着各行各业。 巨大的规模&#xff1a;大数…