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)\) 的定义如下:

struct F4 {
template <typename T>
bool operator()(const T* const x1, const T* const x4, T* residual) const {
residual[0] = sqrt(10.0) * (x1[0] - x4[0]) * (x1[0] - x4[0]);
return true;
}
};

\(\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)\)。这样的话,问题将会被定义为如下的格式:

// 赋予初值
double x1 = 3.0; double x2 = -1.0; double x3 = 0.0; double x4 = 1.0; Problem problem; // Add residual terms to the problem using the autodiff
// wrapper to get the derivatives automatically.
problem.AddResidualBlock(
new AutoDiffCostFunction<F1, 1, 1, 1>(new F1), nullptr, &x1, &x2);
problem.AddResidualBlock(
new AutoDiffCostFunction<F2, 1, 1, 1>(new F2), nullptr, &x3, &x4);
problem.AddResidualBlock(
new AutoDiffCostFunction<F3, 1, 1, 1>(new F3), nullptr, &x2, &x3);
problem.AddResidualBlock(
new AutoDiffCostFunction<F4, 1, 1, 1>(new F4), nullptr, &x1, &x4);

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

  • 所有的程序如下所示:
#include <vector>

#include "ceres/ceres.h"
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "ceres/internal/port.h"
using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solve;
using ceres::Solver; struct F1
{
template <typename T>
bool operator()(const T *const x1, const T *const x2, T *residual) const
{
// f1 = x1 + 10 * x2;
residual[0] = x1[0] + 10.0 * x2[0];
return true;
}
}; struct F2
{
template <typename T>
bool operator()(const T *const x3, const T *const x4, T *residual) const
{
// f2 = sqrt(5) (x3 - x4)
residual[0] = sqrt(5.0) * (x3[0] - x4[0]);
return true;
}
}; struct F3
{
template <typename T>
bool operator()(const T *const x2, const T *const x3, T *residual) const
{
// f3 = (x2 - 2 x3)^2
residual[0] = (x2[0] - 2.0 * x3[0]) * (x2[0] - 2.0 * x3[0]);
return true;
}
}; struct F4
{
template <typename T>
bool operator()(const T *const x1, const T *const x4, T *residual) const
{
// f4 = sqrt(10) (x1 - x4)^2
residual[0] = sqrt(10.0) * (x1[0] - x4[0]) * (x1[0] - x4[0]);
return true;
}
}; DEFINE_string(minimizer,
"trust_region",
"Minimizer type to use, choices are: line_search & trust_region"); int main(int argc, char **argv)
{
GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]); double x1 = 3.0;
double x2 = -1.0;
double x3 = 0.0;
double x4 = 1.0; Problem problem;
// Add residual terms to the problem using the autodiff
// wrapper to get the derivatives automatically. The parameters, x1 through
// x4, are modified in place.
problem.AddResidualBlock(
new AutoDiffCostFunction<F1, 1, 1, 1>(new F1), nullptr, &x1, &x2);
problem.AddResidualBlock(
new AutoDiffCostFunction<F2, 1, 1, 1>(new F2), nullptr, &x3, &x4);
problem.AddResidualBlock(
new AutoDiffCostFunction<F3, 1, 1, 1>(new F3), nullptr, &x2, &x3);
problem.AddResidualBlock(
new AutoDiffCostFunction<F4, 1, 1, 1>(new F4), nullptr, &x1, &x4); Solver::Options options;
// LOG_IF(FATAL,
// !ceres::StringToMinimizerType(CERES_GET_FLAG(FLAGS_minimizer),
// &options.minimizer_type))
// << "Invalid minimizer: " << CERES_GET_FLAG(FLAGS_minimizer)
// << ", valid options are: trust_region and line_search."; options.max_num_iterations = 100;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true; // clang-format off
std::cout << "Initial x1 = " << x1
<< ", x2 = " << x2
<< ", x3 = " << x3
<< ", x4 = " << x4
<< "\n";
// clang-format on // Run the solver!
Solver::Summary summary;
Solve(options, &problem, &summary); std::cout << summary.FullReport() << "\n";
// clang-format off
std::cout << "Final x1 = " << x1
<< ", x2 = " << x2
<< ", x3 = " << x3
<< ", x4 = " << x4
<< "\n";
// clang-format on
return 0;
}

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

