首页 > 其他分享 >cereas学习(1)min(10-x)平方

cereas学习(1)min(10-x)平方

时间:2023-01-03 00:55:24浏览次数:72  
标签:10 ceres const jacobians cereas min cost double problem

 

http://ceres-solver.org/nnls_tutorial.html

 

 

 

 

 

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

  这里要注意的重要一点是这operator()是一个模板化方法,它假定它的所有输入和输出都是某种类型的 T。此处模板的使用允许 Ceres在仅需要残差值时调用 CostFunctor::operator<T>(), 以及在需要雅可比行列式时调用特殊类型。在衍生品中,我们将更详细地讨论向 Ceres 提供衍生品的各种方式。T=doubleT=Jet

一旦我们有了计算残差函数的方法,现在就可以使用它构建一个非线性最小二乘问题并让 Ceres 解决它。

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);

  // The variable to solve for with its initial value.
  double initial_x = 5.0;
  double x = initial_x;

  // Build the problem.
  Problem problem;

  // Set up the only cost function (also known as residual). This uses
  // auto-differentiation to obtain the derivative (jacobian).
  CostFunction* cost_function =
      new AutoDiffCostFunction<CostFunctor, 1, 1>(new CostFunctor);
  problem.AddResidualBlock(cost_function, nullptr, &x);

  // Run the solver!
  Solver::Options options;
  options.linear_solver_type = ceres::DENSE_QR;
  options.minimizer_progress_to_stdout = true;
  Solver::Summary summary;
  Solve(options, &problem, &summary);

  std::cout << summary.BriefReport() << "\n";
  std::cout << "x : " << initial_x
            << " -> " << x << "\n";
  return 0;
}

  

AutoDiffCostFunction将 aCostFunctor作为输入,自动区分它并为其提供CostFunction 接口。

编译运行examples/helloworld.cc 给我们

iter      cost      cost_change  |gradient|   |step|    tr_ratio  tr_radius  ls_iter  iter_time  total_time
   0  4.512500e+01    0.00e+00    9.50e+00   0.00e+00   0.00e+00  1.00e+04       0    5.33e-04    3.46e-03
   1  4.511598e-07    4.51e+01    9.50e-04   9.50e+00   1.00e+00  3.00e+04       1    5.00e-04    4.05e-03
   2  5.012552e-16    4.51e-07    3.17e-08   9.50e-04   1.00e+00  9.00e+04       1    1.60e-05    4.09e-03
Ceres Solver Report: Iterations: 2, Initial cost: 4.512500e+01, Final cost: 5.012552e-16, Termination: CONVERGENCE
x : 0.5 -> 10

  

从一个开始x=5,求解器在两次迭代中变为 10 2。细心的读者会注意到这是一个线性问题,一次线性求解应该足以得到最优值。求解器的默认配置是针对非线性问题的,为了简单起见,我们在这个例子中没有改变它。确实有可能在一次迭代中使用 Ceres 获得此问题的解决方案。另请注意,求解器在第一次迭代中确实非常接近最佳函数值 0。我们将在讨论 Ceres 的收敛和参数设置时更详细地讨论这些问题。

脚注

1个

例子/helloworld.cc

2个

实际上求解器运行了三次迭代,它通过查看线性求解器在第三次迭代中返回的值,观察到参数块的更新太小并宣布收敛。Ceres 仅在迭代结束时打印出显示,并在检测到收敛时立即终止,这就是为什么您在这里只看到两次迭代而不是三个。

