DynamicFusion之预处理共轭梯度下降(Pre-conditioned Conjugate Gradient Solver)

在看DynamicFusion这篇文章时,同学们有可能会主要到文章运到了一个很让人百思不解的solver叫做Pre-conditioned Conjugate Gradient Solver。在****上转了一圈发现,对于conjugate gradient method深入讲解的文章少之又少,所以决定写一篇能让有一定线性代数基础的同学理解得懂的文章。Ok, let’s get started.

迭代优化问题

假设我们有一个线性问题(用AAbb来去求xx):
Ax=bAx = b
如果用直接法(direct method)来求得话,我们可以直接得到:
x=(ATA)1ATbx = (A^TA)^{-1}A^Tb
这种方法好但是如果AA是一个Rn×nR^{n\times n}n>108n > 10^8的矩阵的话,对ATAA^TA直接做Inverse显然是不可取的。于是非直接的迭代优化方式就此诞生。简单来说间接法是用迭代的方式更新xx来缩小AxAxbb的距离。
δx=arg minδx(E(x+δx))=arg minδx(12A(x+δx)b2)\delta x = \argmin_{\delta x}(E(x + \delta x)) = \argmin_{\delta x} (\frac{1}{2}||A(x + \delta x)-b||^2)
x=x+δxx' = x + \delta x
不断迭代知道更新后的xx'对距离影响与之前相比不大为止(convergence)。

学视觉或者做神经网的朋友可能都会经常接触到一些常用的迭代优化的算法,如:

  1. 梯度下降:δx=αEx\delta x = \alpha \frac{\partial E}{\partial x}α\alpha是更新大小(step size)
  2. 高斯牛顿:δx=(JTJ)1JTe\delta x = (J^TJ)^{-1}J^TeJJEE对于xx的雅可比
  3. Levenberg-Marquardt:δx=(JTJ+λI)1JTe\delta x = (J^TJ + \lambda I)^{-1}J^Teλ\lambda是一个梯度下降和高斯牛顿的过渡值。
  4. 共轭梯度下降δx=xk+αpk\delta x =x_k + \alpha p_kpkp_k是Krylov子空间的一个基向量

Krylov子空间

要想理解共轭梯度下降的动机和原理,我们上来要重温一下Krylov子空间和Krylov序列(Krylov sequence)这些经典的线性代数概念。概念很深奥,我尽量去仔细剖析,记得第一次听学校教授讲解Krylov子空间的时候有种要撞墙的冲动(翻出自己笔记。。。)

我们先来看一个1维的公式,假设我们有一个xx的迭代过程:
xn+1=axn+bx_{n+1} = ax_{n}+b
那么我们如果展开来看的话就会发现:

xn+1=anx0+n!n1!an1bx0+...+n!n1!abn1x0+bnx_{n+1} = a^nx_0 + \frac{n!}{n-1!}a^{n-1}bx_0+ ... + \frac{n!}{n-1!}ab^{n-1}x_0 + b^n

如果我们将bb看为常数,而aa为一个变量的话,我们会发现xn+1x_{n+1}所在的维度空间由nn个基组成:

xn+1Span{1,a,a2,...,an1,an}x_{n+1}\in Span\{1, a, a^2,...,a^{n-1}, a^n\}

而这些基所组成的数列就叫做Krylov数列(Krylov Sequence),而如果只用从a0a^0aia^ii<ni < n基所组成的空间则叫做Krylov子空间(Krylov subspace)

现在我们就可以把aa这个常量延伸到一个多维矩阵中,得到(这里是不是很像迭代过程):
xn+1=Axn+bx_{n+1} = Ax_n + b
那么xn+1x_{n+1}所在的空间则为:
xn+1Span{1,A,A2,...,An1,An}x_{n+1} \in Span \{1, A, A^2, ..., A^{n-1}, A^n\}
这里我们可以看出,从x0x_0xn+1x_{n+1}的过程是一个维度增长的过程,而xix_i所在的空间又成了xi+1x_{i+1}的子空间。既然这样,那么我们能否去重复利用前一个子空间的基去更好地诠释下个延伸后的下一个空间呢?这就是Krylov数列(Krylov Sequence)的重要所在。
DynamicFusion之预处理共轭梯度下降(Pre-conditioned Conjugate Gradient Solver)
如图所示,S(x0)S(x_0)的维度空间是S(x1)S(x_1)空间的子空间,而S(x1)S(x_1)S(x2)S(x_2)的子空间,由此类推。由于S(x0)S(x_0)S(x1)S(x_1)的子空间,所以S(x0)S(x_0)的所有基也是S(x1)S(x_1)的基, 由此类推。

所以我们可以利用迭代过程这个一点点累加的更新性质,以Krylov的形式去更新我们高维度梯度下降的方向从而加速其优化速度。

我们发现从xnxn+1x_{n} \rightarrow x_{n+1}的过程中,S(xn+1)S(x_{n+1})的基只比S(xn)S(x_n)的基多了一个,而共轭梯度会根据residual的方向在每步生成一个基然后再这个基上做梯度下降

共轭梯度下降

Conjugate Gradient算法其实就是在更新过程中根据residual的方向来生成一个Krylov子空间的基(pkp_k),然后再这个基(pkp_k)的方向上做梯度下降。
δx=αkpk\delta x = \alpha_k p_k

这个新的基pkp_k其实是先将residual空间进行对之前基的降维,然后在没有被其他基覆盖过得空间中去一个基梯度下降的方向。

pk=rki=0k1<pi,rk><pi,pi>Apip_k = r_k - \sum_{i=0}^{k-1}\frac{<p_i, r_k>}{<p_i,p_i>_A}p_i

这个部分很像Gram-Schmidt垂直法降维的过程(可以参考QR Factorization: Gram-Schmidt Orthogonalization)

如图所示,Gram-Schmidt是如何利用projection来从v2v_2提取e2e_2这个基的。
DynamicFusion之预处理共轭梯度下降(Pre-conditioned Conjugate Gradient Solver)
(更新中。。。)