Ceres-Solver学习笔记(8)

接上一篇

Solver::Options

class Solver::Options

Solver::Options 整体的控制求解器的行为,我们把变量设置和默认值列举如下。

Solver::Options::IsValid

验证选项结构中的值,并在成功时返回true。如果存在问题,则该方法返回false和 error 其中包含对原因的文本描述。

Solver::Options::minimizer_type

Default: TRUST_REGION
在LINE_SEARCH和TRUST_REGION算法之间进行选择。

Solver::Options::line_search_direction_type

Default: TRUST_REGION
在LINE_SEARCH和TRUST_REGION算法之间进行选择。

Solver::Options::line_search_type

Default: WOLFE
可选 WOLFE和ARMIJO。注意,为了保证BFGS和LBFGS线搜索方向算法的假设,必须使用WOLFE线性搜索。

Solver::Options::nonlinear_conjugate_gradient_type

Default: FLETCHER_REEVES
可选 FLETCHER_REEVES, POLAK_RIBIERE 和 HESTENES_STIEFEL

Solver::Options::max_lbfgs_rank

Default: 20
L-BFGS hessian近似是对hessian矩阵的逆矩阵的一种较低秩的近似。近似的秩决定(线性)使用近似的空间和时间复杂度。秩越大,近似的质量越好。然而,由于种种原因,质量的提高是有限制的。

  1. 这个方法只使用secant的信息而不是实际的导数。
  2. Hessian近似被限制为正定。

因此,将秩增加到一个大的数字将花费时间和空间复杂性,却没有相应的质量的提高。对于选择最大的秩,没有硬性规定。最好的选择通常需要一些特定问题的实验。

Solver::Options::use_approximate_eigenvalue_bfgs_scaling

Default: false
作为 BFGS 更新步骤/ LBFGS 右乘步骤的一部分,初始的逆Hessian近似是单位矩阵。然而,Oren展示了使用 Iγ γ 一个标量近似于真实的逆Hessian的特征值,可以在各种各样的情况下提高收敛性。将 use_approximate_eigenvalue_bfgs_scaling 设为true 在 BFGS 和 LBFGS中使能这个缩放。

准确地说,近似的特征值缩放等于

γ=ykskykyk

其中
yk=fk+1fksk=xk+1xk

f() 是线性搜索目标,x参数值向量。
值得注意的是,近似特征值的缩放并不总是能够提高收敛性,而且它实际上可能显著地降低某些类型的问题的性能,这就是为什么它在默认情况下是禁用的。特别是当问题对不同参数的敏感性有很大差异时,它就会降低性能,因为在这种情况下,一个标量因子无法捕捉到这种变化,并且会破坏雅可比矩阵近似于低灵敏度参数的部分。它还会降低解的鲁棒性导致Jacobians的错误。

Solver::Options::line_search_interpolation_type

Default: CUBIC
用于近似目标函数的多项式的次数。可选 BISECTION, QUADRATIC 和 CUBIC.

Solver::Options::min_line_search_step_size

线性搜索终止条件:

Δxk<min_line_search_step_size

表示最大范数, Δxk 是第k次迭代的步长。

Solver::Options::line_search_sufficient_function_decrease

Default: 1e-4
线性搜索问题的精确解是无法计算的。幸运的是,基于线性搜索的优化算法仍然可以保证收敛,如果不是一个精确的解,线性搜索算法返回一个可以充分减少目标函数值的解。更准确地说,我们正在寻找一个步长。

f(step_size)f(0)+sufficient_decrease[f(0)step_size]

这个条件叫做Armijo条件。

Solver::Options::max_line_search_step_contraction

Default: 1e-3
在线性搜索的每个迭代。

new_step_size>=max_line_search_step_contractionstep_size

请注意根据定义,为了收缩:
0<max_step_contraction<min_step_contraction<1

Solver::Options::min_line_search_step_contraction

Default: 0.6
在线性搜索的每个迭代。

new_step_size<=min_line_search_step_contractionstep_size

请注意根据定义,为了收缩:
0<max_step_contraction<min_step_contraction<1

Solver::Options::max_num_line_search_step_size_iterations

Default: 20
在每次线性搜索中,最大的寻找步长的迭代次数,如果在这个数量的试验中不能找到满足条件的步长,那么线性搜索就会停止。$$

因为这是一个“人为的”约束(由用户强加的,而不是依赖于数学),如果使用 WOLFE 线性搜索,在当前的搜索中发现了满足Armijo充分减小的条件的点 (in <=max_num_line_search_step_size_iterations)。然后,有最小函数值且满足了Armijo条件的步长,将会作为新的有效step,尽管它不满足strong Wolfe 条件。这种行为可以防止优化器在一个次优点的过早终止。

