上一篇:Ceres(二)LocalParameterization参数化
参考:Ceres Covariance Estimation
One way to assess the quality of the solution returned by a non-linear least squares solver is to analyze the covariance of the solution.
求解非线性问题
y
=
f
(
x
)
+
N
(
0
,
I
)
y = f(x) + N(0, I)
y=f(x)+N(0,I)
观测
y
y
y是一个独立于
x
x
x的随机非线性函数,其均值是
f
(
x
)
f(x)
f(x),协防差是单位矩阵,为了求解
x
x
x最大似然估计值,转换成如下最小二乘问题:
x
∗
=
arg
min
x
∥
f
(
x
)
∥
2
x^* = \arg \min_x \|f(x)\|^2
x∗=argxmin∥f(x)∥2
x
∗
x^*
x∗的协防差如下:
C
(
x
∗
)
=
(
J
′
(
x
∗
)
J
(
x
∗
)
)
−
1
C(x^*) = \left(J'(x^*)J(x^*)\right)^{-1}
C(x∗)=(J′(x∗)J(x∗))−1
J
(
x
∗
)
J(x^*)
J(x∗)是
f
f
f关于
x
x
x的雅可比矩阵,上述式子是在假定
J
(
x
∗
)
J(x^*)
J(x∗)是列满秩时成立的,如果
J
(
x
∗
)
J(x^*)
J(x∗)不是列满秩的,需要求伪逆
C
(
x
∗
)
=
(
J
′
(
x
∗
)
J
(
x
∗
)
)
†
C(x^*) = \left(J'(x^*)J(x^*)\right)^{\dagger}
C(x∗)=(J′(x∗)J(x∗))†
如果协防差不是单位矩阵,上述求解过程变成:
y
=
f
(
x
)
+
N
(
0
,
S
)
x
∗
=
arg
min
x
f
′
(
x
)
S
−
1
f
(
x
)
C
(
x
∗
)
=
(
J
′
(
x
∗
)
S
−
1
J
(
x
∗
)
)
−
1
\begin{aligned} y &= f(x) + N(0, S) \\ x^* &= \arg \min_x f'(x) S^{-1} f(x) \\ C(x^*) &= \left(J'(x^*) S^{-1} J(x^*)\right)^{-1} \end{aligned}
yx∗C(x∗)=f(x)+N(0,S)=argxminf′(x)S−1f(x)=(J′(x∗)S−1J(x∗))−1
其中 S S S是positive semi-definite矩阵,在ceres中,用户需要使用 S − 1 / 2 f ( x ) S^{-1/2} f(x) S−1/2f(x)替换 f ( x ) f(x) f(x)
1. Rank of the Jacobian
当雅可比是rank deficient类型的时候, J ′ J J'J J′J的逆不存在,下面介绍导致此种问题的原因
1.1 Structural rank deficiency
导致雅可比欠定的可能原因是一些structural-columns,这些列是0或者是常数,这种Structural rank deficiency问题经常出现在:当该problem包含常数参数块时,比如,1) 使用SetParameterBlockConstant()
,2) 手动将不优化的变量对应的那一列雅可比置零,3) 手动使用常数代替某个不优化变量,达到不优化该变量(见旷世标定工具箱)
1.2 Numerical rank deficiency
Numerical rank deficiency, where the rank of the matrix cannot be predicted by its sparsity structure and requires looking at its numerical values is more complicated.
存在两种情况:
1)过参数化导致的欠定
比如SO(3),这种问题需要用户自己实现LocalParameterization
来解决
2)More general numerical rank deficiency in the Jacobian requires the computation of the so called Singular Value Decomposition (SVD) of J′J.
- We do not know how to do this for large sparse matrices efficiently.
- For small and moderate sized problems this is done using dense linear algebra.
2. Covariance::Options::algorithm_type
Default: SPARSE_QR
2.1 SPARSE_QR
只能用于当Jacobian正定时,速度较SVD快,
Q
R
=
J
(
J
⊤
J
)
−
1
=
(
R
⊤
R
)
−
1
\begin{aligned}QR &= J\\ \left(J^\top J\right)^{-1} &= \left(R^\top R\right)^{-1}\end{aligned}
QR(J⊤J)−1=J=(R⊤R)−1
对 R ⊤ R R^\top R R⊤R的求逆采用回代的方式以降低运算量,参考:《numerical mathematics》
ceres中的QR分解有两种实现方式:
1)Eigen’s sparse QR factorization is a moderately fast algorithm suitable for small to medium sized matrices.
2)For best performance we recommend using SuiteSparseQR
which is enabled by setting Covaraince::Options::sparse_linear_algebra_library_type
to SUITE_SPARSE
2.2 DENSE_SVD
DENSE_SVD uses Eigen’s JacobiSVD to perform the computations
U
S
V
⊤
=
J
U S V^\top = J
USV⊤=J
( J ′ J ) † = V S † V ⊤ (J'J)^{\dagger} = V S^{\dagger} V^\top (J′J)†=VS†V⊤
It is an accurate but slow method and should only be used for small to moderate sized problems.
It can handle full-rank as well as rank deficient Jacobians.
3. Covariance::Options::min_reciprocal_condition_number
如果Jacobian是接近奇异的,
J
′
J
J'J
J′J的逆将很不稳定,比如:
J
=
[
1.0
1.0
1.0
1.0000001
]
\begin{aligned}J = \begin{bmatrix} 1.0& 1.0 \\ 1.0& 1.0000001 \end{bmatrix}\end{aligned}
J=[1.01.01.01.0000001]
这个矩阵几乎是欠定的,我们将得到这样的结果,
(
J
′
J
)
−
1
=
[
2.0471
e
+
14
−
2.0471
e
+
14
−
2.0471
e
+
14
2.0471
e
+
14
]
\begin{aligned}(J'J)^{-1} = \begin{bmatrix} 2.0471e+14& -2.0471e+14 \\ -2.0471e+14& 2.0471e+14 \end{bmatrix}\end{aligned}
(J′J)−1=[2.0471e+14−2.0471e+14−2.0471e+142.0471e+14]
因此需要根据结果来判断求解是否成功,也即,
J
′
J
J'J
J′J是否是正定的,下面针对上面说到的两种算法类型采用不同策略进行判别:
1)SPARSE_QR
rank
(
J
)
<
num_col
(
J
)
\operatorname{rank}(J) < \operatorname{num\_col}(J)
rank(J)<num_col(J)
rank ( J ) \operatorname{rank}(J) rank(J)能直接从sparse QR factorization中获取到
2)DENSE_SVD
min_reciprocal_condition_number的默认值是:
1
0
−
14
10^{-14}
10−14
σ
min
σ
max
<
min reciprocal condition number
\frac{\sigma_{\text{min}}}{\sigma_{\text{max}}} < \sqrt{\text{min reciprocal condition number}}
σmaxσmin<min reciprocal condition number
where σ m i n σ_{min} σmin and σ m a x σ_{max} σmax are the minimum and maxiumum singular values of J J J respectively.
4. Covariance::Options::null_space_rank
该选项仅用于当使用DENSE_SVD
来求解逆时来使用,
J
′
J
J'J
J′J的特征分解是
(
λ
i
,
e
i
)
(\lambda_i, e_i)
(λi,ei),
λ
i
λ_i
λi is the
i
t
h
i^{th}
ith eigenvalue and
e
i
e_i
ei is the corresponding eigenvector, then the inverse of
J
′
J
J'J
J′J is:
( J ′ J ) − 1 = ∑ i 1 λ i e i e i ′ (J'J)^{-1} = \sum_i \frac{1}{\lambda_i} e_i e_i' (J′J)−1=i∑λi1eiei′
min_reciprocal_condition_number
和 null_space_rank
控制着要丢掉上式中哪些小特征项
-
If null_space_rank is non-negative,
最小的null_space_rank 个 eigenvalue/eigenvectors将要被dorpped掉,
If the ratio of the smallest non-zero eigenvalue to the largest eigenvalue in the truncated matrix is still below min_reciprocal_condition_number, then the Covariance::Compute() will fail and return false. -
当null_space_rank = -1时,dorpped规则是这样的
λ i λ max < min reciprocal condition number \frac{\lambda_i}{\lambda_{\textrm{max}}} < \textrm{min reciprocal condition number} λmaxλi<min reciprocal condition number
5. Covariance::Options::apply_loss_function
Default: true
用于控制核函数对协防差的影响
Even though the residual blocks in the problem may contain loss functions, setting apply_loss_function
to false will turn off the application of the loss function to the output of the cost function and in turn its effect on the covariance.
6. 在ceres中计算参数块对应的协防差
6.1 bool Covariance::Compute(const vector<pair<const double *, const double *>> &covariance_blocks, Problem *problem)
其中covariance_blocks
表示要计算哪些参数块的协防差,
由于协防差是对称性的,所以用户往covariance_blocks
中传进去一个<block1, block2>, 那么用户可以通过GetCovarianceBlock
得到(block1, block2)和(block2, block1)的协防差
covariance_blocks
不能包含重复的参数块,否则将发生bad thing
在计算协防差的,ceres会使用所有的Jacobian来计算一个大H
,然后根据covariance_blocks
的设置选择计算哪些部分的协防差,即covariance_blocks
不会影响要使用哪些Jacobian来参与计算
6.2 bool GetCovarianceBlock(const double *parameter_block1, const double *parameter_block2, double *covariance_block) const
在调用该函数之前,需要先调用上面的compute来添加参数块,然后再获取<parameter_block2, parameter_block1>对应的协防差
covariance_block
必须指向一个parameter_block1_size x parameter_block2_size
大小的内存块
6.3 bool GetCovarianceBlockInTangentSpace(const double *parameter_block1, const double *parameter_block2, double *covariance_block) const
Returns cross-covariance in the tangent space if a local parameterization is associated with either parameter block; else returns cross-covariance in the ambient space.