Ceres简介及示例(8)On Derivatives(Analytic Derivatives)

news/2024/10/22 19:47:42/

考虑以下曲线(Rat43) 的拟合问题:
y = b 1 ( 1 + e b 2 − b 3 x ) 1 / b 4 y = \frac{b_1}{(1+e^{b_2-b_3x})^{1/b_4}} y=(1+eb2b3x)1/b4b1
也就是说,给定一些数据 { x i , y i } , ∀ i = 1 , . . . , n \{x_i, y_i\},\ \forall i=1,... ,n {xi,yi}, i=1,...,n,确定最适合该数据的参数 b 1 , b 2 , b 3 , b 4 b_1, b_2, b_3, b_4 b1,b2,b3,b4

我们面临的问题就是求解 b 1 , b 2 , b 3 , b 4 b_1, b_2, b_3, b_4 b1,b2,b3,b4 使下列表达式的取值最小:
E ( b 1 , b 2 , b 3 , b 4 ) = ∑ i f 2 ( b 1 , b 2 , b 3 , b 4 ; x i , y i ) = ∑ i ( b 1 ( 1 + e b 2 − b 3 x i ) 1 / b 4 − y i ) 2 \begin{split} E(b_1, b_2, b_3, b_4) &= \sum_i f^2(b_1, b_2, b_3, b_4 ; x_i, y_i)\\ &= \sum_i \left(\frac{b_1}{(1+e^{b_2-b_3x_i})^{1/b_4}} - y_i\right)^2\\ \end{split} E(b1,b2,b3,b4)=if2(b1,b2,b3,b4;xi,yi)=i((1+eb2b3xi)1/b4b1yi)2

最佳拟合的概念取决于用来衡量拟合质量的目标函数的选择,而该目标函数又取决于产生观测结果的潜在噪声过程。当噪声是高斯噪声时,将差的平方和最小化是正确的做法。在这种情况下,参数的最优值是最大似然估计。

为了使用Ceres求解器来解决这个问题,我们需要定义一个CostFunction来计算给定x和y的残差f及其对b1,b2,b3和b4的导数。根据高等数学中微积分的知识,我们可以算出f的一系列导数:
D 1 f ( b 1 , b 2 , b 3 , b 4 ; x , y ) = 1 ( 1 + e b 2 − b 3 x ) 1 / b 4 D 2 f ( b 1 , b 2 , b 3 , b 4 ; x , y ) = − b 1 e b 2 − b 3 x b 4 ( 1 + e b 2 − b 3 x ) 1 / b 4 + 1 D 3 f ( b 1 , b 2 , b 3 , b 4 ; x , y ) = b 1 x e b 2 − b 3 x b 4 ( 1 + e b 2 − b 3 x ) 1 / b 4 + 1 D 4 f ( b 1 , b 2 , b 3 , b 4 ; x , y ) = b 1 log ⁡ ( 1 + e b 2 − b 3 x ) b 4 2 ( 1 + e b 2 − b 3 x ) 1 / b 4 \begin{split} D_1 f(b_1, b_2, b_3, b_4; x,y) &= \frac{1}{(1+e^{b_2-b_3x})^{1/b_4}}\\ D_2 f(b_1, b_2, b_3, b_4; x,y) &= \frac{-b_1e^{b_2-b_3x}}{b_4(1+e^{b_2-b_3x})^{1/b_4 + 1}} \\ D_3 f(b_1, b_2, b_3, b_4; x,y) &= \frac{b_1xe^{b_2-b_3x}}{b_4(1+e^{b_2-b_3x})^{1/b_4 + 1}} \\ D_4 f(b_1, b_2, b_3, b_4; x,y) & = \frac{b_1 \log\left(1+e^{b_2-b_3x}\right) }{b_4^2(1+e^{b_2-b_3x})^{1/b_4}} \end{split} D1f(b1,b2,b3,b4;x,y)D2f(b1,b2,b3,b4;x,y)D3f(b1,b2,b3,b4;x,y)D4f(b1,b2,b3,b4;x,y)=(1+eb2b3x)1/b41=b4(1+eb2b3x)1/b4+1b1eb2b3x=b4(1+eb2b3x)1/b4+1b1xeb2b3x=b42(1+eb2b3x)1/b4b1log(1+eb2b3x)

