虽然Ceres Solver的大部分致力于解决非线性最小二乘问题,但它内部包含一个求解器,可以解决一般的无约束优化问题,只使用其目标函数值和梯度。GradientProblem和GradientProblemSolver对象让用户可以访问这个求解器。
所以没有太多的麻烦,让我们看看如何使用它们。
Rosenbrock’s Function
我们考虑著名的Rosenbrock函数的最小化问题。我们首先定义一个FirstOrderFunction接口的实例。这是在Ceres定义非线性最小二乘问题时的成本函数的模拟。
class Rosenbrock : public ceres::FirstOrderFunction {
public:
virtual bool Evaluate(const double* parameters,
double* cost,
double* gradient) const {
const double x = parameters[0];
const double y = parameters[1];
cost[0] = (1.0 - x) * (1.0 - x) + 100.0 * (y - x * x) * (y - x * x);
if (gradient != nullptr) {
// 对x求导数
gradient[0] = -2.0 * (1.0 - x) - 200.0 * (y - x * x) * 2.0 * x;
// 对y求导数
gradient[1] = 200.0 * (y - x * x);
}
return true;
}
virtual int NumParameters() const { return 2; }
};
然后,通过构造GradientProblem对象并在其上调用Solve(),就可以简单地将其最小化。
double parameters[2] = {-1.2, 1.0};
ceres::GradientProblem problem(new Rosenbrock());
ceres::GradientProblemSolver::Options options;
options.minimizer_progress_to_stdout = true;
ceres::GradientProblemSolver::Summary summary;
ceres::Solve(options, problem, parameters, &summary);
std::cout << summary.FullReport() << "\n";
执行此代码结果,使用有限内存的BFGS算法解决问题。
代码示例在examples/rosenbrock.cc