共轭梯度法的搜索方向加上负梯度方向是为了什么?

[复制链接]
查看3923 | 回复2 | 2022-12-2 13:20:04 | 显示全部楼层 |阅读模式
共轭梯度法的搜索方向加上负梯度方向是为了什么?
模拟不错 | 2022-12-2 14:22:03 | 显示全部楼层
在数值代数的语境中,对于对称正定矩阵A,要求解
4 ~7 I) h( A' ~" W7 }9 |  G- m* \* t
就可以考虑共轭梯度法。共轭梯度法(与其切比雪夫加速变种)是求解对称正定线性系统的标准算法,但共轭梯度法也经常出现在非线性优化的语境里,这是由于上面线性系统的求解与下面的极小化问题等价:
6 o8 [: y8 `) |7 t+ i3 R" M9 F* b3 C/ Z. n2 ]
从优化的角度看有诸多便利,比如可以求梯度:+ j4 f5 {/ ^$ u! F

; {$ F7 ?: O& Y( Z. \9 j1 |& |3 y! v用梯度下降可以求解线性方程,这个效率不太高,于是有共轭梯度法来救场。+ Q' R3 {. ?- H
若干假设
+ E0 a  _8 J6 @8 M7 b0 B9 e4 _+ Q7 K0 x. t/ K; I6 i
接下来将在以下几个假设下推导出共轭梯度法:! M. V, ^  B2 \5 A7 C, P

    8 [& F3 l! c2 N
  • 首先CG作为一种梯度法,其核心要素在于下降方向与步长:
    . d/ G4 Z, P* k( W8 } 其中是方向,是步长。1 ]- E+ V0 o: X2 F+ C
  • 构成矩阵A导出内积空间下的正交基,4 y. a5 f7 j3 V+ W7 W$ c
    由此,可以写成5 S! [  a8 [) o# C8 }! @# \( W* v
    5 L8 o1 n3 Q, s" {$ Y
  • 对于迭代点, 还希望其具有某种最优性,比如:
      {) f  M( p% I3 e" l2 ` 其中,随着空间的扩张,会逐渐逼近.! j$ R8 J) @9 m/ B8 ^$ @+ b
    这个最优性是共轭梯度法的本质,如果变更最优准则(比如二范数),还可以导出其他算法,不提。
    : Q+ Q( z- i, i
  • 也不能随意取,需要充分利用已知信息,取$ o: @3 z+ N$ k* d
    其中, 也挺合理,即为之前点所在位置的梯度所构成的子空间。9 e' F/ g$ d8 Y4 C5 M  y5 u
    另外,给定初始值后,初始方向也有了,
    9 E( P  X% {1 d- x9 _' z
共轭梯度法的性质3 z8 t( V6 {. |& N0 }) m3 Z
: `+ F9 P' |4 g/ a4 Y) d! K
有了上面这些对于算法的假设或者限制,就可以得到更多关于算法的性质了:
: ~0 F2 ?/ R* G' t$ U9 b

    0 H* D) `" d! J& H
  • 步长的实质与的表示如。果没有假设3的话, 是可以随意取值的,然而有了性质3,就有:. T3 G- I8 {+ S7 p

6 B, z2 `$ |0 P% q* Y2 f由于正交性,立马得到.这说明了,即有限步一定收敛,在收敛性分析中,虽然有限步收敛听起来非常强,但通常N非常大,最后分析线性收敛的界更具有参考性。/ t# N& E2 _/ X, j) w( I" `3 t
    1 G5 @. j& d' }& P5 [
  • 由假设4,由于, 那么有6 Z% N1 R" o/ C
  • 除了上面这条,还有一条非常类似的,由+ F( k0 f8 f* F) W$ ]6 f% f
    推出:. Z2 N! O, o) I! j, q( \% X1 W
    时,由正交性,就有% f& ]$ j/ y; ?+ g5 `* W1 ~+ W
    .! I2 z. \0 I  P' F* R
  • 共轭梯度法已经呼之欲出了,利用正交化,先求出方向:
    7 S6 M2 W  h* {! B1 c$ P7 Q/ p. c
    5 q* U& d2 t- Q
  • 再考虑下具体步长,由于- d$ v8 u5 e" U7 k, p
    那么有
    5 g7 D! h. S. t6 y. ^/ o 也即
    0 J* B' G* Y5 d" I( F
    : V: K4 M6 n6 A4 X8 h " M  `& V4 }8 B6 g# W: A2 f( I% S! [0 M8 }
  • 此时,就得到共轭梯度法的第一个形式
    * F. W% z" Z0 L$ z. M: ]+ ?2 p
    ! x( d0 ]: I9 {9 { 当然,这个形式并不太像教科书上的共轭梯度法,但理论上已经一致了,接下来需要化简。/ ~- ^/ }$ L( K$ C+ T* {8 V
  • 由于, 那么有,性质 4中的式子可以大幅简化,结合步长公式,变成:8 f8 k" k, F/ j* C
    ; w0 Y/ N; k: Z" \4 M0 g7 s
  • 上面的推导需要计算内积,这个还可以被优化掉,注意到
    ! K) X5 t0 u# T- \" k- x9 Q 那么有.' i3 h% l* h9 A  c: u' C
  • 最后的共轭梯度法:/ ^7 H' }4 I% u% ^7 S! }4 C
    ) o5 X* E5 W+ k5 d# G0 Y1 i
算例2 N$ s" Y1 P) T% k( j% N
6 Z( @9 K1 `* g! g& E; f
CG的实现非常简单,考虑求解一个Poisson边值问题,上次用Deepritz方法求解过:
1 ]6 {/ F+ b& K$ L$ G6 s# l7 G. \+ p7 s8 s/ p9 h0 l
离散Poisson方程也讲过很多了,这里不讲如何进行方程的理算与构建了,可参考之前的文章, |. H  z4 ~8 a
派大西:泊松方程求解与卫星组件热布局快速预测.py网格数量为, 那么对应的线性系统矩阵,初始化  l+ L: H9 l% z( _
import numpy as np) ^- i3 x& V/ o2 B8 `- ~
import scipy as sp1 d. Y/ P% C' J% c- C% Y
import matplotlib.pyplot as plt* y- p" @7 C) p5 K
) @& i! Y1 j1 {" W: S) d$ s
Nx = 201( T3 ^6 I2 N1 \# Z2 D
Ny = 201
4 T( o& }, R% j2 E) mdx = 2 / (Nx - 1)
# r5 N+ j& L8 ?; Edy = 2 / (Ny - 1)
. R7 Z. U2 x9 V1 k) ]/ L/ s+ |3 kA = sp.sparse.lil_matrix((Nx * Ny, Nx * Ny))3 U- h7 O2 O! T( `/ c2 z+ v
b = np.zeros(Nx * Ny)7 M) }  h& ^4 E" Z/ ^& A
q = lambda x, y: 2 * np.pi ** 2 * np.sin(np.pi * x) * np.sin(np.pi * y)
  g1 @, S4 {: D, Q$ i) o- b5 Lfor i in range(Ny):
" \: |. ?1 X% x$ Z4 m$ S0 V    for j in range(Nx):5 O% [* r: o0 s6 `4 y
        xp = j * 2 / (Nx - 1) - 1
( K* V/ w, U/ V        yp = i * 2 / (Ny - 1) - 1& ?: [9 ]' E# |' l
        if i == 0 or i == Ny - 1 or j == 0 or j == Ny - 1:5 T, @8 f' X* I' x- {
            A[i * Nx + j, i * Nx + j] = 1
5 u6 Y! ]0 x/ c" L. A/ A, s            b[i * Nx + j] = 0.
1 y! a! y9 g/ U$ N: ]' O5 V7 i            continue" M6 f' }7 `: h( f
        A[i * Nx + j, i * Nx + j] = 1 / dx + 1 / dy
! g- R$ G4 B9 g& i/ ?- h7 t- H5 l; L! U' l        A[i * Nx + j, i * Nx + j + 1] = -1 / 2 / dx! w6 s6 g" G7 C9 m4 z8 t  ~# \
        A[i * Nx + j, i * Nx + j - 1] = -1 / 2 / dx
& z+ C9 k7 M6 W% E        A[i * Nx + j, (i - 1) * Nx + j] = -1 / 2 / dy
; M" B0 }2 k6 }+ I+ Y( ]        A[i * Nx + j, (i + 1) * Nx + j] = -1 / 2 / dy$ {6 r% u+ Y7 T( t! Z& [
        b[i * Nx + j] = q(xp, yp)
- D; N7 m7 c: x# P( q: c9 z定义共轭梯度法:- R0 R% S5 f! J/ ~8 |
def cg(A, b, x0=None, tor=1e-10):
3 p; m% F2 q4 O* ]/ N/ G    N = len(b)
  [& q% B/ t: V. S' a8 _* D    if x0 is None:) u' W8 e* I8 _+ N
        x = np.random.randn(N)
, j8 i8 c, X( X! a& V    else:: J/ G2 x5 ?9 W/ @
        x = x0.copy()
2 }6 Z5 y* b2 o0 D. e: A    res = np.Inf
% r$ f) s3 ]: G8 ]: g, t    r = b - A @ x
2 E. q) X0 C6 g% ?" N3 X    d = r" I0 |5 ]( d5 C( H" Q" h
    r_inner_old = np.sum(r * r)
0 s  ?1 S) {% J1 `" e2 G    iteration = 0
8 Y' g0 `2 J* O4 `! g! f    while res > tor:
: x4 U8 v+ A+ r& {        Ad = A @ d4 h' f- B- J+ ~# n+ _1 @
        alpha = r_inner_old / np.sum(Ad * d)
! P8 E* _. q- e; h( n  \        x = x + alpha * d
, D  d: F$ m$ Y; @; ]7 T        if iteration % 50 != 0:! ?$ r& e/ }0 E: B
            r = r - alpha * Ad
$ ?; l5 \7 [3 c% Q5 V3 Q& Y5 h  @        else:7 D6 ]: h+ J* D0 E/ u$ d, J8 G* y
            r = b - A @ x
' G: H2 ]+ ], `& t$ E4 f) A( f6 ^        r_inner_new = np.sum(r * r)
$ ?/ s# R5 Q# n# A0 j( a        beta = r_inner_new / r_inner_old
8 }9 [* _% D$ n" D2 T- g: a- }# k        d = r + beta * d
9 q4 a; ^" _- R0 \/ I4 q        r_inner_old = r_inner_new" n. ~) w' n) G; T2 e; D
        res = np.linalg.norm(r_inner_new)
9 A5 i) d' ]8 @1 Z! k        print(iteration, res)
  z) z+ i1 o* r! Z" s5 q+ w5 T' Z; V        iteration += 1