Initial x1 = 3, x2 = -1, x3 = 0, x4 = 1
iter cost cost_change |gradient| |step| tr_ratio tr_radius ls_iter iter_time total_time
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 Solver Summary (v 1.13.0-eigen-(3.3.4)-lapack-suitesparse-(5.1.2)-cxsparse-(3.1.9)-openmp) Original Reduced
Parameter blocks 4 4
Parameters 4 4
Residual blocks 4 4
Residual 4 4 Minimizer TRUST_REGION Dense linear algebra library EIGEN
Trust region strategy LEVENBERG_MARQUARDT Given Used
Linear solver DENSE_QR DENSE_QR
Threads 1 1
Linear solver threads 1 1
Linear solver ordering AUTOMATIC 4 Cost:
Initial 1.075000e+02
Final 1.120029e-15
Change 1.075000e+02 Minimizer iterations 15
Successful steps 15
Unsuccessful steps 0 Time (in seconds):
Preprocessor 0.0005 Residual evaluation 0.0000
Jacobian evaluation 0.0005
Linear solver 0.0001
Minimizer 0.0009 Postprocessor 0.0000
Total 0.0014 Termination: CONVERGENCE (Gradient tolerance reached. Gradient max norm: 3.642190e-11 <= 1.000000e-10) 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. 2022-11-19:第二高的薪水。表结构和数据的sql语句如下,输出200,因为200是第二大的。请问sql语句如何写? DROP TABLE IF EXISTS `employee`; CREAT

    2022-11-19:第二高的薪水.表结构和数据的sql语句如下,输出200,因为200是第二大的.请问sql语句如何写? DROP TABLE IF EXISTS `employee`; CREAT ...

  2. 2021-02-01:Redis 集群会有写操作丢失吗?

    福哥答案2021-02-01: 以下情况可能导致写操作丢失:1.过期 key 被清理.2.最大内存不足,导致 Redis 自动清理部分 key 以节省空间.3.主库故障后自动重启,从库自动同步.4.单 ...

  3. 2021-02-23:给定一个正数n,求n的裂开方法数。规定:后面的数不能比前面的数小 。比如4的裂开方法有: 1+1+1+1、1+1+2、1+3、2+2、4,5种,所以返回5。

    2021-02-23:给定一个正数n,求n的裂开方法数.规定:后面的数不能比前面的数小 .比如4的裂开方法有: 1+1+1+1.1+1+2.1+3.2+2.4,5种,所以返回5. 福哥答案2021-0 ...

  4. 2022-02-18:最大休假次数。 力扣想让一个最优秀的员工在 N 个城市间旅行来收集算法问题

    2022-02-18:最大休假次数. 力扣想让一个最优秀的员工在 N 个城市间旅行来收集算法问题. 但只工作不玩耍,聪明的孩子也会变傻,所以您可以在某些特定的城市和星期休假. 您的工作就是安排旅行使得 ...

  5. pages.json 文件:globalStyle 全局配置

    globalStyle 用于设置应用的状态栏.导航条.标题.窗口背景色等. 属性 类型 默认值 描述 平台差异说明 navigationBarBackgroundColor HexColor #F7F ...

  6. 500行代码手写docker-以新命名空间运行程序

    (2)500行代码手写docker-以新命名空间运行程序 本系列教程主要是为了弄清楚容器化的原理,纸上得来终觉浅,绝知此事要躬行,理论始终不及动手实践来的深刻,所以这个系列会用go语言实现一个类似do ...

  7. .Net使用第三方onnx或ModelBuilder轻松接入AI模型

    ML.Net - 开源的跨平台机器学习框架 支持CPU/GPU训练 轻松简洁的预测代码 可扩展其他的机器学习平台 跨平台 1.使用Visual Studio的Model Builder训练和使用模型 ...

  8. 代码随想录算法训练营Day18 二叉树

    代码随想录算法训练营 代码随想录算法训练营Day18 二叉树| 513.找树左下角的值 112. 路径总和 113.路径总和ii 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构 ...

  9. 鸟类识别系统Python+Django+TensorFlow+卷积神经网络算法【完整代码】

    一.介绍 鸟类识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法.并通过对数据集进行训练,最后得到一个识别精度较高的模型.并基于Django框架,开 ...

  10. 3 分钟为英语学习神器 Anki 部署一个专属同步服务器

    原文链接:https://icloudnative.io/posts/anki-sync-server/ Anki 介绍 Anki 是一个辅助记忆软件,其本质是一个卡片排序工具--即依据使用者对卡片上 ...