协方差估计
介绍
鉴别最小二乘问题返回值好坏的一个方法是分析解的协方差。我们考虑非线性回归问题。
如果 J(x∗) 是列非满秩的。那么协方差矩阵 C(x∗) 也是非满秩的,由 Moore-Penrose pseudo inverse给出。
规范不变性
在SfM问题(3D重建)中,重建无法区分相似变换,这被称作 Gauge Ambiguity。正确地处理Gauges需要使用SVD或自定义的反演算法。对于小问题用户可以使用稠密算法。更多细节请看Kanatani & Morris的论文Gauges and gauge transformations for uncertainty description of geometric structure with indeterminacy。
协方差
Covariance 允许用户求解非线性最小二乘问题的协方差,并提供对其块的随机访问。计算假设成本函数计算残差的协方差是单位矩阵。
由于计算协方差矩阵一个潜在的大矩阵的逆,这可能需要大量的时间和内存。然而,通常用户只对协方差的很小一部分感兴趣,通常是对角块。Covariance 允许用户指定协方差矩阵中感兴趣的部分,并仅计算和存储这一部分。
Jacobian 的秩
正如我们上面所提到的,如果Jacobian矩阵的秩不足,那么 J′J 的逆就没有定义,而是需要计算一个伪逆。J的秩不足可以是被认为是零或数值的列,这取决于雅可比矩阵的确切值。
当问题包含常量参数块时,就会出现结构秩的不足。这个类正确地处理结构秩的不足。
数值秩的不足,由于它的稀疏结构不能预测矩阵的秩,并且需要看它的数值,这是比较复杂的。这里有两种情况。
Covariance::Options
class Covariance::Options
Covariance::Options::num_threads
Default: 1
计算Jacobian和协方差所使用的线程数。
Covariance::Options::sparse_linear_algebra_library_type
Default: SUITE_SPARSE
Ceres Solver支持 SuiteSparse 和 EIGEN_SPARSE,EIGEN_SPARSE总是可用的。
Covariance::Options::algorithm_type
Default: SPARSE_QR
Ceres Solver支持两种不同的算法计算协方差,代表速度,精度和可靠性的权衡。
Covariance::Options::min_reciprocal_condition_number
Default: 10−14
如果Jacobian矩阵接近奇异,那么 J′J 逆就会导致不可靠的结果,例如,如果
这不是一个有用的结果。因此,默认 Covariance::Compute() 将会返回 false,如果遇到一个秩不足的矩阵.鉴别秩不足依赖于算法
Covariance::Options::null_space_rank
当使用 DENSE_SVD,用户在处理正定和近似正定协方差矩阵有更多的控制。我们计算 J′J 的 Moore-Penrose伪逆矩阵代替 J′J 。
如果 J′J 有特征值分解 (λi,ei) , λi 是第i个特征值, ei 是对应的特征向量, J′J 的逆是
怎样去掉项,由min_reciprocal_condition_number和null_space_rank控制。
如果null_space_rank是非负的,最小的 null_space_rank 特征值/特征向量被丢弃在相应的 λi 大小。如果被截断矩阵中最小的非零特征值与最大的特征值的比值仍然低于min_reciprocal_condition_number,那么 Covariance::Compute() 将会失败并返回false。设置null_space_rank = -1 去掉所有的项
Covariance::Options::apply_loss_function
Default: true
即使问题的残差块包含损失函数,将apply_loss_function设置成false将关闭应用损失函数。
Covariance::Options::apply_loss_function
Default: true
即使问题的残差块包含损失函数,将apply_loss_function设置成false将关闭应用损失函数。
class Covariance
Covariance::Options 正如名字一样,是用来控制协方差估计算法的。Covariance求解是一种复杂的数值敏感的计算。请参阅Covariance::Options 的所有文档,在使用Covariance之前。
Covariance::Compute
计算一部分协方差矩阵。向量 covariance_blocks,利用参数块对协方差矩阵块进行索引。这使得协方差估计算法只能计算和存储这些块。
由于协方差矩阵是对称的,如果用户传递block1, block2,那么GetCovarianceBlock可以通过 block1, block2和block2, block1调用。
covariance_blocks包含重复,如果重复会发生不好的事情。
注意,covariance_blocks的列表只用于确定计算协方差矩阵的哪些部分。完整的Jacobian矩阵用来做计算,也就是说,它们对Jacobian矩阵的计算部分没有影响。
返回值表示协方差计算的成功或失败。请参阅 Covariance::Options的文档关于更多该函数返回false的条件的选项。
GetCovarianceBlock
返回与parameter_block1和parameter_block2相对应的互协方差矩阵的块。
Compute 必须在第一次调用GetCovarianceBlock之前,并且在调用 Compute时,必须在矢量covariance_blocks中出现arameter_block1, parameter_block2 或者 parameter_block2, parameter_block1这两个参数否则,GetCovarianceBlock将返回false。
covariance_block必须指向一个parameter_block1_size × parameter_block2_size大小的内存位置。返回的协方差将是一个行优先矩阵。
GetCovarianceBlockInTangentSpace
返回与parameter_block1和parameter_block2相对应的互协方差矩阵的块。在切空间返回互协方差如果本地参数化与参数块有关,否则就会在环境空间中返回互协方差。
Compute 必须在第一次调用GetCovarianceBlockInTangentSpace之前,并且在调用 Compute时,必须在矢量covariance_blocks中出现arameter_block1, parameter_block2 或者 parameter_block2, parameter_block1这两个参数否则,GetCovarianceBlockInTangentSpace将返回false。
covariance_block必须指向一个parameter_block1_size × parameter_block2_size大小的内存位置。返回的协方差将是一个行优先矩阵。
例子
double x[3];
double y[2];
Problem problem;
problem.AddParameterBlock(x, 3);
problem.AddParameterBlock(y, 2);
Covariance::Options options;
Covariance covariance(options);
vectorconst double*, const double*> > covariance_blocks;
covariance_blocks.push_back(make_pair(x, x));
covariance_blocks.push_back(make_pair(y, y));
covariance_blocks.push_back(make_pair(x, y));
CHECK(covariance.Compute(covariance_blocks, &problem));
double covariance_xx[3 * 3];
double covariance_yy[2 * 2];
double covariance_xy[3 * 2];
covariance.GetCovarianceBlock(x, x, covariance_xx)
covariance.GetCovarianceBlock(y, y, covariance_yy)
covariance.GetCovarianceBlock(x, y, covariance_xy)