Solver::Options::max_num_line_search_direction_restarts

Default: 5
在终止优化之前,线搜索方向算法的最大重启次数。当当前算法不能产生新的下降方向时,线搜索方向算法重新启动。这通常表示一个数值失效,或者是使用近似失效。

Solver::Options::line_search_sufficient_curvature_decrease

Default: 0.9
strong Wolfe 条件包括Armijo的充分减少条件,以及一个额外的要求,即步长选择沿着搜索方向的梯度下降的幅度足够大。准确地说,第二个条件是我们要寻找一个步长标准。

f(step_size)<=sufficient_curvature_decreasef(0)

f() 是线性搜索目标, f() f 对于步长的导数 dfd step size .

Solver::Options::max_line_search_step_expansion

Default: 10.0

在Wolfe线性搜索的过程中,步长会增加,直到找到满足Wolfe条件的一个点,或者是一个包含一个满足条件的点的上界。精确地说,在每次迭代的扩展中:

new_step_size<=max_step_expansionstep_size

通过定义扩展
max_step_expansion>1.0

Solver::Options::trust_region_strategy_type

Default: LEVENBERG_MARQUARDT
Ceres使用的置信域计算方法,当前可选LEVENBERG_MARQUARDT和DOGLEG。

Solver::Options::dogleg_type

Default: TRADITIONAL_DOGLEG
Ceres支持两种dogleg策略,Powell的TRADITIONAL_DOGLEG方法和 ByrdSchnabel]描述的SUBSPACE_DOGLEG 方法。

Solver::Options::use_nonmonotonic_steps

Default: false
放松对信任区域算法严格减少步骤的要求。更多细节请参阅非单调的步骤。

Solver::Options::max_consecutive_nonmonotonic_steps

Default: 5
步骤选择算法使用的窗口大小来接受非单调的步骤。

Solver::Options::max_num_iterations

Default: 50
解析器应该运行的最大迭代次数。

Solver::Options::max_solver_time_in_seconds

Default: 1e6
解析器应该运行的最大时间。

Solver::Options::num_threads

Default: 1
Ceres求Jacobain的线程数目。

Solver::Options::initial_trust_region_radius

Default: 1e4
初始置信域的大小。当使用levenbergmarquardt策略时,这个数字的倒数就是初始的正则化参数。

Solver::Options::max_trust_region_radius

Default: 1e16
置信域的半径是不允许超过这个值的。

Solver::Options::min_trust_region_radius

Default: 1e-32
置信域的半径是不允许小于这个值的。

Solver::Options::min_relative_decrease

Default: 1e-3
在一个置信域的步长被接受之前,相对降低的阈值。

Solver::Options::min_lm_diagonal

Default: 1e6
LEVENBERG_MARQUARDT策略,使用一个对角矩阵来使置信域的step规范化。这是这个对角矩阵的值的下界。

Solver::Options::max_lm_diagonal

Default: 1e32
LEVENBERG_MARQUARDT策略,使用一个对角矩阵来使置信域的step规范化。这是这个对角矩阵的值的上界。

Solver::Options::max_num_consecutive_invalid_steps

Default: 5
置信域策略返回的step有时在数字上是无效的,这通常是由于条件的问题。优化器不会崩溃或停止优化,而是可以尝试使用较小的信任区域/更好的条件来解决问题。该参数设置在最小化放弃之前连续重试的次数。

Solver::Options::function_tolerance

Default: 1e-6
求解终止如果

|Δcost|cost<=function_tolerance

Δcost 是在当前的LM的迭代中,目标函数值的变化(上升或下降)。

Solver::Options::gradient_tolerance

Default: 1e-10
求解终止如果

xΠ(x,g(x))<=gradient_tolerance

最大范数, Π 是在边界约束条件下的投影, 是与参数向量相关的整个局部参数化的加法。

Solver::Options::parameter_tolerance

Default: 1e-8
求解终止如果

Δx<=(x+parameter_tolerance)parameter_tolerance

Δx 是当前迭代下线性求解的步长。

Solver::Options::linear_solver_type

Default: SPARSE_NORMAL_CHOLESKY / DENSE_QR
在 Levenberg-Marquardt算法的每一次迭代中,用于计算线性最小二乘问题的线性求解器的类型。如果Ceres是支持西SuiteSparse,或者 CXSparse,或者是Eigen的稀疏Cholesky 分解,默认是 SPARSE_NORMAL_CHOLESKY,否则就是DENSE_QR。

Solver::Options::preconditioner_type