根据这些手动计算出的导数,我们现在可以实现CostFunction了:

class Rat43Analytic : public SizedCostFunction<1,4> {public:Rat43Analytic(const double x, const double y) : x_(x), y_(y) {}virtual ~Rat43Analytic() {}virtual bool Evaluate(double const* const* parameters,double* residuals,double** jacobians) const {const double b1 = parameters[0][0];const double b2 = parameters[0][1];const double b3 = parameters[0][2];const double b4 = parameters[0][3];residuals[0] = b1 *  pow(1 + exp(b2 -  b3 * x_), -1.0 / b4) - y_;if (!jacobians) return true;double* jacobian = jacobians[0];if (!jacobian) return true;jacobian[0] = pow(1 + exp(b2 - b3 * x_), -1.0 / b4);jacobian[1] = -b1 * exp(b2 - b3 * x_) *pow(1 + exp(b2 - b3 * x_), -1.0 / b4 - 1) / b4;jacobian[2] = x_ * b1 * exp(b2 - b3 * x_) *pow(1 + exp(b2 - b3 * x_), -1.0 / b4 - 1) / b4;jacobian[3] = b1 * log(1 + exp(b2 - b3 * x_)) *pow(1 + exp(b2 - b3 * x_), -1.0 / b4) / (b4 * b4);return true;}private:const double x_;const double y_;};

这是一段冗长乏味的代码,难以阅读,并且有很多冗余。所以在实践中,我们会缓存一些子表达式来提高它的效率,这将会得到如下结果:

class Rat43AnalyticOptimized : public SizedCostFunction<1,4> {public:Rat43AnalyticOptimized(const double x, const double y) : x_(x), y_(y) {}virtual ~Rat43AnalyticOptimized() {}virtual bool Evaluate(double const* const* parameters,double* residuals,double** jacobians) const {const double b1 = parameters[0][0];const double b2 = parameters[0][1];const double b3 = parameters[0][2];const double b4 = parameters[0][3];const double t1 = exp(b2 -  b3 * x_);const double t2 = 1 + t1;const double t3 = pow(t2, -1.0 / b4);residuals[0] = b1 * t3 - y_;if (!jacobians) return true;double* jacobian = jacobians[0];if (!jacobian) return true;const double t4 = pow(t2, -1.0 / b4 - 1);jacobian[0] = t3;jacobian[1] = -b1 * t1 * t4 / b4;jacobian[2] = -x_ * jacobian[1];jacobian[3] = b1 * log(t2) * t3 / (b4 * b4);return true;}private:const double x_;const double y_;};

这两种实现在性能上有什么不同?

CostFunction

Time (ns)

Rat43Analytic

255

Rat43AnalyticOptimized

92

Rat43AnalyticOptimizedRat43Analytic快2.8倍。这种运行时上的差异并不少见。为了从分析计算的导数中获得最佳性能,通常需要优化代码以考虑公共子表达式。

什么时候应该使用analytical derivatives?

  • 1.表达式很简单,例如大部分是线性的

  • 2.像Maple、Mathematica或symy这样的计算机代数系统可以用来符号化地区分目标函数,并生成c++来计算它们。

  • 3.式子中有一些代数结构可以实现比自动微分有更好的性能。
    也就是说, 获得在计算倒数之外的最大性能需要大量的工作.在沿着这条路径走下去之前,评估雅可比矩阵的计算花费是整个求解时间的一小部分是很有用的,,记住Amdahl法则是你的朋友。

  • 4.没有其他方法来计算导数,例如你想要计算一个多项式的根的导数:
    a 3 ( x , y ) z 3 + a 2 ( x , y ) z 2 + a 1 ( x , y ) z + a 0 ( x , y ) = 0 a_3(x,y)z^3 + a_2(x,y)z^2 + a_1(x,y)z + a_0(x,y) = 0 a3(x,y)z3+a2(x,y)z2+a1(x,y)z+a0(x,y)=0

    对于x,y,这就需要用到反函数定理

  • 5.你喜欢链式法则也喜欢手动计算代数运算。


