Ceres 求解 Powell’s function 的最小化

\(\quad\)现在考虑一个稍微复杂一点的例子—鲍威尔函数的最小化。

\(\quad{}\) \(x=[x_1,x_2,x_3,x_4]\) 并且

\[\begin{array}{l}
f_{1}(x)=x_{1}+10 x_{2} \\
f_{2}(x)=\sqrt{5}\left(x_{3}-x_{4}\right) \\
f_{3}(x)=\left(x_{2}-2 x_{3}\right)^{2} \\
f_{4}(x)=\sqrt{10}\left(x_{1}-x_{4}\right)^{2} \\ \\
F(x)=\left[f_{1}(x), f_{2}(x), f_{3}(x), f_{4}(x)\right]
\end{array}
\]

\(\quad{}\) \(F(x)\) 是一个拥有四个参数的函数,并且拥有四个残差块,我们希望找到一个 \(x\) 使得下面的式子得到最小化:

\[\frac{1}{2}||F(x)||^2
\]

\(\quad{}\)同样,第一步是定义对目标函子中的项进行评估的函子。 这是评估的代码,翻译过来不太准确,或者说这其实是在定义残差块。对 \(f_4(x_1,x_4)\) 的定义如下:

  1. struct F4 {
  2. template <typename T>
  3. bool operator()(const T* const x1, const T* const x4, T* residual) const {
  4. residual[0] = sqrt(10.0) * (x1[0] - x4[0]) * (x1[0] - x4[0]);
  5. return true;
  6. }
  7. };

\(\quad{}\) 同样,我们也可以类似的定义 \(F_1\), \(F_2\) 和 \(F_3\) 去评估计算 \(f_1(x_1,x_2)\),\(f_2(x_3,x_4)\),\(f_3(x_2,x_3)\)。这样的话,问题将会被定义为如下的格式:

  1. // 赋予初值
  2. double x1 = 3.0; double x2 = -1.0; double x3 = 0.0; double x4 = 1.0;
  3. Problem problem;
  4. // Add residual terms to the problem using the autodiff
  5. // wrapper to get the derivatives automatically.
  6. problem.AddResidualBlock(
  7. new AutoDiffCostFunction<F1, 1, 1, 1>(new F1), nullptr, &x1, &x2);
  8. problem.AddResidualBlock(
  9. new AutoDiffCostFunction<F2, 1, 1, 1>(new F2), nullptr, &x3, &x4);
  10. problem.AddResidualBlock(
  11. new AutoDiffCostFunction<F3, 1, 1, 1>(new F3), nullptr, &x2, &x3);
  12. problem.AddResidualBlock(
  13. new AutoDiffCostFunction<F4, 1, 1, 1>(new F4), nullptr, &x1, &x4);