Default: JACOBI
迭代线性求解使用的预处理,默认是块Jacobi 预处理,可用的选项是IDENTITY, JACOBI, SCHUR_JACOBI, CLUSTER_JACOBI 和 CLUSTER_TRIDIAGONAL。

Solver::Options::visibility_clustering_type

Default: CANONICAL_VIEWS
在构造基于可见性的预调节器时使用的聚类算法。最初的基于可见性的预处理论文和实现只使用了规范的视图算法。

这个算法给出了高质量的结果,但是对于大的稠密图来说可能特别复杂。最坏的情况是图形大小3次方。

另一种选择是使用 SINGLE_LINKAGE,这是一种简单的、单一的链接聚类算法,只关注Schur complement的紧密耦合块。这是一种运行良好的快速算法。

聚类算法的最佳选择取决于问题的稀疏结构,但是一般来说,我们建议您先尝试一下 CANONICAL_VIEWS,如果它太过复杂,尝试 SINGLE_LINKAGE。

Solver::Options::dense_linear_algebra_library_type

Default: EIGEN
Ceres支持使用多密度的线性代数库来进行密集的矩阵分解。目前,EIGEN和LAPACK是有效的选择。EIGEN始终是可用的,LAPACK依赖于系统BLAS+LAPACK库,它可能是可用的,也可能是不可用的。

Solver::Options::sparse_linear_algebra_library_type

Default: 优先级 SUITE_SPARSE > CX_SPARSE > EIGEN_SPARSE > NO_SPARSE
Ceres支持使用三种稀疏的线性代数库。SuiteSparse 通过将参数设为 SUITE_SPARSE,CXSparse 通过将参数设为 CX_SPARSE,Eigen 通过将参数设为 EIGEN_SPARSE,最后,NO_SPARSE意味着不需要使用稀疏的线性求解;注意,这与Ceres的编译是否支持一个是无关的。

SuiteSparse 是一个久经考验而复杂的稀疏线性代数库,应该被广泛使用。

如果您的需求/平台阻止您使用SuiteSparse,请考虑使用CXSparse,这是一个小得多的简单的库。可以想象,它在大问题上的性能不能与SuiteSparse 的性能相媲美。

最后非常重要的一点,你可以使用Eigen的线性代数例程。目前这个图书馆的表现是这三个库中最差的。但这种情况在不久的将来就会改变。

另一件需要考虑的事情是,Eigen的稀疏Cholesky分解库是在LGPL下获得许可的,在Ceres中使用EIGEN_SPARSE,这将导致一个LGPL授权的库(因为Eigen的相应代码被编译到库中)。好处是,您不需要构建并链接到外部库以使用EIGEN_SPARSE。

Solver::Options::num_linear_solver_threads

Default: 1
线性解算使用的线程数。

Solver::Options::linear_solver_ordering

Default: NULL
ordering对象的一个实例告知线性求解器所需参数块消除的顺序。
如果是NULL,解析器就可以自由选择它认为最好的排序。

Solver::Options::use_explicit_schur_complement

Default: false
ITERATIVE_SCHUR使用一个显式的Schur complement矩阵。
默认情况下,这一选项是禁用的,而ITERATIVE_SCHUR通过利用Schur complement的代数表达式来对Schur complement和向量之间的矩阵向量乘积进行求值。

这个计算的复杂度与Jacobian矩阵中非零项的数目有关。
对于小到中等大小的问题,有一个很好的地方,计算Schur complement足够简单,而明确地计算它并使用它来求矩阵向量乘积是更有效的。

启用这个选项可以告诉 ITERATIVE_SCHUR,使用一个显式的Schur complement。这可以显著提高 ITERATIVE_SCHUR的性能。

Solver::Options::use_post_ordering

Default: false
稀疏的Cholesky分解算法使用一个 fill-reducing 的顺序来对Jacobian矩阵的列进行排序。有两种方法可以做到这一点。

  1. 以某种顺序计算雅可比矩阵,然后用分解算法置换Jacobian矩阵的列。
  2. 用已经置换列来计算雅可比矩阵。

第一个选项会导致严重的内存损失,分解算法必须对置换Jacobian矩阵进行复制,因此, Ceres 对Jacobian矩阵的列向量进行预处理。一般来说,不会有任何性能损失。

在一些罕见的情况下,使用一个更复杂的重新排序算法是值得的,它的运行时性能稍好一些,而代价是雅可比矩阵的额外拷贝。将 use_postordering 设置为true可以实现此折衷。

Solver::Options::dynamic_sparsity

