解析導數
在有些情況下,不使用AutoDiffCostFunction,例如我們用近似的方式計算導數,而不是用AutoDiff的鏈式法則,我們需要自己的殘差和Jacobin計算。這時我們定義一個CostFunction或者SizedCostFunction的子類。
#include <vector>
#include "ceres/ceres.h"
#include "glog/logging.h"
using ceres::CostFunction;
using ceres::SizedCostFunction;
using ceres::Problem;
using ceres::Solver;
using ceres::Solve;
// 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:
virtual ~QuadraticCostFunction() {}
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
double x = parameters[0][0];
// f(x) = 10 - x.
residuals[0] = 10 - x;
if (jacobians != NULL && jacobians[0] != NULL) {
jacobians[0][0] = -1;
}
return true;
}
};
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
// 初始化待優化變量
double x = 0.5;
const double initial_x = x;
// 構建問題
Problem problem;
// 設置殘差函數
CostFunction* cost_function = new QuadraticCostFunction;
problem.AddResidualBlock(cost_function, NULL, &x);
// 構建求解器
Solver::Options options;
// 輸出到cout
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;
}
The jacobians
array is optional, Evaluate
is expected to check when it is non-null, and if it is the case then fill it with the values of the derivative of the residual function.
QuadraticCostFunction::Evaluate
parameters
作爲輸入,residuals
作爲殘差輸出和Jacobians作爲雅可比矩陣的輸出。jacobians
是可選的,Evaluate
is expected to check when it is non-null, and if it is the case then fill it with the values of the derivative of the residual function.在這個例子中,殘差函數是線性的,故而Jacobian是常量。
除非有一個很好的管理Jacobian的理由,否則建議使用AutoDiffCostFunction
或NumericDiffCostFunction
。
CMakeLists.txt文件
cmake_minimum_required(VERSION 2.8)
project(ceres)
find_package(Ceres REQUIRED)
include_directories(${CERES_INCLUDE_DIRS})
add_executable(use_ceres main.cpp)
target_link_libraries(use_ceres ${CERES_LIBRARIES})
有關衍生工具的更多信息
到目前爲止,計算導數是使用Ceres的最複雜的部分,並且根據情況,用戶可能需要更復雜的計算導數的方法。本節僅介紹如何將衍生物提供給Ceres。
當你熟悉了NumericDiffCostFunction
和AutoDiffCostFunction
的使用後,建議在考慮下DynamicAutoDiffCostFunction
, CostFunctionToFunctor
,NumericDiffFunctor
以及 ConditionedCostFunction
更先進的方法構建和計算代價函數。