\(\quad{}\) 请注意,每个 ResidualBlock 仅依赖于对应残差对象所依赖的两个参数,而不依赖于所有四个参数。

  • 所有的程序如下所示:
  1. #include <vector>
  2. #include "ceres/ceres.h"
  3. #include "gflags/gflags.h"
  4. #include "glog/logging.h"
  5. #include "ceres/internal/port.h"
  6. using ceres::AutoDiffCostFunction;
  7. using ceres::CostFunction;
  8. using ceres::Problem;
  9. using ceres::Solve;
  10. using ceres::Solver;
  11. struct F1
  12. {
  13. template <typename T>
  14. bool operator()(const T *const x1, const T *const x2, T *residual) const
  15. {
  16. // f1 = x1 + 10 * x2;
  17. residual[0] = x1[0] + 10.0 * x2[0];
  18. return true;
  19. }
  20. };
  21. struct F2
  22. {
  23. template <typename T>
  24. bool operator()(const T *const x3, const T *const x4, T *residual) const
  25. {
  26. // f2 = sqrt(5) (x3 - x4)
  27. residual[0] = sqrt(5.0) * (x3[0] - x4[0]);
  28. return true;
  29. }
  30. };
  31. struct F3
  32. {
  33. template <typename T>
  34. bool operator()(const T *const x2, const T *const x3, T *residual) const
  35. {
  36. // f3 = (x2 - 2 x3)^2
  37. residual[0] = (x2[0] - 2.0 * x3[0]) * (x2[0] - 2.0 * x3[0]);
  38. return true;
  39. }
  40. };
  41. struct F4
  42. {
  43. template <typename T>
  44. bool operator()(const T *const x1, const T *const x4, T *residual) const
  45. {
  46. // f4 = sqrt(10) (x1 - x4)^2
  47. residual[0] = sqrt(10.0) * (x1[0] - x4[0]) * (x1[0] - x4[0]);
  48. return true;
  49. }
  50. };
  51. DEFINE_string(minimizer,
  52. "trust_region",
  53. "Minimizer type to use, choices are: line_search & trust_region");
  54. int main(int argc, char **argv)
  55. {
  56. GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
  57. google::InitGoogleLogging(argv[0]);
  58. double x1 = 3.0;
  59. double x2 = -1.0;
  60. double x3 = 0.0;
  61. double x4 = 1.0;
  62. Problem problem;
  63. // Add residual terms to the problem using the autodiff
  64. // wrapper to get the derivatives automatically. The parameters, x1 through
  65. // x4, are modified in place.
  66. problem.AddResidualBlock(
  67. new AutoDiffCostFunction<F1, 1, 1, 1>(new F1), nullptr, &x1, &x2);
  68. problem.AddResidualBlock(
  69. new AutoDiffCostFunction<F2, 1, 1, 1>(new F2), nullptr, &x3, &x4);
  70. problem.AddResidualBlock(
  71. new AutoDiffCostFunction<F3, 1, 1, 1>(new F3), nullptr, &x2, &x3);
  72. problem.AddResidualBlock(
  73. new AutoDiffCostFunction<F4, 1, 1, 1>(new F4), nullptr, &x1, &x4);
  74. Solver::Options options;
  75. // LOG_IF(FATAL,
  76. // !ceres::StringToMinimizerType(CERES_GET_FLAG(FLAGS_minimizer),
  77. // &options.minimizer_type))
  78. // << "Invalid minimizer: " << CERES_GET_FLAG(FLAGS_minimizer)
  79. // << ", valid options are: trust_region and line_search.";
  80. options.max_num_iterations = 100;
  81. options.linear_solver_type = ceres::DENSE_QR;
  82. options.minimizer_progress_to_stdout = true;
  83. // clang-format off
  84. std::cout << "Initial x1 = " << x1
  85. << ", x2 = " << x2
  86. << ", x3 = " << x3
  87. << ", x4 = " << x4
  88. << "\n";
  89. // clang-format on
  90. // Run the solver!
  91. Solver::Summary summary;
  92. Solve(options, &problem, &summary);
  93. std::cout << summary.FullReport() << "\n";
  94. // clang-format off
  95. std::cout << "Final x1 = " << x1
  96. << ", x2 = " << x2
  97. << ", x3 = " << x3
  98. << ", x4 = " << x4
  99. << "\n";
  100. // clang-format on
  101. return 0;
  102. }