一些非线性最小二乘问题具有symbolically稠密,但numerically稀疏。也就是说,在任何给定的状态下,只有少量Jacobian矩阵的项是非零的,但非零的位置和数量根据状态不同而不同。对于这些问题,在分解器迭代中分解稀疏的雅可比矩阵是很有用的,而不是将所有的零项都包含在一个通用分解中。

如果您的问题没有这个属性(或者您不知道),那么最好保不要使用,否则它可能会导致更糟糕的性能。

这种设置只会影响到SPARSE_NORMAL_CHOLESKY求解器。

Solver::Options::min_linear_solver_iterations

Default: 0
线性解算器使用的最小迭代次数。只有当线性解算器是一个迭代解算器时,才有意义。例如,ITERATIVE_SCHUR或CGNR。

Solver::Options::max_linear_solver_iterations

Default: 500
线性解算器使用的最大迭代次数。只有当线性解算器是一个迭代解算器时,才有意义。例如,ITERATIVE_SCHUR或CGNR。

Solver::Options::eta

Default: 1e-1
强制序列参数。截断牛顿求解使用这个数来控制牛step计算的相对精度。这个常量被传递给ConjugateGradientsSolver,它使用它来终止迭代

QiQi1Qi<ηi

Solver::Options::jacobi_scaling

Default: true
true的意思是Jacobian矩阵在被传递给线性解算器之前被它的列的范数所缩放。这提高了一般方程的数值条件。

Solver::Options::use_inner_iterations

Default: false
使用一个非线性的简化变量投影算法。本质上,这相当于使用coordinate下降算法对每个 Newton/Trust区域的步骤进行进一步优化。要了解更多细节,请参见 Inner Iterations。

Solver::Options::inner_iteration_tolerance

Default: 1e-3
一般来说,内部迭代在解决方案的早期阶段取得重大进展,然后它们的贡献会急剧下降,这时花在进行内部迭代上的时间是不值得的。

一旦由于内部迭代而导致的目标函数的相对减少下降到内在迭代的容忍范围内,那么在随后的置信域最小化迭代中使用内迭代就会被禁用。

Solver::Options::inner_iteration_ordering

Default: NULL
如果 Solver::Options::use_inner_iterations 为 true,那么用户有两个选择。

  1. 让解析器启发式地在每一个内部迭代中决定优化哪些参数块。要做到这一点,设置 Solver::Options::inner_iteration_ordering为NULL。
  2. 指定一组有序的独立集合。在内部优化阶段,较低的编号组在较高的数组之前进行了优化。每个组必须是一个独立的集合,并不是所有的参数块都需要包含在排序中。

Solver::Options::logging_type

Default: PER_MINIMIZER_ITERATION

Solver::Options::minimizer_progress_to_stdout

Default: false
默认情况下,根据vlog级别,将最小化进程的过程记录到STDERR。如果这个标志被设置为true,并且 Solver::Options::loggingtype不是 SILENT,日志输出将被发送到 STDOUT。

TRUST_REGION_MINIMIZER 的过程显示

iter      cost      cost_change  |gradient|   |step|    tr_ratio  tr_radius  ls_iter  iter_time  total_time
   0  4.185660e+06    0.00e+00    1.09e+08   0.00e+00   0.00e+00  1.00e+04       0    7.59e-02    3.37e-01
   1  1.062590e+05    4.08e+06    8.99e+06   5.36e+02   9.82e-01  3.00e+04       1    1.65e-01    5.03e-01
   2  4.992817e+04    5.63e+04    8.32e+06   3.19e+02   6.52e-01  3.09e+04       1    1.45e-01    6.48e-01
  1. cost 是目标函数的值
  2. cost_change 是目标函数值的改变,如果计算的step被这次迭代接受。
  3. gradient 是梯度的最大范数
  4. step 是参数向量的改变
  5. tr_ratio 是目标函数值的实际变化量与置信域模型值的变化量的比值。
  6. tr_radius 置信域半径大小。
  7. ls_iter 是计算置信域step的线性搜索迭代次数。对于 direct/factorization 求解,值为1,对于迭代求解,像 ITERATIVE_SCHUR,它是Conjugate Gradients算法的迭代次数。
  8. iter_time 当前迭代花费时间。
  9. total_time 最小化的总时间。

LINE_SEARCH_MINIMIZER 的过程显示

