最优化方法Python计算:正定二次型共轭梯度算法

用基本共轭方向法(详见博文《最优化方法Python计算:基本共轭方向算法》)计算正定二次型目标函数 f ( x ) = 1 2 x ⊤ H x − x ⊤ b f(\boldsymbol{x})=\frac{1}{2}\boldsymbol{x}^\top\boldsymbol{Hx}-\boldsymbol{x}^\top\boldsymbol{b} f(x)=21xHxxb x ∈ R n \boldsymbol{x}\in\text{ℝ}^n xRn的最优解点 x 0 \boldsymbol{x}_0 x0,效率是很高的:至多迭代 n n n次,并且初始点的选取是任意的。然而,共轭方向法需要事先计算正定阵 H \boldsymbol{H} H的共轭向量组 d 1 , d 2 , ⋯   , d n \boldsymbol{d}_1,\boldsymbol{d}_2,\cdots,\boldsymbol{d}_n d1,d2,,dn。本文探讨一个在搜索过程中动态生成共轭向量 d 1 , d 2 , ⋯   , d k \boldsymbol{d}_1,\boldsymbol{d}_2,\cdots,\boldsymbol{d}_k d1,d2,,dk k = 1 , 2 , ⋯ k=1,2,\cdots k=1,2,的搜索方法。
定理1 二次型目标函数
f ( x ) = 1 2 x ⊤ H x − x ⊤ b , x ∈ R n f(\boldsymbol{x})=\frac{1}{2}\boldsymbol{x}^\top\boldsymbol{Hx}-\boldsymbol{x}^\top\boldsymbol{b},\boldsymbol{x}\in\text{ℝ}^n f(x)=21xHxxb,xRn
其中, H ∈ R n × n \boldsymbol{H}\in\text{ℝ}^{n\times n} HRn×n为正定矩阵。任取 x 1 ∈ R n \boldsymbol{x}_1\in\text{ℝ}^n x1Rn,记 ∇ f ( x 1 ) = g 1 \nabla f(\boldsymbol{x}_1)=\boldsymbol{g}_1 f(x1)=g1,若 g 1 ≠ o \boldsymbol{g}_1\not=\boldsymbol{o} g1=o,设 d 1 = − g 1 , α 1 = − g 1 ⊤ d 1 d 1 ⊤ H d 1 \boldsymbol{d}_1=-\boldsymbol{g}_1,\alpha_1=-\frac{\boldsymbol{g}_1^\top\boldsymbol{d}_1}{\boldsymbol{d}_1^\top\boldsymbol{Hd}_1} d1=g1,α1=d1Hd1g1d1。对 1 ≤ k ≤ n 1\leq k\leq n 1kn x k + 1 = x k + α k d k \boldsymbol{x}_{k+1}=\boldsymbol{x}_k+\alpha_k\boldsymbol{d}_k xk+1=xk+αkdk。假定对每个 k k k g k + 1 = ∇ f ( x k ) ≠ o \boldsymbol{g}_{k+1}=\nabla f(\boldsymbol{x}_k)\not=\boldsymbol{o} gk+1=f(xk)=o α k = − g k ⊤ d k d k ⊤ H d k \alpha_k=-\frac{\boldsymbol{g}_k^\top\boldsymbol{d}_k}{\boldsymbol{d}_k^\top\boldsymbol{Hd}_k} αk=dkHdkgkdk β k = g k + 1 ⊤ H d k d k ⊤ H d k \beta_k=\frac{\boldsymbol{g}_{k+1}^\top\boldsymbol{Hd}_{k}}{\boldsymbol{d}_k^\top\boldsymbol{Hd}_k} βk=dkHdkgk+1Hdk d k + 1 = − g k + β k d k \boldsymbol{d}_{k+1}=-\boldsymbol{g}_k+\beta_k\boldsymbol{d}_k dk+1=gk+βkdk,则 d 1 , d 2 , ⋯   , d k + 1 \boldsymbol{d}_1,\boldsymbol{d}_2,\cdots,\boldsymbol{d}_{k+1} d1,d2,,dk+1关于 H \boldsymbol{H} H共轭,且则存在 1 ≤ m ≤ n + 1 1\leq m\leq n+1 1mn+1,使得 x m = x 0 \boldsymbol{x}_{m}=\boldsymbol{x}_0 xm=x0。其中 x 0 \boldsymbol{x}_0 x0 f ( x ) f(\boldsymbol{x}) f(x)的最优解点。
利用定理1,我们将解正定二次型函数 f ( x ) = 1 2 x ⊤ H x − x ⊤ b f(\boldsymbol{x})=\frac{1}{2}\boldsymbol{x}^\top\boldsymbol{Hx}-\boldsymbol{x}^\top\boldsymbol{b} f(x)=21xHxxb最优解的基本共轭算法加以修改,由于正定矩阵 H \boldsymbol{H} H每个共轭向量 d k + 1 = − g k + β k d k \boldsymbol{d}_{k+1}=-\boldsymbol{g}_k+\beta_k\boldsymbol{d}_k dk+1=gk+βkdk均由梯度 g k = ∇ f ( x k ) \boldsymbol{g}_{k}=\nabla f(\boldsymbol{x}_k) gk=f(xk)算得,故称为共轭梯度算法。以下的Python函数实现共轭梯度算法。