\(\quad{}\) 编译并运行可得到如下输出:

  1. Initial x1 = 3, x2 = -1, x3 = 0, x4 = 1
  2. iter cost cost_change |gradient| |step| tr_ratio tr_radius ls_iter iter_time total_time
  3. 0 1.075000e+02 0.00e+00 1.55e+02 0.00e+00 0.00e+00 1.00e+04 0 5.89e-05 5.71e-04
  4. 1 5.036190e+00 1.02e+02 2.00e+01 2.16e+00 9.53e-01 3.00e+04 1 1.80e-04 7.80e-04
  5. 2 3.148168e-01 4.72e+00 2.50e+00 6.23e-01 9.37e-01 9.00e+04 1 3.90e-05 8.32e-04
  6. 3 1.967760e-02 2.95e-01 3.13e-01 3.08e-01 9.37e-01 2.70e+05 1 3.65e-05 8.79e-04
  7. 4 1.229900e-03 1.84e-02 3.91e-02 1.54e-01 9.37e-01 8.10e+05 1 3.57e-05 9.23e-04
  8. 5 7.687123e-05 1.15e-03 4.89e-03 7.69e-02 9.37e-01 2.43e+06 1 3.54e-05 9.67e-04
  9. 6 4.804625e-06 7.21e-05 6.11e-04 3.85e-02 9.37e-01 7.29e+06 1 3.52e-05 1.01e-03
  10. 7 3.003028e-07 4.50e-06 7.64e-05 1.92e-02 9.37e-01 2.19e+07 1 3.53e-05 1.05e-03
  11. 8 1.877006e-08 2.82e-07 9.54e-06 9.62e-03 9.37e-01 6.56e+07 1 3.53e-05 1.10e-03
  12. 9 1.173223e-09 1.76e-08 1.19e-06 4.81e-03 9.37e-01 1.97e+08 1 3.58e-05 1.15e-03
  13. 10 7.333425e-11 1.10e-09 1.49e-07 2.40e-03 9.37e-01 5.90e+08 1 3.54e-05 1.19e-03
  14. 11 4.584044e-12 6.88e-11 1.86e-08 1.20e-03 9.37e-01 1.77e+09 1 3.51e-05 1.24e-03
  15. 12 2.865573e-13 4.30e-12 2.33e-09 6.02e-04 9.37e-01 5.31e+09 1 3.55e-05 1.28e-03
  16. 13 1.791438e-14 2.69e-13 2.91e-10 3.01e-04 9.37e-01 1.59e+10 1 3.55e-05 1.32e-03
  17. 14 1.120029e-15 1.68e-14 3.64e-11 1.51e-04 9.37e-01 4.78e+10 1 3.54e-05 1.37e-03
  18. Solver Summary (v 1.13.0-eigen-(3.3.4)-lapack-suitesparse-(5.1.2)-cxsparse-(3.1.9)-openmp)
  19. Original Reduced
  20. Parameter blocks 4 4
  21. Parameters 4 4
  22. Residual blocks 4 4
  23. Residual 4 4
  24. Minimizer TRUST_REGION
  25. Dense linear algebra library EIGEN
  26. Trust region strategy LEVENBERG_MARQUARDT
  27. Given Used
  28. Linear solver DENSE_QR DENSE_QR
  29. Threads 1 1
  30. Linear solver threads 1 1
  31. Linear solver ordering AUTOMATIC 4
  32. Cost:
  33. Initial 1.075000e+02
  34. Final 1.120029e-15
  35. Change 1.075000e+02
  36. Minimizer iterations 15
  37. Successful steps 15
  38. Unsuccessful steps 0
  39. Time (in seconds):
  40. Preprocessor 0.0005
  41. Residual evaluation 0.0000
  42. Jacobian evaluation 0.0005
  43. Linear solver 0.0001
  44. Minimizer 0.0009
  45. Postprocessor 0.0000
  46. Total 0.0014
  47. Termination: CONVERGENCE (Gradient tolerance reached. Gradient max norm: 3.642190e-11 <= 1.000000e-10)
  48. Final x1 = 0.000146222, x2 = -1.46222e-05, x3 = 2.40957e-05, x4 = 2.40957e-05

\(\quad{}\) 其实我们很容易看出函数的最优解在 \(x_1=0, x_2=0,x_3=0,x_4=0\) ,而最终的计算结果虽然并不是完全为\(0\) 但是也基本接近。