, z! l+ J# m* a7 B- W4 Y    return x: o% W, G/ ]" W) v1 ~  N+ a( g
. R5 u8 @5 \0 h/ Z) s! ]
最后求解得到:
" l. Q: L0 Q( d5 R
* h1 F& a3 C- Q- q/ Y) Z 共轭梯度法的搜索方向加上负梯度方向是为了什么?-51.jpg
3 m9 Q( `3 a) e8 @" z! V0 \看起来没啥问题,然后是时间与规模的关系:
3 S1 A3 }7 a; Q. E, r
  M% a) C, U) V6 S2 V 共轭梯度法的搜索方向加上负梯度方向是为了什么?-52.jpg
( y7 u' k; w# r" o0 L时间的增长可能来源于矩阵向量乘法的耗时增加与迭代步数的增加,看起来会比迭代步数增长更快,如果追求更高的规模或精度,就需要引入一些预条件了,下次再说吧。
苏麒麟麟v | 2022-12-2 22:42:37 | 显示全部楼层
被邀请了,那就班门弄斧,抛砖引玉一下。(术语我知道中文是啥的,我会用中文,不知道怎么翻译的我就保留英文了)
5 x4 r  w! s" m- d) m: i# JReference: Conjugate Gradient Descent Notes (我基本就是照着这个来的,总结和翻译了一下)6 `2 M+ G4 g2 B2 D7 @) O  p
一句话总结:为什么要加上负梯度方向?因为CG的原理导致下降方向正好和负梯度方向有关,不是为了什么原因特地加入负梯度。
/ O2 \6 K# G0 X* e& p(详细解释)
5 g5 l3 b: m# J' |+ g& X共轭梯度法本来是为了求解线性系统 ,这等价于最小化 。当然这个方法也被拓展到用于优化一些别的东西。不过以下都假设我们要最小化
9 P  f) L6 J+ S& X下面介绍几个必要的概念:
, I9 e) Y8 w7 G3 p1) Krylov subspaces:0 F( q* u0 g! G+ Q1 B
一系列nested subspaces: .显然
+ s9 Y" A7 t( O* V8 ~Fact 1:
2 H& N& q9 g  w: G# f/ [Proof: From Cayley-Hamiltion theorem. (Refer to the reference page 3)
6 i4 ], B! j  q$ p+ m
; j$ Y# K2 F" P0 }可以看出来线性系统的最优解就在 里,那么如何找到它? 6 O) h8 n* J( H- H4 D2 |
2)Krylov sequences:
) C7 k+ L1 u% @( _& S6 R' w1 k定义 ,我们将 称为Krylov sequences。显然 。这说明了如果我们只要有这么 个Krylov sequences,我们就能找到 的最优解。本质上共轭梯度法就是生成这些Krylov sequences,当你生成到 时就结束了。0 ]+ o4 T, q" ^1 }
! Z# i, }) K' O2 b) P: ^& W) k
Krylov sequences 好棒啊,那么怎么找到它们?又要介绍一通概念了。
$ M1 L- E8 j6 A* c1 N3)Optimal condition on :
2 M  U7 N" W; u2 _ 有两个要求:
) X: r2 x: h3 Z* D  |4) Residual
7 J! Y* C. _4 ^# k我们接下来定义residual   , 可以观察到 。同时我们也看出来 这里出现负梯度啦!!!
; s! h% p8 H2 ~) v. i根据residual的性质,我们得到 and 9 x. U9 p( e0 Y9 B( b! x6 n+ z
5)Conjugate direction
. d" @5 p. ~" P( S: h6 t定义: ,有如下性质: . 证明在reference第七页。
/ R" a$ d* |5 K( S8 g7 j& F% f我们就得到Krylov的一个'conjugate' basis: $ d, w* H* A# R' M$ ^% z/ X
可以看出来,Krylov sequence的 之间变化的方向和负梯度有关。这就是为什么看CG算法里会有加入了负梯度的感觉。但是其实这个思路是反过来的,不是为了什么特意加入负梯度,而是在Krylov sequence求解的时候自然而然的出现了负梯度。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

200

金钱

0

收听

0

听众
性别

新手上路

金钱
200 元