天天看點

使用ceres求f(x)=2(x-5)^2極值

Ceres是一個非線性的優化庫,在優化問題中廣泛使用,今天我們就來使用這一優化庫來求解一個函數的極值點​。非線性優化庫優化的原理是在給定初值的條件下不斷計算偏移量,使得待優化參數向着目标函數梯度最小處移動。

使用Ceres優化庫的步驟可以歸納為以下幾步​:

  1. 定義參數塊,主要定義待優化參數的形​式;
  2. 定義殘差塊的計算方式。殘差塊通常關聯若幹個參數塊,對它們進行一些自定義的計算,然後傳回殘內插補點​;
  3. 殘差塊也需要定義雅可比的計算方式​。在Ceres中,你可以使用它提供的“自動求導”功能,也可以手動指定雅可比的計算過程。如果要使用自動求導,那麼殘差塊需要按照特定的寫法書寫;殘差的計算過程應該是一個帶模闆的括号運算符;
  4. 将所有的參數塊和殘差塊加入Ceres定義的Problem對象中,調用Slove函數求解即可​。求解之前,我們可以傳入一些配置資訊,例如疊代次數、終止條件等,也可以使用預設的配置​。
#include <iostream>
#include <ceres/ceres.h>
#include <glog/logging.h>
#include<chrono>
#include <math.h>
#include <algorithm>
using namespace std;
using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solve;
using ceres::Solver;
//x表示待優化參數塊,residual表示殘差塊
//通過非線性優化找到函數梯度下降的自變量的取值。
struct CostFunctor {
  template <typename T>
  bool operator()(const T* const x, T* residual) const {
    residual[0] = 2.0*pow(x[0]-5.0,2);
    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).
  //定義誤差函數,誤差類型,輸入次元,輸出次元
  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;
}
           
使用ceres求f(x)=2(x-5)^2極值

繼續閱讀