#include "ceres/ceres.h"
#include "glog/logging.h"
using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solve;
using ceres::Solver;
// A templated cost functor that implements the residual r = 10 -
// x. The method operator() is templated so that we can then use an
// automatic differentiation wrapper around it to generate its
// derivatives.
//残差定义
struct CostFunctor {
  template <typename T>
  bool operator()(const T* const x, T* residual) const {
    residual[0] = 10.0 - x[0];
    return true;
  }
};
int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  // The variable to solve for with its initial value. It will be
  // mutated in place by the solver.
  //初始值
  double x = 0.5;
  const double initial_x = x;
  // Build the problem.
  Problem problem;
  // Set up the only cost function (also known as residual). This uses
  // auto-differentiation to obtain the derivative (jacobian).
  //<CostFunctor, 1, 1>  残差1 纬度  待优化变量1纬
  CostFunction* cost_function =
      new AutoDiffCostFunction<CostFunctor, 1, 1>(new CostFunctor);
  problem.AddResidualBlock(cost_function, nullptr, &x);
  // Run the solver!
  Solver::Options options;
  options.minimizer_progress_to_stdout = true;
  Solver::Summary summary;
  Solve(options, &problem, &summary);
  std::cout << summary.BriefReport() << "\n";
  std::cout << "x : " << initial_x << " -> " << x << "\n";
  return 0;
}

/*
运行结果
iter      cost      cost_change  |gradient|   |step|    tr_ratio  tr_radius  ls_iter  iter_time  total_time
   0  4.512500e+01    0.00e+00    9.50e+00   0.00e+00   0.00e+00  1.00e+04       0    5.33e-04    3.46e-03
   1  4.511598e-07    4.51e+01    9.50e-04   9.50e+00   1.00e+00  3.00e+04       1    5.00e-04    4.05e-03
   2  5.012552e-16    4.51e-07    3.17e-08   9.50e-04   1.00e+00  9.00e+04       1    1.60e-05    4.09e-03
Ceres Solver Report: Iterations: 2, Initial cost: 4.512500e+01, Final cost: 5.012552e-16, Termination: CONVERGENCE
x : 0.5 -> 10

*/

  

解析导数

在某些情况下,无法使用自动微分。例如,以封闭形式计算导数可能比依赖自动微分代码使用的链式法则更有效。

在这种情况下,可以提供您自己的残差和雅可比计算代码。为此, 如果您在编译时知道参数和残差的大小,请定义CostFunctionor的子类。SizedCostFunction例如,这里是SimpleCostFunctionimplementsf(x)=10−x

 

class QuadraticCostFunction : public ceres::SizedCostFunction<1, 1> {
 public:
  virtual ~QuadraticCostFunction() {}
  virtual bool Evaluate(double const* const* parameters,
                        double* residuals,
                        double** jacobians) const {
    const double x = parameters[0][0];
    residuals[0] = 10 - x;

    // Compute the Jacobian if asked for.
    if (jacobians != nullptr && jacobians[0] != nullptr) {
      jacobians[0][0] = -1;
    }
    return true;
  }
};

  

SimpleCostFunction::Evaluate提供了 的输入数组 parametersresiduals残差输出数组jacobians和 Jacobian 矩阵的输出数组。该jacobians数组是可选的,Evaluate预计会在它非空时进行检查,如果是这种情况,则用残差函数的导数值填充它。在这种情况下,由于残差函数是线性的,因此雅可比行列式是常数4

从上面的代码片段可以看出,实现 CostFunction对象有点繁琐。我们建议,除非您有充分的理由自己管理雅可比计算,否则您可以使用AutoDiffCostFunctionor NumericDiffCostFunction来构建您的残差块。

