用基本共轭方向法(详见博文《最优化方法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)=21x⊤Hx−x⊤b,
x
∈
R
n
\boldsymbol{x}\in\text{ℝ}^n
x∈Rn的最优解点
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)=21x⊤Hx−x⊤b,x∈Rn
其中,
H
∈
R
n
×
n
\boldsymbol{H}\in\text{ℝ}^{n\times n}
H∈Rn×n为正定矩阵。任取
x
1
∈
R
n
\boldsymbol{x}_1\in\text{ℝ}^n
x1∈Rn,记
∇
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=−d1⊤Hd1g1⊤d1。对
1
≤
k
≤
n
1\leq k\leq n
1≤k≤n,
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=−dk⊤Hdkgk⊤dk,
β
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=dk⊤Hdkgk+1⊤Hdk,
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
1≤m≤n+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)=21x⊤Hx−x⊤b最优解的基本共轭算法加以修改,由于正定矩阵
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}
10−5。
第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)=Hx1−b
赋予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=dkHdk−gk⊤dk
赋予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+1−b
更新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=dk⊤Hdkgk+1⊤Hdk
赋予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)=21xk⊤Hxk−b⊤xk+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+x22−3x1x2−x2−7的最优解点
x
0
∈
R
2
\boldsymbol{x}_0\in\text{ℝ}^2
x0∈R2,给定初始点
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)=21x⊤Hx−x⊤b+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=(5−3−32),
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}
ε=10−5的容错误差下,共轭梯度算法迭代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+x22−3x1x2−x2−7的最优解
x
0
=
(
3
5
)
\boldsymbol{x}_0=\begin{pmatrix}3\\5\end{pmatrix}
x0=(35)。
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!