舒尔补 / 稀疏性 (Schur complement / Sparsity)
光束法平差乍看起来难以处理:一个有 个关键帧和 个地图点的适中规模地图,未知数个数为 ,而 轻易就能达到数十万。使其变得可行的原因是这个问题具有稀疏性,而**舒尔补(Schur complement)**正是利用这种稀疏性的技巧。
稀疏性从何而来。 每一个重投影误差项只涉及一个位姿和一个地图点。因此,在高斯-牛顿正规方程 (其中 )中,Hessian矩阵具有箭头状的分块结构
其中 ()只耦合位姿,()只耦合地图点,而 保存位姿-地图点之间的耦合关系。关键之处在于,两个地图点绝不会出现在同一个残差项中,因此 是块对角的——每个地图点对应一个独立的 块。
舒尔补步骤(也称为边缘化掉地图点)从线性系统中消去地图点变量,留下简化后的相机系统:
由于 是块对角的,求 几乎不花代价(对每个 块分别求逆即可)。求解 的简化系统得到位姿更新量,然后通过回代独立地恢复每个地图点的更新量。一个 维的求解就变成了 维的求解——当 (这总是成立)时,速度提升几个数量级。
实践中还有两层额外的稀疏性值得关注。第一,简化后的相机矩阵 本身也是稀疏的:条目 非零仅当关键帧 和 观测到共同的地图点(即共视结构),因此配合良好的变量排序(COLAMD)的稀疏Cholesky分解可以应用于此。第二,同样的消元视角可以推广:在因子图术语中,舒尔补正是变量消元,这正是滑动窗口VIO和iSAM2等增量式平滑器中边缘化操作的底层原理。
公式从何而来
舒尔补并没有什么神秘之处,它不过是分块高斯消元。写出正规方程的两个分块行:
从第二行解出地图点更新量 ,并代入第一行——上面的简化相机系统立即出现,而同一个表达式在求出 之后就是回代规则。从统计角度看,简化后的系统正是相机变量边缘分布的信息矩阵形式:消去地图点并不是任何近似,而是对同一个高斯分布的精确重新表达。
计算量对比。 直接稠密求解整个系统的代价是 。使用舒尔技巧:求 的逆是 次独立的 求逆(),构造简化系统的代价受观测数量约束,剩余求解的最坏情况是 ——通常由于共视稀疏性远低于此。当 为数百、 为数十万时,消去地图点的差异就是毫秒和分钟之间的区别。当 本身变大时(城市级SfM),即使简化后的系统也不再便宜,求解器会转向迭代方法(对舒尔补做预条件共轭梯度——Ceres的 ITERATIVE_SCHUR)。
在Ceres中,所有这些只需一个配置选项:
ceres::Solver::Options options;
options.linear_solver_type = ceres::SPARSE_SCHUR; // or DENSE_SCHUR, ITERATIVE_SCHUR
求解器会自动检测位姿/地图点的消元顺序(或者接受显式的 ParameterBlockOrdering)。每一个正式的求解器——Ceres、g2o、GTSAM——都实现了同样的技巧;理解它可以解释为什么BA能够扩展、为什么边缘化旧状态会在剩余Hessian中产生填充项(稠密块),以及为什么求解器选择和排序会导致运行时间相差几个数量级。
常见陷阱
- 以错误的顺序消元——这个技巧之所以有效,是因为地图点数量多、代价低、且相互独立;如果先消去位姿,会把它们各自的地图点全部耦合在一起,使系统变得稠密。消元顺序是一个关乎性能正确性的决策。
- 将边缘化与删除混为一谈——丢弃旧状态和边缘化旧状态是不同的:边缘化会把它们的信息保留为对其邻居的一个稠密先验(填充项)。正是这种稠密性,使得滑动窗口VIO系统需要仔细选择边缘化哪些状态、丢弃哪些状态。
- 规范自由度(gauge freedom)——单目情况下完整BA有7个不可观测的自由度(6+尺度);如果不固定某个位姿(或添加先验),简化后的相机矩阵是奇异的,求解器会举步维艰甚至失败。
- 远处地图点导致的病态——深度接近无穷的地图点使其 块几乎奇异;逆深度参数化或深度先验可以让 保持良好的数值性质。
对SLAM的意义
实时SLAM之所以存在,正是因为有利用结构的线性代数:如果没有舒尔补,即使只有几百个关键帧的光束法平差也是无望的。同样的思想——消去变量、保持问题稀疏——在边缘化、滑动窗口估计器和增量式平滑中反复出现,因此这是整个路线图中收益最高的数学知识点之一。