0: f: 2.317806e+05 d: 0.00e+00 g: 3.19e-01 h: 0.00e+00 s: 0.00e+00 e:  0 it: 2.98e-02 tt: 8.50e-02
1: f: 2.312019e+05 d: 5.79e+02 g: 3.18e-01 h: 2.41e+01 s: 1.00e+00 e:  1 it: 4.54e-02 tt: 1.31e-01
2: f: 2.300462e+05 d: 1.16e+03 g: 3.17e-01 h: 4.90e+01 s: 2.54e-03 e:  1 it: 4.96e-02 tt: 1.81e-01
  1. f 是目标函数值。
  2. d 是目标函数值的改变,如果计算的step被这次迭代接受
  3. g 是梯度的最大范数
  4. h 是参数向量的改变
  5. s 是计算的优化步长
  6. it 前迭代花费时间。
  7. tt 最小化的总时间。

Solver::Options::trust_region_minimizer_iterations_to_dump

Default: empty
置信域最小化的迭代列表应该转储置信域问题。用于测试和确定基准。如果是空的,就不会有问题被转储。

Solver::Options::trust_region_problem_dump_directory

Default: /tmp
应该将问题写入到哪个目录。不为空,如果 Solver::Options::trust_region_minimizer_iterations_to_dump 不是空 并且 Solver::Options::trust_region_problem_dump_format_type 不是 CONSOLE.

Solver::Options::trust_region_problem_dump_format

Default: TEXTFILE

当Solver::Options::trust_region_minimizer_iterations_to_dump 不为空的时候,置信域的问题应该被记录下来。有三个选项:

  • CONSOLE 用一种人类可读的格式打印线性最小二乘的问题到stderr。Jacobian被打印成稠密的矩阵,向量D, x 和 f被打印成稠密的向量,这应该用于小问题。
  • TEXTFILE 把线性最小二乘法的问题写在Solver::Options::trust_region_problem_dump_directory作为文本文件,可以读到MATLAB/Octave。Jacobian矩阵被转储为包含(i、j、s)三联体的文本文件,向量D、x和f被转储为包含其值列表的文本文件。
    一个 MATLAB/Octave 脚本叫做 ceres_solver_iteration_???.m 也是也个输出,它可以用来解析和将问题加载到内存中。

Solver::Options::check_gradients

Default: false
用有限的差分来检查每一个残差块所计算的所有的Jacobians。这是复杂的,因为它涉及到通过正常手段(如用户指定,autodiff等等)计算导数,然后使用有限差分计算它。比较结果,如果它们有很大的不同,那么优化失败,细节也会存储在解析器摘要中。

Solver::Options::gradient_check_relative_precision

Default: 1e08
在梯度检查器中检查精度。如果Jacobian矩阵中的一个元素的相对差超过这个数,那么这个cost项的雅可比矩阵就被丟了。

Solver::Options::gradient_check_numeric_derivative_relative_step_size

Default: 1e-6

注意 这个选项只适用于 Solver::Options::check_gradients 是true,用于检查用户提供的导数的数值微分。如果你使用的是 NumericDiffCostFunction ,并且有兴趣在你的成本函数中改变数字微分的步长,请看看 NumericDiffOptions。

当olver::Options::check_gradients是true,计算数值微分时的偏移量。

对于有限差分,每个维度都以略微移位的值进行求解。例如,对于前向微分

δΔf=gradient_check_numeric_derivative_relative_step_size=f((1+δ)x)f(x)δx

在每个维度上都有有限差分。使用相对(而不是绝对)步长的原因是这样的,数值微分适用于那些参数通常很大的函数(例如 109 ),当值很小(例如 105 )。我们有可能构建出错的情况来打破这种有限的差异,但它们在实践中并不是经常出现的。

Solver::Options::callbacks

Default: 1e-6
Minimizer 每次迭代结束时执行的回调。它们按照在向量中指定的顺序执行。默认情况下,参数块只在优化结束时更新。换言之,Minimizer终止时。这个行为是由求Solver::Options::update_state_every_variable 来控制的。如果用户希望在他/她的回调函数被执行时访问更新参数块,那么设置Solver::Options::update_state_every_iteration为true。

解算器不需要这些指针的所有权。

Solver::Options::update_state_every_iteration

Default: false
通常,当解析器终止时,参数块才会更新。将其设置为true时在每次迭代中对其进行更新。在使用Ceres和使用IterationCallback 构建交互式应用程序时,这种设置非常有用。

ParameterBlockOrdering

class ParameterBlockOrdering

ParameterBlockOrdering 是一个类, 用于存储和操作一个groups/sets 的集合,具有以下语义:

Group IDs 是非负整数值。元素是任何可以作为map的key或set的元素的类型。

一个元素一次只能属于一个组。一个组可能包含任意数量的元素。
Groups 是按组id排序的。

ParameterBlockOrdering::AddElementToGroup(const double *element, const int group)