http://www.ppmy.cn/news/75229.html

相关文章

小红书数据分析:如何用ChatGPT输出爆文笔记

ChatGPT的热度依旧不减&#xff0c;随着技术升级&#xff0c;越来越多更高级的玩法被发掘。今天我们就来聊聊&#xff0c;如何用ChatGPT写出小红书风格的文章。 首先&#xff0c;小红书笔记制作分为两个步骤&#xff1a; 1、找选题 2、写小红书风格的笔记 我们用例子说话&a…

SQL执行过程

1. select 语句执行过程 一条 select 语句的执行过程如上图所示 1、建立连接 连接器会校验你输入的用户名和密码是否正确&#xff0c;如果错误会返回提示&#xff0c;如果正确&#xff0c;连接器会查询当前用户对于的权限。连接器的作用就是校验用户权限 2、查询缓存 MySQL…

17.plantUML画类图的语法、组合关系和聚合关系之间的区别

文章目录 plantUML画类图的语法组合关系和聚合关系之间的区别依赖关系和关联关系的区别一个类图语法示例 plantUML画类图的语法 泛化关系就是继承关系 语法解释&#xff1a;<|-- 表示组合&#xff0c;<|-表示继承 表示 public&#xff0c; #表示protect - 表示 private…

新华三发布绿洲平台3.0,五大能力升级,构筑坚实用数底座

当前我国数字经济飞速发展&#xff0c;据中国信息通信研究院发布的《中国数字经济发展研究报告&#xff08;2023年&#xff09;》显示&#xff0c;2022年&#xff0c;我国数字经济规模达到50.2万亿元&#xff0c;同比名义增长10.3%&#xff0c;已连续11年显著高于同期GDP名义增…

阿里国际数字商业持续增长背后,蒋凡正在经历“考验”

出品 | 何玺 排版 | 叶媛 5月18日&#xff0c;阿里巴巴集团发布2023财年第四季度及全年业绩。财报显示&#xff0c;2023财年阿里总收入8686.87亿元&#xff08;合1264.91亿美元&#xff09;&#xff0c;同比增长了2%&#xff1b;经营收入为人民币1003.51亿元合14,612百万美元&…

深入探索SDL游戏开发

前言 欢迎来到小K的SDL专栏第二小节&#xff0c;本节将为大家带来基本窗口构成、渲染器、基本图形绘制、贴图、事件处理等的详细讲解&#xff0c;看完后希望对你有收获 文章目录 前言一、简单窗口二、渲染器三、基本图形绘制1、点2、线3、矩形4、圆和椭圆 四、贴图五、事件处理…

手把手教你接入网站微信支付

文章目录 为何需要接入微信支付&#xff1f;申请微信公众号申请商户号Java SDK代码示例支付流程Native API的使用示例支付结果通知 第三方支付平台相关法规相关链接支付宝支付接入 为何需要接入微信支付&#xff1f; 小摊小贩们在线下交易一般无需接入微信支付&#xff0c;只需…

lwIP更新记01:全局互斥锁替代消息机制

从 lwIP-2.0.0 开始&#xff0c;在 opt.h 中多了一个宏开关 LWIP_TCPIP_CORE_LOCKING&#xff0c;默认使能。这个宏用于启用 内核锁定 功能&#xff0c;使用 全局互斥锁 实现。在之前&#xff0c;lwIP 使用 消息机制 解决 lwIP 内核线程安全问题。消息机制易于实现&#xff0c;…