#include <vector>
#include "ceres/ceres.h"
#include "glog/logging.h"
using ceres::CostFunction;
using ceres::Problem;
using ceres::SizedCostFunction;
using ceres::Solve;
using ceres::Solver;
// A CostFunction implementing analytically derivatives for the
// function f(x) = 10 - x.
class QuadraticCostFunction
    : public SizedCostFunction<1 /* number of residuals */,
                               1 /* size of first parameter */> {
 public:
  bool Evaluate(double const* const* parameters,
                double* residuals,
                double** jacobians) const override {
    double x = parameters[0][0];
    // f(x) = 10 - x.
    residuals[0] = 10 - x;
    // f'(x) = -1. Since there's only 1 parameter and that parameter
    // has 1 dimension, there is only 1 element to fill in the
    // jacobians.
    //
    // Since the Evaluate function can be called with the jacobians
    // pointer equal to nullptr, the Evaluate function must check to see
    // if jacobians need to be computed.
    //
    // For this simple problem it is overkill to check if jacobians[0]
    // is nullptr, but in general when writing more complex
    // CostFunctions, it is possible that Ceres may only demand the
    // derivatives w.r.t. a subset of the parameter blocks.
    if (jacobians != nullptr && jacobians[0] != nullptr) {
      jacobians[0][0] = -1;
    }
    return true;
  }
};
int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  // The variable to solve for with its initial value. It will be
  // mutated in place by the solver.
  double x = 0.5;
  const double initial_x = x;
  // Build the problem.
  Problem problem;
  // Set up the only cost function (also known as residual).
  CostFunction* cost_function = new QuadraticCostFunction;
  problem.AddResidualBlock(cost_function, nullptr, &x);
  // Run the solver!
  Solver::Options options;
  options.minimizer_progress_to_stdout = true;
  Solver::Summary summary;
  Solve(options, &problem, &summary);
  std::cout << summary.BriefReport() << "\n";
  std::cout << "x : " << initial_x << " -> " << x << "\n";
  return 0;
}

  

标签:10,ceres,const,jacobians,cereas,min,cost,double,problem
From: https://www.cnblogs.com/gooutlook/p/17020926.html

相关文章

  • cereas学习(2) 鲍威尔函数 多项式
      structF4{template<typenameT>booloperator()(constT*constx1,constT*constx4,T*residual)const{//f4=sqrt(10)(x1-x4)^2r......
  • 230102_50_RPC底层原理
    packagecom.bill.rpc01;importcom.bill.rpc.common.User;importjava.io.ByteArrayOutputStream;importjava.io.DataInputStream;importjava.io.DataOutputStrea......
  • Win10在线升级Win11
    下载微软官方在线升级工具,直接一键在线升级https://www.microsoft.com/zh-cn/software-download/windows11/  右键菜单一键恢复win10风格,管理员运行以下命令:1、......
  • 力扣110 判断是否是平衡二叉树
    力扣110判断是否是平衡二叉树题目:给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对......
  • 吐血整理!10 个机器学习教程汇总,爱可可推荐!
    今天给大家推荐10个机器学习课程清单,含课程视频。这份教程是由一名来自硅谷的计算机科学家ChipHuyen。ChipHuyen是毕业于斯坦福大学计算机科学理学学士和硕士学位,在那......
  • Vensim7.3.5 WIN10 64位安装步骤
    Vensim7.3.5WIN1064位安装步骤:1.使用“百度网盘客户端”下载Vensim7.3.5软件安装包到电脑磁盘英文路径文件夹下,并解压缩,安装前先断开电脑网络,然后找到VensimPLEx32Setup_......
  • (组合数学笔记)Pólya计数理论_Part.10_Pólya定理的推广——De Bruijn定理的母函数形式
    文章目录写在前面介绍DeBruijn定理的母函数形式,由此《(组合数学笔记)Pólya计数理论》系列完结。引入与Pólya定理的母函数形式的推导类似,首先引入模式清单的概念,并介绍两个......
  • 力扣107 二叉树的层序遍历
    力扣107二叉树的层序遍历题目:给你二叉树的根节点root,返回其节点值自底向上的层序遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)示例1:输入:root......
  • 心流|mind flow
    看视频时候瞎写,防止走神springboot不用配置xml因为注解自带扫描约定大于配置自动配置原理springbootdependencies管理springboot应用所有版本依赖解决了依赖冲突问题......
  • windows10 导致无法进入BIOS 界面
    windows10导致bios无法进入原因:windows的关机默认是假的,压根就没有真正的关机自然不管你怎么操作都无法进入bios。......