向组中添加一个元素。如果这个id的组不存在,就创建一个。这个方法被同一元素调用任意次数。组id应该是非负数。返回值表明如果添加元素是成功的。

ParameterBlockOrdering::Clear()

清除顺序。

ParameterBlockOrdering::Remove(const double *element)

清除元素,不管他在哪个组。如果元素不是任何组的成员,那么调用该方法将导致崩溃。返回值指示是否删除了元素。

ParameterBlockOrdering::Reverse()

颠倒小组的顺序。

ParameterBlockOrdering::GroupId(const double *element) const

返回元素的组id。如果元素不是任何组的成员,则返回-1。

ParameterBlockOrdering::IsMember(const double *element) const

true,如果有一个包含参数块的组。

ParameterBlockOrdering::GroupSize(const int group) const

这个函数总是成功的。隐式地存在一个对每个整数的组。

ParameterBlockOrdering::NumElements() const

排序中的元素个数。

ParameterBlockOrdering::NumGroups() const

具有一个或多个元素的组的数量。

IterationCallback

class IterationSummary

IterationSummary 描述每次迭代结束时最小化的状态。

IterationSummary::iteration

当前迭代数。

IterationSummary::step_is_valid

step在数值上是有效的。换句话说,所有的值都是有限的,step降低了线性化模型的值。

注意 IterationSummary::iteration = 0 时, IterationSummary::step_is_valid 是 false。

IterationSummary::step_is_nonmonotonic

step并没有充分地减少目标函数的值,但由于非单调置信域算法使用的松弛接受准则,它被接受了。

注意 IterationSummary::iteration = 0 时,IterationSummary::step_is_nonmonotonic 是false 。

IterationSummary::step_is_successful

不管这个最小化是否接受了这个step。

如果使用一般的信任区域算法,这就意味着目标函数值的相对减少要大于Solver::Options::min_relative_decrease。然而,如果使用非单调的置信域算法(Solver::Options::use_nonmonotonic_steps = true),即使相对的减少是不够的,算法也可以接受这个step,并声明步骤是成功的。

注意 IterationSummary::iteration = 0 时,IterationSummary::step_is_successful 是false 。

IterationSummary::cost

目标函数的值。

IterationSummary::cost_change

在这个迭代中目标函数的改变值。这可以是正的,也可以是负的。

IterationSummary::gradient_max_norm

梯度向量的无穷范数。

IterationSummary::gradient_norm

梯度向量的2-范数。

IterationSummary::step_norm

在这个迭代中计算的step的大小的2-范数。

IterationSummary::relative_decrease

对于信任区域的算法,cost的实际变化与线性化逼近的cost变化的比值。
当使用线性搜索最小化时,该字段不会被使用。

IterationSummary::trust_region_radius

在当前迭代结束时,信任区域的大小。对于Levenberg-Marquardt算法,正则化参数是1.0 /member::IterationSummary::trust_region_radius。

IterationSummary::eta

对于不精确步骤的LM算法,这是该step被解决的相对精度。这个数字只适用于能够准确解决线性系统的迭代解决方案。基于分解的精确求解eta总是0。

IterationSummary::step_size

由线性搜索算法计算出的步长。
当使用信任区域的最小值时,该字段不会被使用。

IterationSummary::line_search_function_evaluations

线搜索算法使用的函数评估的数量。
当使用信任区域的最小值时,该字段不会被使用。

IterationSummary::linear_solver_iterations

线性解算器求解置信域step的迭代次数。
当使用一个线性搜索最小值时,该字段不会被使用。

IterationSummary::iteration_time_in_seconds

时间(以秒为单位)在当前迭代的最小循环中花费。

IterationSummary::step_solver_time_in_seconds

时间(以秒为单位)求解置信域step的花费。

IterationSummary::cumulative_time_in_seconds

时间(以秒为单位),从用户调用了Solve()开始。

class IterationCallback

用于指定在最小化每次迭代结束时执行的回调函数接口。

class IterationCallback {
 public:
  virtual ~IterationCallback() {}
  virtual CallbackReturnType operator()(const IterationSummary& summary) = 0;
};

求解程序使用 operator()的返回值来决定是否继续或终止。用户可以返回三个值。

  1. SOLVER_ABORT 表示回调检测到异常情况。求解器返回却没有更新参数块(除非 Solver::Options::update_state_every_iteration 设置为 true),求解器返回时将Solver::Summary::termination_type 设置为 USER_FAILURE。
  2. SOLVER_TERMINATE_SUCCESSFULLY 表示不再需要优化(一些用户指定的终止条件已经满足)。求解器返回时将 Solver::Summary::termination_type 设置为 USER_SUCCESS。
  3. SOLVER_CONTINUE 表示求解器需要继续优化。

