Ceres 學習 安裝、編譯、求解Options參數
1. 基礎
Ceres solver 是谷歌開發的一款用於非線性優化的庫,在谷歌的開源激光雷達slam項目cartographer中被大量使用。Ceres官網上的文檔非常詳細地介紹了其具體使用方法。文檔轉入
1.1 下載
- 可以在github上直接下載,或者直接克隆 git clone https://ceres-solver.googlesource.com/ceres-solver
- 或者查看幫助文檔
1.2 Linux 安裝
1.2.1 依賴安裝
# CMake
sudo apt-get install cmake
# google-glog + gflags
sudo apt-get install libgoogle-glog-dev
# BLAS & LAPACK
sudo apt-get install libatlas-base-dev
# Eigen3
sudo apt-get install libeigen3-dev
# SuiteSparse and CXSparse (optional)
# - If you want to build Ceres as a *static* library (the default)
# you can use the SuiteSparse package in the main Ubuntu package
# repository:
sudo apt-get install libsuitesparse-dev
# - However, if you want to build Ceres as a *shared* library, you must
# add the following PPA:
sudo add-apt-repository ppa:bzindovic/suitesparse-bugfix-1319687
sudo apt-get update
sudo apt-get install libsuitesparse-dev
1.2. 2 安裝
tar zxf ceres-solver-1.14.0.tar.gz
mkdir ceres-bin
cd ceres-bin
cmake ../ceres-solver-1.14.0
make -j3
make test
# Optionally install Ceres, it can also be exported using CMake which
# allows Ceres to be used without requiring installation, see the documentation
# for the EXPORT_BUILD_DIR option for more information.
make install
1.2.3 測試
您還可以嘗試運行命令行捆綁應用程序,其中包含一個包含的問題,這些問題來自華盛頓大學的BAL數據集[Agarwal]。
bin/simple_bundle_adjuster ../ceres-solver-1.14.0/data/problem-16-22106-pre.txt
1.3 簡易使用
- Ceres必須已安裝 make install,
1.3.1 cmake中
簡單helloworld
find_package(Ceres REQUIRED)
include_directories(${CERES_INCLUDE_DIRS})
# helloworld
add_executable(helloworld helloworld.cc)
target_link_libraries(helloworld ${CERES_LIBRARIES})
1.3.2 ros package
cmakelists.txt中
find_package(Ceres REQUIRED COMPONENTS SuiteSparse)
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC
"${CERES_INCLUDE_DIRS}")
target_link_libraries(${PROJECT_NAME} PUBLIC ${CERES_LIBRARIES})
package.xml 中
<depend>ceres-solver</depend>
注意:
- 在調用find_package(Ceres)時,您可以指定所需的特定Ceres組件(以便將Ceres報告爲已找到)。 這允許您指定,例如,您需要使用SuiteSparse支持構建的Ceres版本。 根據定義,如果在調用find_package(Ceres)時沒有指定任何組件(默認值),則檢測到的任何Ceres版本都將被報告爲found,而不管它是使用哪個組件構建的。
LAPACK: Ceres built using LAPACK (LAPACK=ON).
SuiteSparse: Ceres built with SuiteSparse (SUITESPARSE=ON).
CXSparse: Ceres built with CXSparse (CXSPARSE=ON).
EigenSparse: Ceres built with Eigen’s sparse Cholesky factorization (EIGENSPARSE=ON).
SparseLinearAlgebraLibrary: Ceres built with at least one sparse linear algebra library. This is equivalent to SuiteSparse OR CXSparse OR EigenSparse.
SchurSpecializations: Ceres built with Schur specializations (SCHUR_SPECIALIZATIONS=ON).
OpenMP: Ceres built with OpenMP (OPENMP=ON).
TBB: Ceres built with Intel Thread Building Blocks (TBB) (TBB=ON).
Multithreading: Ceres built with a multithreading library. This is equivalent to OpenMP OR TBB.
C++11: Ceres built with C++11 (CXX11=ON).
1.4 指定版本+本地安裝
此外,當CMake找到Ceres時,它可以選擇檢查包版本,如果已在find_package()調用中指定。例如:
find_package(Ceres 1.2.3 REQUIRED)
本地安裝
如果通過指定-DCMAKE_INSTALL_PREFIX =“/ some / where / local”將Ceres安裝在非標準路徑中,則用戶應將PATHS選項添加到find_package()命令,例如:
find_package(Ceres REQUIRED PATHS "/some/where/local/")
1.5 使用步驟
使用Ceres求解非線性優化問題,一共分爲三個部分:
- 第一部分:構建cost fuction,即代價函數,也就是尋優的目標式。這個部分需要使用仿函數(functor)這一技巧來實現,做法是定義一個cost function的結構體,在結構體內重載()運算符,具體實現方法後續介紹。
- 第二部分:通過代價函數構建待求解的優化問題。
- 第三部分:配置求解器參數並求解問題,這個步驟就是設置方程怎麼求解、求解過程是否輸出等,然後調用一下Solve方法。
2. Ceres的Options詳解
Ceres是一個非常優秀的非線性優化庫(谷歌出品)。能完成很複雜的優化功能,選項也非常的多,本篇博客就來梳理下這些選項。Ceres的參數主要有三類,一類通用參數,比如迭代次數什麼的;第二類是和優化算法的參數;第三類是和線性求解器(在信任域算法中被使用)有關的參數。
2.1 常用參數
- bool Solver::Options::IsValid(string *error) const
檢查options是否合法,不合法的話返回false,並將錯誤信息存到error裏面。 - int Solver::Options::max_num_iterations
默認值:50
最大迭代次數。 - double Solver::Options::max_solver_time_in_seconds
默認值:1e6
最長運行時間,單位爲秒。 - int Solver::Options::num_threads
默認值:1
Ceres用於評估Jacobian的線程數,越多優化速度越快。 - DenseLinearAlgebraLibrary Solver::Options::dense_linear_algebra_library_type
默認值:EIGEN
Ceres支持使用多個密集線性代數庫進行稠密矩陣分解。 目前可選的爲EIGEN和LAPACK。 EIGEN始終可用;LAPACK指的是BLAS + LAPACK庫,可能有也可能沒有(得看編譯Ceres庫時有沒有加入BLAS + LAPACK的支持)。此設置會影響DENSE_QR,DENSE_NORMAL_CHOLESKY和DENSE_SCHUR求解器。 對於小到中等大小的求解器(這裏的大小應該是指運算量,也就是問題規模的大小),EIGEN是一個很好的選擇,但對於大問題,LAPACK + BLAS實現可以在性能上優勢很大。 - SparseLinearAlgebraLibrary Solver::Options::sparse_linear_algebra_library_type
默認值:SUITE_SPARSE > CX_SPARSE > EIGEN_SPARSE > NO_SPARSE
Ceres支持使用三個稀疏線性代數庫SuiteSparse、CXSparse、EIGEN_SPARSE ,NO_SPARSE意味着不應使用稀疏線性求解器。
SuiteSparse:高性能稀疏Cholesky分解和近似最低學位排序是一個非常複雜的稀疏線性代數庫(就是一羣非常牛*的人寫的),性能最好,推薦使用。
CXSparse:SuiteSparse的輕量級替換,不需要 LAPACK / BLAS實現。 因此,它的性能是比SuiteSparse低一點。如果SuiteSparse不可用(編譯Ceres的時候沒有加入SuiteSparse支持),請考慮使用CXSparse,這是一個更小,更容易編譯的庫。但是,它在大問題上的性能與SuiteSparse的性能相差巨大。
EIGEN_SPARSE:Eigen的稀疏線性代數例程,目前,這個庫的表現是三個中最差的。說不定在不久的將來性能會有改善。 - int Solver::Options::num_linear_solver_threads
默認值:-1
這是一個廢棄的選項,將在1.15中刪除。 - LoggingType Solver::Options::logging_type
默認值:PER_MINIMIZER_ITERATION 最小化迭代
每次迭代都打印信息,另一個可選的爲SILENT。(無聲) - bool Solver::Options::minimizer_progress_to_stdout
默認值:false
默認情況下,Minimizer(優化器)進度會記錄到stderr,具體取決於vlog級別。 如果此標誌設置爲true,並且Solver::Option:: logging_type不是SILENT,則日誌記錄輸出將發送到stdout(在終端打印出信息)。 - bool Solver::Options::check_gradients
默認值:false
檢查由具有有限差分的每個殘差塊計算的所有雅可比行列式,比較結果,如果它們大不相同,則優化失敗。如果設置爲true的花比較耗費性能,一般保持默認。 - double Solver::Options::gradient_check_relative_precision
默認值: 1e-8
在gradient checker中檢查的精度。 如果雅可比行列式中的元素之間的相對差異超過此數字,則dump該cost term的雅可比行列式。 - vector Solver::Options::callbacks
在Minimizer的每次迭代結束時執行的回調。
它們按照在此vector中指定的順序執行。 默認情況下,參數僅在優化結束時更新。 如果希望在執行回調時訪問更新的參數,則將Solver::Options::update_state_every_iteration需要設置爲true。 - bool Solver::Options::update_state_every_iteration
默認值:false
如果爲true,則在每個迭代結束時更新參數,否則在優化終止時才更新參數。更多細節請參考鏈接。
2.2 優化方法無關參數
- MinimizerType Solver::Options::minimizer_type
默認值:TRUST_REGION
可選的爲LINE_SEARCH和TRUST_REGION,這是非線性優化的兩類算法。參考:Trust Region Methods 、 Line Search Methods。 - double Solver::Options::gradient_tolerance
默認值:1e-10
求解器會在滿足
時停止求解。其中||⋅||∞是指最大範數,Π是對邊界約束的投影,⊞是與參數矢量相關的整體局部參數化的加法運算。
2.3 信任區域
- double Solver::Options::function_tolerance
默認值:1e-6
求解器滿足
時停止求解,其中Δcost是Levenberg-Marquardt方法中當前迭代中目標函數值(也就是損失函數)的變化。上面的公式可以這樣理解,Δcost/cost非常小了,就說明cost基本沒啥變化,就認爲已經得到一個解了,故停止優化。 - TrustRegionStrategyType Solver::Options::trust_region_strategy_type
默認值:LEVENBERG_MARQUARDT --Ceres支持用於計算信任區域步驟的不同策略。
LEVENBERG_MARQUARDT :默認的信任區域策略是使用逐步計算用於Levenberg-Marquardt算法
DOGLEG:Powell的dogleg算法在Cauchy點和Gauss-Newton步驟之間進行插值。 如果VENBERG_MARQUARDT算法使大量的
不成功的步驟 - double Solver::Options::max_trust_region_radius
默認值:1e16
信任區域半徑最大值。 - double Solver::Options::min_trust_region_radius
默認值:1e-32
信任區域的最小值。當信任區域小於此值,會停止優化。 - double Solver::Options::min_relative_decrease
默認值:1e-3
信任域步長(trust region step)相對減少的最小值。 - double Solver::Options::min_lm_diagonal
默認值:1e-6
LEVENBERG MARQUARDT算法使用對角矩陣來規範(regularize)信任域步長。 這是該對角矩陣的值的下限。 - double Solver::Options::max_lm_diagonal
默認值:1e32
LEVENBERG MARQUARDT算法使用對角矩陣來規範(regularize)信任域步長。這是該對角矩陣的值的上限。 - int Solver::Options::max_num_consecutive_invalid_steps
默認值:5
信任區域策略返回的步驟有時可能在數值上無效,通常是因爲條件問題。 優化器可以繼續嘗試使用較小的信任區域/更好的條件問題來解決,而不是崩潰或停止優化。 此參數設置最小化器停止優化之前的連續重試次數。
2.4 線搜索
- LineSearchDirectionType Solver::Options::line_search_direction_type
默認值:LBFGS
可選的爲STEEPEST_DESCENT、NONLINEAR_CONJUGATE_GRADIENT、BFGS和LBFGS,都屬於LINE_SEARCH類的算法。 - LineSearchType Solver::Options::line_search_type
默認值:WOLFE
選擇是ARMIJO和WOLFE(強WOLFE條件)。 爲了保證BFGS和LBFGS線搜索方向算法的基本假設得到滿足,應使用WOLFE線性搜索。 - int Solver::Options::max_lbfgs_rank
默認值:20
L-BFGS的Hessian矩陣是對Hessian矩陣的逆的低秩近似。 近似的秩的大小與近似算法的空間和時間複雜度線性相關。 秩越高,近似的質量越好。 然而,由於以下兩種原因,質量的提高受到限制。
~The method only uses secant information and not actual derivatives.
~The Hessian approximation is constrained to be positive definite.
因此,將該秩增加到一個特別大的數字將大量將花費時間和空間而不會相應地提高求解的質量。不同的問題,可能最佳的秩也不同。
待續