import numpy as np                                                      #导入numpy
from scipy.optimize import OptimizeResult                               #导入OptimizeResult
def conjG(x1,H,b,c,gtol=1e-5):                                          #实现共轭梯度算法的函数
    xk=x1                                                               #设置初始迭代点
    gk=(np.matmul(H,xk)-b)                                              #计算当前梯度
    dk=-gk                                                              #搜索方向
    k=1
    while np.linalg.norm(gk)>=gtol:                                     #只要梯度不为0
        ak=-np.matmul(gk,dk)/np.matmul(np.matmul(dk,H),dk)              #搜索步长
        xk+=ak*dk                                                       #更新迭代点
        gk=(np.matmul(H,xk)-b)                                          #计算当前梯度
        bk=np.matmul(np.matmul(gk,H),dk)/np.matmul(np.matmul(dk,H),dk)  #计算beta
        dk=-gk+bk*dk                                                    #计算搜索方向
        k+=1
    bestx=xk
    besty=(np.matmul(np.matmul(xk,H),xk)/2-np.matmul(b,xk))+c
    return OptimizeResult(fun=besty, x=bestx, nit=k)

程序的第3~17行定义的conjG函数实现共轭梯度算法,参数x1表示初始迭代点 x 1 \boldsymbol{x}_1 x1,H,b,c分别表示函数 f ( x ) f(\boldsymbol{x}) f(x)表达式中的矩阵 H \boldsymbol{H} H,向量 b \boldsymbol{b} b和常数 c c c,gtol表示容错误差 ε \varepsilon ε,缺省值为 1 0 − 5 10^{-5} 105
第4~7行进行初始化操作:第4行用x1初始化表示迭代点 x k \boldsymbol{x}_k xk的xk。第5行计算二次型函数 f ( x ) f(\boldsymbol{x}) f(x)的梯度
g 1 = ∇ f ( x 1 ) = H x 1 − b \boldsymbol{g}_1=\nabla f(\boldsymbol{x}_1)=\boldsymbol{Hx}_1-\boldsymbol{b} g1=f(x1)=Hx1b
赋予gk。第6行按定理1计算搜索方向
d 1 = − ∇ f ( x 1 ) = − g 1 \boldsymbol{d}_1=-\nabla f(\boldsymbol{x}_1)=-\boldsymbol{g}_1 d1=f(x1)=g1
赋予dk。第7行将迭代次数k初始化为1。\par
第8~14行的while循环执行迭代:第9行按定理1计算
α k = − g k ⊤ d k d k H d k \alpha_k=\frac{-\boldsymbol{g}_k^\top\boldsymbol{d}_k}{\boldsymbol{d}_k\boldsymbol{Hd}_k} αk=dkHdkgkdk
赋予ak。第10行计算迭代点
x k + 1 = x k + α k d k \boldsymbol{x}_{k+1}=\boldsymbol{x}_k+\alpha_k\boldsymbol{d}_k xk+1=xk+αkdk
更新xk。第11行计算
g k + 1 = H x k + 1 − b \boldsymbol{g}_{k+1}=\boldsymbol{Hx}_{k+1}-\boldsymbol{b} gk+1=Hxk+1b
更新gk。第12行按定理1计算组合系数
β k = g k + 1 ⊤ H d k d k ⊤ H d k \beta_k=\frac{\boldsymbol{g}_{k+1}^\top\boldsymbol{Hd}_k}{\boldsymbol{d}_k^\top\boldsymbol{Hd}_k} βk=dkHdkgk+1Hdk
赋予bk。第13行按定理1计算共额方向
d k + 1 = − g k + 1 + β k d k \boldsymbol{d}_{k+1}=-\boldsymbol{g}_{k+1}+\beta_k\boldsymbol{d}_k dk+1=gk+1+βkdk
更新dk。第14行将迭代次数自增1。循环往复,直至条件
∥ g k ∥ < ε \lVert\boldsymbol{g}_k\rVert<\varepsilon gk<ε
成立为止。
第15~17行用 f ( x k ) = 1 2 x k ⊤ H x k − b ⊤ x k + c f(\boldsymbol{x}_k)=\frac{1}{2}\boldsymbol{x}_k^\top\boldsymbol{Hx}_k-\boldsymbol{b}^\top\boldsymbol{x}_k+c f(xk)=21xkHxkbxk+c x k \boldsymbol{x}_k xk k k k构造OptimizeResult对象(第2行导入)并返回。
例1 利用共轭梯度法计算正定二次型函数 f ( x ) = 5 2 x 1 2 + x 2 2 − 3 x 1 x 2 − x 2 − 7 f(\boldsymbol{x})=\frac{5}{2}x_1^2+x_2^2-3x_1x_2-x_2-7 f(x)=25x12+x223x1x2x27的最优解点 x 0 ∈ R 2 \boldsymbol{x}_0\in\text{ℝ}^2 x0R2,给定初始点 x 1 = ( 0 0 ) \boldsymbol{x}_1=\begin{pmatrix}0\\0\end{pmatrix} x1=(00)
:目标函数的矩阵形式为
f ( x ) = 1 2 x ⊤ H x − x ⊤ b + c f(\boldsymbol{x})=\frac{1}{2}\boldsymbol{x}^\top\boldsymbol{Hx}-\boldsymbol{x}^\top\boldsymbol{b}+c f(x)=21xHxxb+c
其中, x = ( x 1 x 2 ) ∈ R 2 \boldsymbol{x}=\begin{pmatrix}x_1\\x_2\end{pmatrix}\in\text{ℝ}^2 x=(x1x2)R2 H = ( 5 − 3 − 3 2 ) \boldsymbol{H}=\begin{pmatrix}5&-3\\-3&2\end{pmatrix} H=(5332) b = ( 0 1 ) \boldsymbol{b}=\begin{pmatrix}0\\1\end{pmatrix} b=(01) c = 7 c=7 c=7。下列代码完成计算。

import numpy as np                          #导入numpy
H=np.array([[5, -3],                        #设置Hesse阵
            [-3, 2]],dtype='float')
b=np.array([0,1],dtype='float')             #设置向量
c=7                                         #设置常数
x=np.array([0,0],dtype='float')             #设置初始迭代点
print(conjG(x,H,b,c))                       #计算并输出最优解

利用代码内的注释信息容易理解本程序代码。运行程序,输出

 fun: 4.5
 nit: 3
   x: array([3., 5.])

这意味着在 ε = 1 0 − 5 \varepsilon=10^{-5} ε=105的容错误差下,共轭梯度算法迭代3次算得正定二次型函数 f ( x ) = 5 2 x 1 2 + x 2 2 − 3 x 1 x 2 − x 2 − 7 f(\boldsymbol{x})=\frac{5}{2}x_1^2+x_2^2-3x_1x_2-x_2-7 f(x)=25x12+x223x1x2x27的最优解 x 0 = ( 3 5 ) \boldsymbol{x}_0=\begin{pmatrix}3\\5\end{pmatrix} x0=(35)
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值