例如,Ceres内部使用了下面的迭代回调来记录优化的进展。

class LoggingCallback : public IterationCallback {
 public:
  explicit LoggingCallback(bool log_to_stdout)
      : log_to_stdout_(log_to_stdout) {}

  ~LoggingCallback() {}

  CallbackReturnType operator()(const IterationSummary& summary) {
    const char* kReportRowFormat =
        "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e "
        "rho:% 3.2e mu:% 3.2e eta:% 3.2e li:% 3d";
    string output = StringPrintf(kReportRowFormat,
                                 summary.iteration,
                                 summary.cost,
                                 summary.cost_change,
                                 summary.gradient_max_norm,
                                 summary.step_norm,
                                 summary.relative_decrease,
                                 summary.trust_region_radius,
                                 summary.eta,
                                 summary.linear_solver_iterations);
    if (log_to_stdout_) {
      cout << output << endl;
    } else {
      VLOG(1) << output;
    }
    return SOLVER_CONTINUE;
  }

 private:
  const bool log_to_stdout_;
};

CRSMatrix

class CRSMatrix

一个被压缩的行稀疏矩阵主要用于向用户传递Jacobian矩阵。

CRSMatrix::num_rows

行的数量。

CRSMatrix::rows

CRSMatrix::rows 是一个 CRSMatrix::num_rows + 1大小的数组,指向CRSMatrix::cols 和 CRSMatrix::values 数组。

CRSMatrix::cols

CRSMatrix::cols 包含矩阵中所有的非零项。
对每一行i,cols[rows[i]] … cols[rows[i + 1] - 1]是第i行的非零列的索引。

CRSMatrix::values

CRSMatrix::values 包含矩阵中所有的非零项。
对每一行i,values[rows[i]] … values[rows[i + 1] - 1]是第i行的非零列的索引。

例如考虑 3x4 的稀疏矩阵

0 10 0 4
0 2 -3 2
1 2 0 0

三个数组将如下
Ceres-Solver学习笔记(8)_第1张图片

Solver::Summary

class Solver::Summary

求解结束后求解的各个阶段的摘要。

Solver::Summary::BriefReport() const

求解结束后的一个一行简单的求解状态描述。

Solver::Summary::FullReport() const

求解结束后的一个多行的求解状态描述。

Solver::Summary::IsSolutionUsable() const

优化算法返回的解是否能在数字上保持正常。如果Solver::Summary:termination_type被设置为CONVERGENCE, USER_SUCCESS 或NO_CONVERGENCE,换句话说,求解要么达到收敛条件,要么用户表示已经收敛,要么是达到最大的迭代次数或时间。

Solver::Summary::minimizer_type

最小化算法类型。

Solver::Summary::termination_type

最小化终止条件。

Solver::Summary::message

最小化终止原因。

Solver::Summary::initial_cost

问题的cost(目标函数值)在优化之前。

Solver::Summary::final_cost

问题的cost(目标函数值)在优化之后。

Solver::Summary::fixed_cost

问题的部分cost,来自处理中固定不动的残差块,因为他们依赖的参数块是固定的。

Solver::Summary::iterations

顺序的每个最小化迭代的IterationSummary。

Solver::Summary::num_successful_steps

step被接受的最小化迭代次数。除非 Solver::Options::use_non_monotonic_steps 是 true,它也是目标函数值下降的次数。

Solver::Summary::num_unsuccessful_steps

step被拒绝的最小化迭代次数,因为它没能足够的减小cost,或者step是无效数字。

Solver::Summary::num_inner_iteration_steps

使用内部迭代的次数。

Solver::Summary::num_line_search_steps

在所有调用中,线性搜索算法总迭代次数。我们将这些迭代称为“steps”,将它们与线性搜索和置信域最小化算法的外部迭代区分开来,后者将线性搜索算法称为子程序。

Solver::Summary::preprocessor_time_in_seconds

预处理花费时间(秒为单位)。

Solver::Summary::minimizer_time_in_seconds

最小化花费的时间。

Solver::Summary::postprocessor_time_in_seconds

打印输出花费时间。

Solver::Summary::total_time_in_seconds

求解花费时间。

Solver::Summary::linear_solver_time_in_seconds

线性求解计算置信域step花费时间。

Solver::Summary::residual_evaluation_time_in_seconds

计算残差向量花费时间。

Solver::Summary::jacobian_evaluation_time_in_seconds

计算Jacobian 矩阵花费时间。

Solver::Summary::inner_iteration_time_in_seconds

内部迭代花费时间。

