looyifan / Newton Conjugate Gradient Method

Created 6 days ago Modified 6 days ago

Newton Conjugate Gradient Method

共轭梯度法

  • 背景
    • 本质上是一种求Ax=bAx=b的方法,它厉害在不需要知道AA的具体值,只需要多调用几次AyAy点积接口就可以把xx求出来
    • 计算复杂度
      • 函数的梯度的计算复杂度一般是O(n)O\left ( n \right )
      • 求函数的梯度的复杂度和求函数本身的复杂度是常数倍的关系
      • Hessian的计算复杂度是O(n2)O\left ( n^{2} \right )
      • Hessian的逆的计算复杂度是O(n3)O\left ( n^{3} \right )
      • Hessian-vec的复杂度是O(n)O\left ( n \right ),证明过程如下:
        • 假设ξ\xi 是一个已知的常向量
        • 根据泰勒展开有:f(x+αξ)=f(x)+α2f(x)ξ+o(α)\triangledown f(x+\alpha\xi)=\triangledown f(x)+\alpha\triangledown^{2}f(x)\xi +o(\left|\alpha\right|)
        • 简单变形:2f(x)ξf(x+αξ)f(x)α\triangledown^{2}f(x)\xi\approx\frac{\triangledown f(x+\alpha\xi)-\triangledown f(x)}{\alpha}
        • 可以发现,求Hessian-vec的近似解只需要求原函数的两次导即可
      • hessian-vec
  • Linear Conjugate Gradient Method
    • 针对问题Ax=bAx=b,我们可以将其转化成一个优化问题argminxf(x)=12xTAxbTxargmin_{x}f(x)=\frac{1}{2}x^{T}Ax-b^{T}x,因为该优化问题的导数是AxbAx-b,最优解即令其导数为零的点。
    • 梯度下降法和牛顿法求该问题
      • gd newton
      • 梯度法没法得到精确解,步长总会引入误差;牛顿法计算量太大,而且牛顿法需要求A1A^{-1},而我们本来就是要求这个,鸡生蛋蛋生鸡了;我们需要一种折中的方法——LCG方法
    • 假设xRnx\in R^{n},LCG法就是找nn个互相共轭(如果AA是单位阵,共轭就是垂直)的向量,每次沿着一个向量(的方向)走到最低点,最终一定能走到全局最低点
      • 下图是AA为单位阵的情况
        • lcg
      • general的情况如下
        • lcg general
    • LCG算法流程
      • nn个互相共轭的向量
        • 初始化nn个线性不相关的向量v1,,vnv^{1},…,v^{n}
        • 计算互相共轭的向量:
        • cg vector
        • 这里的投影操作也叫做Gram-Schmidt process,分别考虑AA是单位阵(右)和AA不是单位阵(左)的情况:
        • conjugare proj
        • 最终得到的e1,,ene^{1},…,e^{n}就是我们需要的互相共轭的向量
        • 注意到计算vnv^{n}的时候需要对过去的n1n-1个向量做投影,这个计算量很大,我们可以增量地计算vkv^{k}(这也是lcg方法一个很大的贡献点):
        • inc cg vector
        • 至于为什么用这种方法生成的vkv^{k}就可以保证projuj(vk)=0proj_{u^{j}}(v^{k})=0可以去看论文证明
      • 有了互相共轭向量后,继续看迭代流程
        • lcg progress
        • α\alpha的迭代公式是由公式12(xk+αuk)A(xk+αuk)bT(xk+αuk)\frac{1}{2}(x^{k}+\alpha u^{k})A(x^{k}+\alpha u^{k})-b^{T}(x^{k}+\alpha u^{k})的导数取0推导而来的
        • 公式中的AukAu^{k}不需要把AA(也是该优化目标函数的Hessian)完整的算出来,直接用Hessian-vec方法进行近似求解,计算复杂度和求导一样
      • 最终的伪代码流程如下:
        • lcg code
    • LCG特点
      • 很多时候需要在求LCG之前把AA normalize一下,可以通过L-BFGS(memory size=8)去近似估计BB(即Hessian的逆),令A~=B12AB12\tilde{A}=B^{\frac{1}{2}}AB^{\frac{1}{2}},对A~x=b\tilde{A}x=b进行lcg求解,最后将xx做线性变换恢复到真实值。A~\tilde{A}的条件数会比AA更低,CG过程会收敛的更快。下图是一个例子,A的维度是555×555555\times 555,条件数是101010^{10},Preconditioned CG收敛速度比其他方法快很多
        • cg with preconditioner
  • Newton-CG Method
    • 回顾一下newton要解的问题(2f)d=f(\triangledown^{2}f)d=-\triangledown f,套用上面的LCG方法就可以解出dd。但还有两个问题需要考虑:
      • 如何处理Hessian不正定的问题?
        • Truncated CG(截断法),见下面的算法流程
      • 我们是否需要求一个精确的dd
        • 答案是否。针对问题Hd=gHd=-g,我们只需要保证limg0dd~g=0\displaystyle\lim_{g\to0}\frac{\left|d^{*}-\tilde{d}\right|}{\left|g\right|}=0即可(dd^{*}是最优解,d~\tilde{d}是迭代得到的解),简单说就是一开始梯度还比较大的时候,我们求的dd精度也不需要很高,越靠近最优点的时候,精度要求越高。这是牛顿法非常重要的一个结论。
    • 算法流程(伪代码)
      • newton cg
      • 本质上就是将牛顿法中求解下降方向的步骤替换成蓝色框中的模块
      • 注意点
        • dd需要初始化为0向量,因为我们希望最优的direction尽可能稳定,所以需要它从0开始出发
        • (uj)T2f(xk)uj0(u^{j})^{T}\triangledown^{2}f(x^{k})u^{j}\leq0时,说明我们当前所处的位置的Hessian是不定的,分两种情况对待:
          • 如果当前是第一次迭代,那可能是我们距离最优解太远了,这时候直接采用sgd方法更新direction(djd^{j}
          • 如果当前不是第一次迭代,就直接break,依然使用上一次算出来的direction去更新外部的循环(因为本次的direction可能会让函数上升,上一次的虽然是旧的信息,但至少方向没错),这就是截断法
    • 算法对比
      • newton cg vs lbfgs
      • 两种都是Hessian-Free的方法
      • 两种方法只能保证函数值是单调下降的,不能保证梯度的模是单调下降的
      • 通常情况下,Newton-CG比L-BFGS的最终得到的梯度模长更小

Gitalking ...