Ceres简单应用-求解(Powell's Function)鲍威尔函数最小值的更多相关文章

  1. c++ virturn function -- 虚函数

    c++ virturn function -- 虚函数 pure irtual function  -- 纯虚函数   先看例子 #include <iostream> using nam ...

  2. [ES6系列-07]Generator Function: 生成器函数

    [原创]码路工人 Coder-Power 大家好,这里是码路工人有力量,我是码路工人,你们是力量. github-pages 博客园cnblogs Generator function 生成器函数是E ...

  3. cost function 成本函数

    cost function 成本函数 cost function-成本函数 1.目标 :实现和探索具有一个变量的线性回归的成本函数. import numpy as np %matplotlib wi ...

  4. function foo(){}、(function(){})、(function(){}())等函数区别分析

    前面一段时间,看到(function(){}),(function(){}())这些函数就犯晕,不知道它到底是什么意思,为什么函数外要加小括号,函数后要加小括号,加和不加到底有什么区别……一直犯迷糊, ...

  5. js function定义函数的4种方法

    js function定义函数的4种方法 1.最基本的作为一个本本分分的函数声明使用. 复制代码代码如下: 复制代码代码如下: function func(){} 或 var func=functio ...

  6. Shell脚本中使用function(函数)示例

    这篇文章主要介绍了Shell脚本中使用function(函数)示例,本文着重讲解的是如何在shell脚本中使用自定义函数,并给出了两个例子,需要的朋友可以参考下   函数可以在shell script ...

  7. ECMAScript基本对象——function定义函数

    function:函数对象=java方法,java的方法或者函数是,java对象的一部分. JavaScript的函数或者方法,就是一个对象实参:都必须具有确定的值, 以便把这些值传送给形参. 形参: ...

  8. JS function 是函数也是对象, 浅谈原型链

    JS function 是函数也是对象, 浅谈原型链 JS 唯一支持的继承方式是通过原型链继承, 理解好原型链非常重要, 我记录下我的理解 1. 前言 new 出来的实例有 _proto_ 属性, 并 ...

  9. 十一、Powell算法(鲍威尔算法)原理以及实现

    一.介绍 Powell算法是图像配准里面的常用的加速算法,可以加快搜索速度,而且对于低维函数的效果很好,所以本篇博客主要是为了介绍Powell算法的原理以及实现. 由于网上已经有了对于Powell算法 ...

  10. 简单遗传算法求解n皇后问题

    版权声明:本文为博主原创文章,转载请注明出处. 先解释下什么是8皇后问题:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法.在不 ...

随机推荐

  1. PostgreSQL-HA 高可用集群在 Rainbond 上的部署方案

    PostgreSQL 是一种流行的开源关系型数据库管理系统.它提供了标准的SQL语言接口用于操作数据库. repmgr 是一个用于 PostgreSQL 数据库复制管理的开源工具.它提供了自动化的复制 ...

  2. 卧槽Winform也可以这么好看?

    Winform也可以这么好看? 对于Winform很多人的刻板印象就是拖拉拽,简单生产界面,但是这样对于界面的效果,它并不会很好,虽然简单,快,但是效果也是极差,所以有很多人就去使用WPF,去写xml ...

  3. 2022-05-06:给你一个整数数组 arr,请你将该数组分隔为长度最多为 k 的一些(连续)子数组。分隔完成后,每个子数组的中的所有值都会变为该子数组中的最大值。 返回将数组分隔变换后能够得到的元

    2022-05-06:给你一个整数数组 arr,请你将该数组分隔为长度最多为 k 的一些(连续)子数组.分隔完成后,每个子数组的中的所有值都会变为该子数组中的最大值. 返回将数组分隔变换后能够得到的元 ...

  4. 2021-10-24:快乐数。编写一个算法来判断一个数 n 是不是快乐数。「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是

    2021-10-24:快乐数.编写一个算法来判断一个数 n 是不是快乐数.「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和.然后重复这个过程直到这个数变为 1,也可能是 ...

  5. 华为Atlas 200I DK A2开箱!

    摘要:Atlas 200I DK A2是Atlas 200DK之后的一款产品,从2022年一直酝酿至今,终于在2023年5月6日-7日昇腾AI开发者峰会2023正式发布. 本文分享自华为云社区< ...

  6. AcWing 1023. 买书

    小明手里有n元钱全部用来买书,书的价格为10元,20元,50元,100元. 问小明有多少种买书方案?(每种书可购买多本) 输入格式 一个整数 n,代表总共钱数. 输出格式 一个整数,代表选择方案种数. ...

  7. NeoVim 学习笔记

    NeoVim 学习笔记 这篇学习笔记将用于记录本人在学习使用 NeoVim 编辑器过程中所编写的学习心得与代码.该笔记将会存放在https://github.com/owlman/study_note ...

  8. 基于渗透的python

    Python for Pentesters 还记得开始学习编程的C,虽然淡忘,但思想仍在. 子域名枚举 request库 import pyfiglet import requests import ...

  9. @SuppressWarnings注解的使用

    Java编译器在编译代码时,会产生一些安全警告信息.如果被@SuppressWarnings注解标记的元素,就可以告诉编译器抑制指定的警告. 先看看@SuppressWarnings注解在Java S ...

  10. PHP文件包含总结

    1.文件包含小知识 1.1 包含函数 PHP共有4个与文件包含相关的函数: include require include_once require_once include与include_once ...