使用Ceres优化多维功能

时间:2018-08-10 10:24:53

标签: c++ c++11 optimization multidimensional-array ceres-solver

我想使用Ceres优化n个参数的函数。尽管我确实有明确的成本,但如何找到此函数的梯度尚不清楚。到目前为止,我一直在使用带有数值微分的GSL,但我想我会尝试将Ceres与自动差异一起使用。

我看了一个玩具示例helloworld_analytic_diff.cc,其中他们使用AutoDiff最小化函数f(x)= 0.5(10-x)^ 2并阅读了教程,所以我想我会尝试并将其扩展到二维函数f(x,y)=(10-x)^ 2 +(20- y)^ 2,该函数在x,y = 10,20处具有全局最小值。但是我得到一个有点卡住了:

#include "ceres/ceres.h"
#include "glog/logging.h"

using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solver;
using ceres::Solve;


struct CostFunctor {
  template <typename T> bool operator()(const T* const x, T* residual) const {
      const T x1 = x[0];
      const T y1 = x[1];
      residual[0] = (10.0-x[0]) + (20.0-x[1]);

    return true;
  }
};

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

    double x[2] = {0.5, -3.0};
    const double initial_x[2] = {0.5, -3.0};
    Problem problem;

    CostFunction* cost_function = new AutoDiffCostFunction<CostFunctor, 1, 2>(new CostFunctor);
          problem.AddResidualBlock(cost_function, NULL, &x[0]);

    // 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[0] << ", " << initial_x[0]
        << " -> " << x[0] << ", " << x[1]<< "\n";

    return 0;
}

但是,如果我运行此命令,最终会收敛到不正确的内容,具体取决于最初的猜测:

Ceres Solver Report: Iterations: 3, Initial cost: 5.281250e+02, Final cost: 3.667046e-16, Termination: CONVERGENCE
x : 0.5, 0.5 -> 16.75, 13.25

关于我在这里做错了什么的任何想法? 非常感谢!

1 个答案:

答案 0 :(得分:0)

您的费用函子是错误的。 您要解决的优化问题是

[((10.0-x)+(20.0-y)] ^ 2

不是

(10-x)^ 2 +(20- y)^ 2,

您应该在这里拥有两个成本函子,如下所示:

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

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

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

    double x[2] = {0.5, -3.0};
    const double initial_x[2] = {0.5, -3.0};
    Problem problem;
    problem.AddResidualBlock(new AutoDiffCostFunction<CostFunctor1, 1, 2>(new 
    CostFunctor1), NULL, &x[0]);
    problem.AddResidualBlock(new AutoDiffCostFunction<CostFunctor2, 1, 2>(new 
    CostFunctor2), NULL, &x[0]);

    // 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[0] << ", " << initial_x[0]
        << " -> " << x[0] << ", " << x[1]<< "\n";

    return 0;
}