Solver::Summary::num_parameter_blocks

问题的参数块数量。

Solver::Summary::num_parameters

问题的参数数量。

Solver::Summary::num_effective_parameters

问题的切空间维度(或者问题中Jacobian 矩阵的列数),这与Solver::Summary::num_parameters不同,如果参数块与 LocalParameterization相联系。

Solver::Summary::num_residual_blocks

问题中残差块的数量。

Solver::Summary::num_residuals

问题中残差的数量。

Solver::Summary::num_parameter_blocks_reduced

去除inactive 参数块和常量参数块之后,问题中的参数块数量。如果没有残差块引用的话,一个参数块是inactive 的。

Solver::Summary::num_parameters_reduced

缩减后的问题中的参数块数量。

Solver::Summary::num_effective_parameters_reduced

缩减后的问题的切空间(或者缩减后问题的Jacobian 列数)。这与Solver::Summary::num_parameters_reduced 不同,如果缩减后的参数块与LocalParameterization相联系。

Solver::Summary::num_residual_blocks_reduced

缩减后的问题的残差块数量。

Solver::Summary::num_residuals_reduced

缩减后的问题的残差数量。

Solver::Summary::num_threads_given

用户指定的计算Jacobian 和残差的线程数量。

Solver::Summary::num_threads_used

真正用于的计算Jacobian 和残差的线程数量。如果 无法获得OpenMP ,它与Solver::Summary::num_threads_given是不同的。

Solver::Summary::num_linear_solver_threads_given

用户指定的用于求解置信域的线程数。

Solver::Summary::num_linear_solver_threads_used

实际用于求解置信域的线程数。如果 无法获得OpenMP ,它与Solver::Summary::num_threads_given是不同的。

Solver::Summary::linear_solver_type_given

用户要求的线性求解类型。

Solver::Summary::linear_solver_type_used

实际的线性求解类型。如果Ceres觉得问题的结构用 Solver::Summary::linear_solver_type_given 无法求解,或者无法获得用户要求的类型,例如,用户要求SPARSE_NORMAL_CHOLESKY ,但是没有稀疏的线性代数库可用。

Solver::Summary::linear_solver_ordering_given

用户给的消除组大小,作为线性求解的提示。

Solver::Summary::linear_solver_ordering_used

在排序雅可比矩阵的列时,求解器使用的参数组的大小。这可能与Solver::Summary::linear_solver_ordering_given不同,如果要求自动顺序,或者问题有一些inactive 参数和常量参数。

Solver::Summary::schur_structure_given

对于Schur 类型的线性求解,这个字符串描述了实际实例化使用的模板。不同于Solver::Summary::schur_structure_given的原因是对应的模板不存在。

可以通过编辑internal/ceres/generate_template_specializations.py模板指定添加到Ceres。

Solver::Summary::inner_iterations_given

为true,如果用户要求内部优化作为优化的一部分。

Solver::Summary::inner_iterations_used

为true,如果用户要求内部优化作为优化的一部分,并且问题结构允许,例如,只有一个参数块的问题,就不会使用内部迭代。

Solver::Summary::inner_iteration_ordering_given

用户给定的执行内部迭代的参数组大小。

Solver::Summary::inner_iteration_ordering_used

实际执行内部迭代的参数组大小。

Solver::Summary::preconditioner_type_given

用户要求的预处理类型。

Solver::Summary::preconditioner_type_used

实际的预处理类型。

Solver::Summary::visibility_clustering_type

用于基于可见性预调的聚类算法。只有Solver::Summary::preconditioner_type是CLUSTER_JACOBI 或者CLUSTER_TRIDIAGONAL才有意义。

Solver::Summary::trust_region_strategy_type

置信域策略的类型。

Solver::Summary::dogleg_type

dogleg 类型用于解决置信域问题。

Solver::Summary::dense_linear_algebra_library_type

稠密线性代数库类型。

Solver::Summary::sparse_linear_algebra_library_type

稀疏线性代数库类型。

Solver::Summary::line_search_direction_type

搜索方向使用的类型。

Solver::Summary::line_search_type

线性搜索算法的类型。

Solver::Summary::line_search_interpolation_type

当运行线性搜索,用来近似目标函数的多项式的次数。

Solver::Summary::nonlinear_conjugate_gradient_type

如果线性搜索方向是NONLINEAR_CONJUGATE_GRADIENT,那么这表明了所使用的非线性共轭梯度的特殊变化。

Solver::Summary::max_lbfgs_rank

如果线性搜索方向是LBFGS,那么这表明了近似Hessian 的秩。

你可能感兴趣的:(c++)