General Unconstrained Minimization

Ceres 求解器除了能求解非线性最小二乘法问题外,还能使用目标函数值和梯度求解一般无约束问题。在本章中,我们将了解如何做到这一点。

Rosenbrock’s Function

考虑尝试最小化 Rosenbrock’s function。最简单方法是定义一个模板函数来评估误差函数,然后使用 Ceres Solver 的自动微分来计算其导数。我们首先定义一个模板化的函数,然后使用 AutoDiffFirstOrderFunction 构造一个 FirstOrderFunction 接口的实例。这个对象负责计算目标函数值和梯度(如果需要)。这与 Ceres 中定义非线性最小二乘法问题时的 CostFunction类似。

// f(x,y) = (1-x)^2 + 100(y - x^2)^2;
struct Rosenbrock {
  template <typename T>
  bool operator()(const T* parameters, T* cost) const {
    const T x = parameters[0];
    const T y = parameters[1];
    cost[0] = (1.0 - x) * (1.0 - x) + 100.0 * (y - x * x) * (y - x * x);
    return true;
  }

  static ceres::FirstOrderFunction* Create() {
    constexpr int kNumParameters = 2;
    return new ceres::AutoDiffFirstOrderFunction<Rosenbrock, kNumParameters>();
  }
};

然后,只需构建一个 GradientProblem 对象并调用 Solve() 即可将其最小化。

执行该代码,使用 limited memory BFGS算法解决问题。

如果由于某种原因无法使用自动微分(例如因为需要调用外部库),那么可以使用数值微分。在这种情况下,函数的定义如下

最后,如果你更愿意手工计算导数(比如因为参数向量太大而无法自动微分)。那么就应该定义 FirstOrderFunction 的实例,它与 CostFunction 类似,适用于非线性最小二乘法问题

Footnotes

Last updated