最近在看ATOM,作者在线训练了一个分类器,用的方法是高斯牛顿法和共轭梯度法。看不懂,于是恶补了一波。学习这些东西并不难,只是难找到学习资料。简单地搜索了一下,许多文章都是一堆公式,这谁看得懂啊。
后来找到一篇《An Introduction to the Conjugate Gradient Method Without the Agonizing Pain》,解惑了。
为什么中文没有这么良心的资料呢?英文看着费劲,于是翻译过来搬到自己的博客,以便回顾。
由于原文比较长,一共 66 66 66 页的PDF,所以这里分成几个部分来写。
目录
共轭梯度法(Conjugate Gradients)(1)
共轭梯度法(Conjugate Gradients)(2)
共轭梯度法(Conjugate Gradients)(3)
共轭梯度法(Conjugate Gradients)(4)
共轭梯度法(Conjugate Gradients)(5)
给定输入 A A A, b b b,起始值 x x x,最大迭代次数 i m a x i_{max} imax,容忍误差(error tolerance) ε < 1 \varepsilon < 1 ε<1:
i ⇐ 0 r ⇐ b − A x δ ⇐ r T r δ 0 ⇐ δ While i < i m a x and δ > ε 2 δ 0 do q ⇐ A r α ⇐ δ r T q x ⇐ x + α r If i is divisible by 50 r ⇐ b − A x else r ⇐ r − α q δ ⇐ r T r i ⇐ i + 1 \begin{aligned} & i \Leftarrow 0 \\ & r \Leftarrow b-Ax \\ & \delta \Leftarrow r^T r \\ & \delta _0 \Leftarrow \delta \\ & \text{While} \; \; i < i_{max} \; \; \text{and} \; \; \delta > \varepsilon^2 \delta_0 \; \; \text{do} \\ & \qquad q \Leftarrow Ar \\ & \qquad \alpha \Leftarrow \dfrac{\delta}{ r^T q} \\ & \qquad x \Leftarrow x + \alpha r \\ & \qquad \text{If} \; \; i \; \; \text{is divisible by 50} \\ & \qquad \qquad r \Leftarrow b - A x \\ & \qquad \text{else} \\ & \qquad \qquad r \Leftarrow r - \alpha q \\ & \qquad \delta \Leftarrow r^T r \\ & \qquad i \Leftarrow i + 1 \end{aligned} i⇐0r⇐b−Axδ⇐rTrδ0⇐δWhilei<imaxandδ>ε2δ0doq⇐Arα⇐rTqδx⇐x+αrIfiis divisible by 50r⇐b−Axelser⇐r−αqδ⇐rTri⇐i+1
当迭代次数达到 i m a x i_{max} imax ,或者 ∥ r ( i ) ∥ ≤ ε ∥ r ( 0 ) ∥ \| r_{(i)}\| \leq \varepsilon \| r_{(0)}\| ∥r(i)∥≤ε∥r(0)∥ 的时候停止迭代。
通常我们用的是残差的快速递归公式,但是每进行 50 50 50 次迭代,就会重新计算精确的残差,以消除累积的浮点误差。当然,这个 50 50 50 是可以任意设置的,对于比较大的 n n n,采用 n \sqrt{n} n 比较合适。
如果 ε \varepsilon ε 很大,那就不需要修正残差(实际中也很少用到修正)。如果 tolerance 接近你的机器的浮点数精度的极限,那在计算了 δ \delta δ 之后,就要检查一下是否 δ ≤ ε 2 δ 0 \delta \leq \varepsilon^2\delta_0 δ≤ε2δ0,如果是,那就得重新计算精确的残差值,再重新计算 δ \delta δ。这能够预防浮点数舍入误差造成的早停。
给定输入 A A A, b b b,起始值 x x x,最大迭代次数 i m a x i_{max} imax,容忍误差(error tolerance) ε < 1 \varepsilon < 1 ε<1:
i ⇐ 0 r ⇐ b − A x d ⇐ r δ n e w ⇐ r T r δ 0 ⇐ δ n e w While i < i m a x and δ > ε 2 δ 0 do q ⇐ A d α ⇐ δ n e w d T q x ⇐ x + α d If i is divisible by 50 r ⇐ b − A x else r ⇐ r − α q δ o l d ⇐ δ n e w δ n e w ⇐ r T r β ⇐ δ n e w δ ( o l d ) d ⇐ r + β d i ⇐ i + 1 \begin{aligned} & i \Leftarrow 0 \\ & r \Leftarrow b-Ax \\ & d \Leftarrow r \\ & \delta _{new} \Leftarrow r^Tr \\ & \delta _{0} \Leftarrow \delta _{new} \\ & \text{While} \; \; i < i_{max} \; \; \text{and} \; \; \delta > \varepsilon^2 \delta_0 \; \; \text{do} \\ & \qquad q \Leftarrow Ad \\ & \qquad \alpha \Leftarrow \dfrac{\delta_{new}}{ d^T q} \\ & \qquad x \Leftarrow x + \alpha d \\ & \qquad \text{If} \; \; i \; \; \text{is divisible by 50} \\ & \qquad \qquad r \Leftarrow b - A x \\ & \qquad \text{else} \\ & \qquad \qquad r \Leftarrow r - \alpha q \\ & \qquad \delta_{old} \Leftarrow \delta_{new} \\ & \qquad \delta_{new} \Leftarrow r^T r \\ & \qquad \beta \Leftarrow \dfrac{\delta_{new} }{ \delta_{(old)} } \\ & \qquad d \Leftarrow r + \beta d \\ & \qquad i \Leftarrow i + 1 \end{aligned} i⇐0r⇐b−Axd⇐rδnew⇐rTrδ0⇐δnewWhilei<imaxandδ>ε2δ0doq⇐Adα⇐dTqδnewx⇐x+αdIfiis divisible by 50r⇐b−Axelser⇐r−αqδold⇐δnewδnew⇐rTrβ⇐δ(old)δnewd⇐r+βdi⇐i+1
[见 B1. 小节的说明]
给定输入 A A A, b b b,起始值 x x x, preconditioner M M M(可能是隐式定义的), 最大迭代次数 i m a x i_{max} imax,容忍误差(error tolerance) ε < 1 \varepsilon < 1 ε<1:
i ⇐ 0 r ⇐ b − A x d ⇐ M − 1 r δ n e w ⇐ r T d δ 0 ⇐ δ n e w While i < i m a x and δ > ε 2 δ 0 do q ⇐ A d α ⇐ δ n e w d T q x ⇐ x + α d If i is divisible by 50 r ⇐ b − A x else r ⇐ r − α q s ⇐ M − 1 r δ o l d ⇐ δ n e w δ n e w ⇐ r T s β ⇐ δ n e w δ o l d d ⇐ s + β d i ⇐ i + 1 \begin{aligned} & i \Leftarrow 0 \\ & r \Leftarrow b-Ax \\ & d \Leftarrow M^{-1}r \\ & \delta _{new} \Leftarrow r^T d \\ & \delta _{0} \Leftarrow \delta _{new} \\ & \text{While} \; \; i < i_{max} \; \; \text{and} \; \; \delta > \varepsilon^2 \delta_0 \; \; \text{do} \\ & \qquad q \Leftarrow Ad \\ & \qquad \alpha \Leftarrow \dfrac{\delta_{new}}{ d^T q} \\ & \qquad x \Leftarrow x + \alpha d \\ & \qquad \text{If} \; \; i \; \; \text{is divisible by 50} \\ & \qquad \qquad r \Leftarrow b - A x \\ & \qquad \text{else} \\ & \qquad \qquad r \Leftarrow r - \alpha q \\ & \qquad s \Leftarrow M^{-1} r \\ & \qquad \delta_{old} \Leftarrow \delta_{new} \\ & \qquad \delta_{new} \Leftarrow r^T s \\ & \qquad \beta \Leftarrow \dfrac{\delta_{new} }{ \delta_{old} } \\ & \qquad d \Leftarrow s + \beta d \\ & \qquad i \Leftarrow i + 1 \end{aligned} i⇐0r⇐b−Axd⇐M−1rδnew⇐rTdδ0⇐δnewWhilei<imaxandδ>ε2δ0doq⇐Adα⇐dTqδnewx⇐x+αdIfiis divisible by 50r⇐b−Axelser⇐r−αqs⇐M−1rδold⇐δnewδnew⇐rTsβ⇐δoldδnewd⇐s+βdi⇐i+1
“ s ⇐ M − 1 r ” “\; s \Leftarrow M^{-1} r \; ” “s⇐M−1r” 这一条声明意味着你应该应用 preconditioner,不一定要以矩阵的形式。
剩下的,同样 [见 B1. 小节的说明]。
给定一个函数 f f f,起始值 x x x,CG 的最大迭代次数 i m a x i_{max} imax,CG 的容忍误差(error tolerance) ε < 1 \varepsilon < 1 ε<1,牛顿-拉夫森(Newton-Raphson) 的最大迭代次数 j m a x j_{max} jmax,牛顿-拉夫森的容忍误差 ϵ < 1 \epsilon < 1 ϵ<1 有:
i ⇐ 0 k ⇐ 0 r ⇐ − f ′ ( x ) d ⇐ r δ n e w ⇐ r T r δ 0 ⇐ δ n e w While i < i m a x and δ n e w > ε 2 δ 0 do j ⇐ 0 δ d ⇐ d T d Do α ⇐ = [ f ′ ( x ) ] T d d T f ′ ′ ( x ) d x ⇐ x + α d j ⇐ j + 1 while j < j m a x and α 2 δ d > ϵ 2 r ⇐ − f ′ ( x ) δ o l d ⇐ δ n e w δ n e w ⇐ r T r β ⇐ δ n e w δ o l d d ⇐ r + β d k ⇐ k + 1 If k = n or r T d ≤ 0 d ⇐ r k ⇐ 0 i ⇐ i + 1 \begin{aligned} & i \Leftarrow 0 \\ & k \Leftarrow 0 \\ & r \Leftarrow -f'(x) \\ & d \Leftarrow r \\ & \delta _{new} \Leftarrow r^T r \\ & \delta _{0} \Leftarrow \delta _{new} \\ & \text{While} \; \; i < i_{max} \; \; \text{and} \; \; \delta_{new} > \varepsilon^2 \delta_0 \; \; \text{do} \\ & \qquad j \Leftarrow 0 \\ & \qquad \delta_d \Leftarrow d^Td \\ & \qquad \text{Do} \\ & \qquad \qquad \alpha \Leftarrow = \dfrac{ [f'(x)]^T d }{ d^T f''(x)d } \\ & \qquad \qquad x \Leftarrow x + \alpha d \\ & \qquad \qquad j \Leftarrow j +1 \\ & \qquad \text{while} \; \; j
当迭代次数达到 i m a x i_{max} imax ,或者 ∥ r ( i ) ∥ ≤ ε ∥ r ( 0 ) ∥ \| r_{(i)}\| \leq \varepsilon \| r_{(0)}\| ∥r(i)∥≤ε∥r(0)∥ 的时候停止迭代。
每次 Newton-Raphson 迭代都对 x x x 加上 α d \alpha d αd,它的迭代结束条件是:更新值 α d \alpha d αd 小于给定的容忍度( ∥ α d ∥ < ϵ \| \alpha d\| < \epsilon ∥αd∥<ϵ),或者迭代次数达到了 j m a x j_{max} jmax。
可以通过使用较小的 j m a x j_{max} jmax ,同时/或者 用它的对角元素来近似海森矩阵 f ′ ′ ( x ) f''(x) f′′(x) 来完成快速精确的线搜索。
一旦算出来的搜索方向不是一个下降方向,那就要重启非线性 CG(通过令 d ⇐ r d\Leftarrow r d⇐r)。每迭代 n n n 次也会重启一次,以提高收敛性(当 n n n 很小的时候)。
计算 α \alpha α 的时候,可能会出现 “除以 0 0 0” 的错误,因为起始点 x ( 0 ) x_(0) x(0) 可能距离期望的最小值不够近,或者 f f f 不是二阶连续可导。
前一种情况的解决办法是,选择一个更好的起点,或者用更复杂的线搜索。对于后一种情况, CG 也许不是最合适的最小化算法。
给定一个函数 f f f,起始值 x x x,CG 的最大迭代次数 i m a x i_{max} imax,CG 的容忍误差(error tolerance) ε < 1 \varepsilon < 1 ε<1。
弦截法(Secant) 的步长 σ 0 \sigma_0 σ0,最大迭代次数 j m a x j_{max} jmax,Secant 的容忍误差 ϵ < 1 \epsilon < 1 ϵ<1 ,有:
i ⇐ 0 k ⇐ 0 r ⇐ − f ′ ( x ) Calculate a preconditioner M ≈ f ′ ′ ( x ) s ⇐ M − 1 r d ⇐ s δ n e w ⇐ r T d δ 0 ⇐ δ n e w While i < i m a x and δ n e w > ε 2 δ 0 do j ⇐ 0 δ d ⇐ d T d α ⇐ − σ 0 η p r e v ⇐ [ f ′ ( x + σ 0 d ) ] T d Do η ⇐ [ f ′ ( x ) ] T d α ⇐ α η η p r e v − η x ⇐ x + α d η p r e v ⇐ η j ⇐ j + 1 while j < j m a x and α 2 δ d > ϵ 2 r ⇐ − f ′ ( x ) δ o l d ⇐ δ n e w δ m i d ⇐ r T s Calculate a preconditioner M ≈ f ′ ′ ( x ) s ⇐ M − 1 r δ n e w ⇐ r T s β ⇐ δ n e w − δ m i d δ o l d k ⇐ k + 1 If k = n or β ≤ 0 d ⇐ s k ⇐ 0 else d ⇐ s + β d i ⇐ i + 1 \begin{aligned} & i \Leftarrow 0 \\ & k \Leftarrow 0 \\ & r \Leftarrow -f'(x) \\ & \text{Calculate a preconditioner} \;\; M \approx f''(x) \\ & s \Leftarrow M^{-1} r \\ & d \Leftarrow s \\ & \delta _{new} \Leftarrow r^T d \\ & \delta _{0} \Leftarrow \delta _{new} \\ & \text{While} \; \; i < i_{max} \; \; \text{and} \; \; \delta_{new} > \varepsilon^2 \delta_0 \; \; \text{do} \\ & \qquad j \Leftarrow 0 \\ & \qquad \delta_d \Leftarrow d^Td \\ & \qquad \alpha \Leftarrow - \sigma_0 \\ & \qquad \eta_{prev} \Leftarrow [f'(x+ \sigma_0 d)]^T d \\ & \qquad \text{Do} \\ & \qquad \qquad \eta \Leftarrow [f'(x)]^T d \\ & \qquad \qquad \alpha \Leftarrow \alpha \dfrac{ \eta }{ \eta_{prev} - \eta } \\ & \qquad \qquad x \Leftarrow x + \alpha d \\ & \qquad \qquad \eta_{prev} \Leftarrow \eta \\ & \qquad \qquad j \Leftarrow j +1 \\ & \qquad \text{while} \; \; j
当迭代次数达到 i m a x i_{max} imax ,或者 ∥ r ( i ) ∥ ≤ ε ∥ r ( 0 ) ∥ \| r_{(i)}\| \leq \varepsilon \| r_{(0)}\| ∥r(i)∥≤ε∥r(0)∥ 的时候停止迭代。
每次 Secant 迭代都对 x x x 加上 α d \alpha d αd,它的迭代结束条件是:更新值 α d \alpha d αd 小于给定的容忍度( ∥ α d ∥ < ϵ \| \alpha d\| < \epsilon ∥αd∥<ϵ),或者迭代次数达到了 j m a x j_{max} jmax。使用较小的 j m a x j_{max} jmax 可以完成快速精确线搜索。参数 σ 0 \sigma_0 σ0 决定了 式子(59) 中的 σ \sigma σ 值,用于每次 Secant 法最小化过程中的第 1 1 1 个迭代。为了能收敛,这个参数可能需要调节。
Polak-Ribière 法的参数 β \beta β 是:
δ n e w − δ m i d δ o l d = r ( i + 1 ) T s ( i + 1 ) − r ( i + 1 ) T s ( i ) r ( i ) T s ( i ) = r ( i + 1 ) T M − 1 ( r ( i + 1 ) − r ( i ) ) r ( i ) T M − 1 r ( i ) \dfrac{\delta_{new} - \delta_{mid}}{\delta_{old}} = \dfrac{r^T_{(i+1)} s_{(i+1)} - r^T_{(i+1)} s_{(i)} }{ r^T_{(i)} s_{(i)} } = \dfrac{ r_{(i+1)}^T M^{-1} (r_{(i+1)} - r_{(i)}) }{ r_{(i)}^T M^{-1} r_{(i)} } δoldδnew−δmid=r(i)Ts(i)r(i+1)Ts(i+1)−r(i+1)Ts(i)=r(i)TM−1r(i)r(i+1)TM−1(r(i+1)−r(i))
需要注意的是, preconditioner M M M 总是正定的。它不一定要是矩阵的形式。
一旦 Polak-Ribière 的参数 β \beta β 变成负数,就要重启非线性 CG(令 d ⇐ r d \Leftarrow r d⇐r)。每迭代 n n n 次也会重启一次,以提高收敛性(当 n n n 很小的时候)。
非线性 CG 有几种选择:
是否 Preconditioned;
用牛顿-拉夫森(Newton-Raphson)法或者弦截(Secant)法或者别的;
Fletcher-Reeves 或者 Polak-Ribière。
还可以从上面提到的方法中构造各种变体。( Polak-Ribière 几乎总是首选的。)