作为求解目标函数
f
(
x
)
f(\boldsymbol{x})
f(x)无约束优化问题的策略之一的信赖域方法,与前讨论的线性搜索策略略有不同。线性搜索策略是在当前点
x
k
\boldsymbol{x}_k
xk处先确定搜索方向
d
k
\boldsymbol{d}_k
dk,再确定在该方向上的搜索步长
α
k
\alpha_k
αk。以此计算下一步搜索点
x
k
+
1
=
x
k
+
α
k
d
k
.
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k+\alpha_k\boldsymbol{d}_k.
xk+1=xk+αkdk.
信赖域方法的基本思想是以当前点
x
k
\boldsymbol{x}_k
xk为心,以
Δ
k
\Delta_k
Δk为半径的称为信任域的闭球内,求解与
f
(
x
)
f(\boldsymbol{x})
f(x)相似的二次型函数称为信赖域子问题的最优点来确定搜索方向
d
k
\boldsymbol{d}_k
dk:
d
k
=
arg
min
∥
d
∥
≤
Δ
k
(
1
2
d
⊤
H
k
d
+
g
k
⊤
d
)
\boldsymbol{d}_k=\arg\min_{\lVert\boldsymbol{d}\rVert\leq\Delta_k}\left(\frac{1}{2}\boldsymbol{d}^\top\boldsymbol{H}_k\boldsymbol{d}+\boldsymbol{g}_k^\top\boldsymbol{d}\right)
dk=arg∥d∥≤Δkmin(21d⊤Hkd+gk⊤d)
其中,
g
k
=
∇
f
(
x
k
)
\boldsymbol{g}_k=\nabla f(\boldsymbol{x}_k)
gk=∇f(xk),
H
k
\boldsymbol{H}_k
Hk是
f
(
x
)
f(\boldsymbol{x})
f(x)在
x
k
\boldsymbol{x}_k
xk处的Hesse阵。若求得的
d
k
\boldsymbol{d}_k
dk能使
f
(
x
)
f(\boldsymbol{x})
f(x)明显下降,则以此确定下一步搜索点
x
k
+
1
=
x
k
+
d
k
.
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k+\boldsymbol{d}_k.
xk+1=xk+dk.
否则,调整(缩放)信赖域半径
Δ
k
\Delta_k
Δk,重新求解信赖域子问题。循环往复,直至
d
k
\boldsymbol{d}_k
dk能使
f
(
x
)
f(\boldsymbol{x})
f(x)充分下降。
1、信赖域子问题的解
对二阶连续可微的目标函数
f
(
x
)
f(\boldsymbol{x})
f(x),所谓信赖域子问题是指的求解
minimize
q
k
(
d
)
=
1
2
d
⊤
H
k
d
+
g
k
⊤
d
s.t.
∥
d
∥
≤
Δ
k
.
(
1
)
\begin{array}{c} \text{minimize}\quad q_k(\boldsymbol{d})=\frac{1}{2}\boldsymbol{d}^\top\boldsymbol{H}_k\boldsymbol{d}+\boldsymbol{g}_k^\top\boldsymbol{d} \\ \text{s.t.}\quad\lVert\boldsymbol{d}\rVert\leq\Delta_k. \end{array}\quad\quad(1)
minimizeqk(d)=21d⊤Hkd+gk⊤ds.t.∥d∥≤Δk.(1)
其中,
g
k
=
∇
f
(
x
k
)
\boldsymbol{g}_k=\nabla f(\boldsymbol{x}_k)
gk=∇f(xk),
H
k
=
∇
2
f
(
x
k
)
\boldsymbol{H}_k=\nabla^2f(\boldsymbol{x}_k)
Hk=∇2f(xk)。
这是一个二次型函数
q
k
(
d
)
q_k(\boldsymbol{d})
qk(d)的优化问题,我们试图运用上一章讨论过的共轭梯度法(详见博文《最优化方法Python计算:正定二次型共轭梯度算法》)来解决信赖域子问题。首先,注意到目标函数
q
k
(
d
)
q_k(\boldsymbol{d})
qk(d)的自变量为
d
\boldsymbol{d}
d,初始
d
1
=
o
\boldsymbol{d}_1=\boldsymbol{o}
d1=o。为避免发生符号混淆,记
r
i
=
∇
q
k
(
d
i
)
=
H
k
d
i
+
g
k
\boldsymbol{r}_i=\nabla q_k(\boldsymbol{d}_i)=\boldsymbol{H}_k\boldsymbol{d}_i+\boldsymbol{g}_k
ri=∇qk(di)=Hkdi+gk为
q
k
(
d
)
q_k(\boldsymbol{d})
qk(d)在第
i
i
i次迭代时的梯度,初始
r
1
=
g
k
=
∇
f
(
x
k
)
\boldsymbol{r}_1=\boldsymbol{g}_k=\nabla f(\boldsymbol{x}_k)
r1=gk=∇f(xk)。
p
i
\boldsymbol{p}_i
pi为第
i
i
i次迭代时的搜索方向,初始
p
1
=
−
r
1
\boldsymbol{p}_1=-\boldsymbol{r}_1
p1=−r1。
α
i
=
−
r
i
⊤
p
i
p
i
⊤
H
k
p
i
\alpha_i=\frac{-\boldsymbol{r}_{i}^\top\boldsymbol{p}_{i}}{\boldsymbol{p}_{i}^\top\boldsymbol{H}_k\boldsymbol{p}_{i}}
αi=pi⊤Hkpi−ri⊤pi为第
i
i
i次迭代时的搜索步长。
β
i
=
r
i
+
1
⊤
r
i
+
1
r
i
⊤
r
i
\beta_i=\frac{\boldsymbol{r}_{i+1}^\top\boldsymbol{r}_{i+1}}{\boldsymbol{r}_i^\top\boldsymbol{r}_i}
βi=ri⊤riri+1⊤ri+1为方向向量
p
i
+
1
=
−
r
i
+
1
+
β
i
p
i
\boldsymbol{p}_{i+1}=-\boldsymbol{r}_{i+1}+\beta_i\boldsymbol{p}_i
pi+1=−ri+1+βipi的线性组合系数。由此而得
d
i
+
1
=
d
i
+
α
i
p
i
\boldsymbol{d}_{i+1}=\boldsymbol{d}_i+\alpha_i\boldsymbol{p}_i
di+1=di+αipi
是
q
k
(
d
)
q_k(\boldsymbol{d})
qk(d)的无约束优化问题的第
i
+
1
i+1
i+1个迭代点,但加上约束条件
∥
d
∥
≤
Δ
k
\lVert\boldsymbol{d}\rVert\leq\Delta_k
∥d∥≤Δk后,可能需要作下列的“截断操作”:
(1)若
p
i
⊤
H
k
p
i
≤
0
\boldsymbol{p}_i^\top\boldsymbol{H}_k\boldsymbol{p}_i\leq0
pi⊤Hkpi≤0,即
H
k
\boldsymbol{H}_k
Hk不是正定阵,停止迭代。保持
p
i
\boldsymbol{p}_i
pi的方向,将其推至信赖域边界,即寻求
ρ
>
0
\rho>0
ρ>0,使得
∥
d
i
+
ρ
p
i
∥
=
Δ
k
\lVert\boldsymbol{d}_i+\rho\boldsymbol{p}_i\rVert=\Delta_k
∥di+ρpi∥=Δk, 返回
d
i
+
ρ
p
i
=
Δ
k
\boldsymbol{d}_i+\rho\boldsymbol{p}_i=\Delta_k
di+ρpi=Δk。
(2)
p
i
⊤
H
k
p
i
>
0
\boldsymbol{p}_i^\top\boldsymbol{H}_k\boldsymbol{p}_i>0
pi⊤Hkpi>0,但
∥
d
i
+
α
i
p
i
∥
>
Δ
k
\lVert\boldsymbol{d}_i+\alpha_i\boldsymbol{p}_i\rVert>\Delta_k
∥di+αipi∥>Δk,即
d
i
+
1
\boldsymbol{d}_{i+1}
di+1突破了约束条件
∥
d
∥
≤
Δ
k
\lVert\boldsymbol{d}\rVert\leq\Delta_k
∥d∥≤Δk,停止迭代。寻求
ρ
∈
(
0
,
1
)
\rho\in(0,1)
ρ∈(0,1),使得
∥
d
i
+
ρ
p
i
∥
=
Δ
k
\lVert\boldsymbol{d}_i+\rho\boldsymbol{p}_i\rVert=\Delta_k
∥di+ρpi∥=Δk,返回
d
i
+
ρ
p
i
=
Δ
k
\boldsymbol{d}_i+\rho\boldsymbol{p}_i=\Delta_k
di+ρpi=Δk。
(3)
p
i
⊤
H
k
p
i
>
0
\boldsymbol{p}_i^\top\boldsymbol{H}_k\boldsymbol{p}_i>0
pi⊤Hkpi>0,
∥
d
i
+
α
i
p
i
∥
≤
Δ
k
\lVert\boldsymbol{d}_i+\alpha_i\boldsymbol{p}_i\rVert\leq\Delta_k
∥di+αipi∥≤Δk,且
∥
r
i
+
1
∥
>
ε
\lVert\boldsymbol{r}_{i+1}\rVert>\varepsilon
∥ri+1∥>ε,令
d
i
+
1
=
d
i
+
α
i
p
i
\boldsymbol{d}_{i+1}=\boldsymbol{d}_i+\alpha_i\boldsymbol{p}_i
di+1=di+αipi,继续迭代。其中,
ε
\varepsilon
ε为给定的容错误差。
用上述为满足约束条件而进行迭代截断的思想改造共轭梯度算法(详见博文《最优化方法Python计算:正定二次型共轭梯度算法》)。由于这一方法是在对共轭梯度算法的迭代过程进行了有条件的“截断”,故称为截断共轭梯度算法。
下列代码实现截断共轭梯度算法。
import numpy as np
def tcg(H,g,D,eps=1e-6):
n=g.size
di=np.zeros(n)
ri=g
pi=-ri
i=1
while np.linalg.norm(ri)>eps:
if np.matmul(np.matmul(pi,H),pi)<=0:
rho=1
while np.linalg.norm(di+rho*pi)<D:
rho*=1.05
while np.linalg.norm(di+rho*pi)>D:
rho*=0.95
return di+rho*pi
ai=(-np.matmul(ri,pi)/np.matmul(np.matmul(pi,H),pi))
if np.linalg.norm(di+ai*pi)>D:
rho=ai*0.95
while np.linalg.norm(di+rho*pi)>D:
rho*=0.95
return di+rho*pi
di=di+ai*pi
ri=ri+ai*np.matmul(H,pi)
bi=np.matmul(np.matmul(ri,H),pi)/np.matmul(np.matmul(pi,H),pi)
pi=-ri+bi*pi
i+=1
return di
程序的第2~27行定义的函数tcg实现计算信赖域子问题的截断共轭梯度算法。参数H表示子问题目标函数中的矩阵
H
k
\boldsymbol{H}_k
Hk,g表示向量
g
k
\boldsymbol{g}_k
gk,D表示信赖域半径
Δ
k
\Delta_k
Δk,eps表示容错误差
ε
\varepsilon
ε,缺省值设置为
1
0
−
6
10^{-6}
10−6。\par
第3~7行做初始化操作。其中第3行读取g的维数赋予n,第4行调用numpy的zeros函数将最优解向量di初始化为n维零向量,第5行将表示目标函数的梯度
r
i
\boldsymbol{r}_i
ri的ri初始化为表示
g
k
\boldsymbol{g}_k
gk的g。第6行将表示搜索方向
p
i
\boldsymbol{p}_i
pi的pi初始化为
−
r
i
-\boldsymbol{r}_i
−ri。第7行将迭代次数i初始化为1。
第8~ 26行的while循环进行迭代操作。其中,第9~15行根据检测条件
∥
p
i
⊤
H
k
p
i
∥
≤
0
\lVert\boldsymbol{p}_i^\top\boldsymbol{H}_k\boldsymbol{p}_i\rVert\leq0
∥pi⊤Hkpi∥≤0
真假决定是否调截断迭代:若该条件为真,则第10~14行的两个并列while循环计算满足
∥
d
i
+
ρ
p
i
∥
=
Δ
k
\lVert\boldsymbol{d}_i+\rho\boldsymbol{p}_i\rVert=\Delta_k
∥di+ρpi∥=Δk
的实数
ρ
\rho
ρ,并在第15行返回最优解的近似值(截断)
d
i
+
ρ
p
i
.
\boldsymbol{d}_i+\rho\boldsymbol{p}_i.
di+ρpi.
否则,第16行计算
α
i
=
−
r
i
⊤
p
i
p
i
⊤
H
k
p
i
\alpha_i=-\frac{\boldsymbol{r}_i^\top\boldsymbol{p}_i}{\boldsymbol{p}_i^\top\boldsymbol{H}_k\boldsymbol{p}_i}
αi=−pi⊤Hkpiri⊤pi
赋予ai。第17~21行根据检测条件
∥
d
i
+
ρ
p
i
∥
>
Δ
k
\lVert\boldsymbol{d}_i+\rho\boldsymbol{p}_i\rVert>\Delta_k
∥di+ρpi∥>Δk
的真假决定是否截断迭代:若条件为真,第19~20行的while循环计算满足
∥
d
i
+
ρ
p
i
∥
=
Δ
k
\lVert\boldsymbol{d}_i+\rho\boldsymbol{p}_i\rVert=\Delta_k
∥di+ρpi∥=Δk
的实数
ρ
\rho
ρ,并在第21行返回最优解的近似值(截断)
d
i
+
ρ
p
i
.
\boldsymbol{d}_i+\rho\boldsymbol{p}_i.
di+ρpi.
否则完成本次迭代:第22行计算
d
i
+
1
=
d
i
+
α
i
p
i
\boldsymbol{d}_{i+1}=\boldsymbol{d}_i+\alpha_i\boldsymbol{p}_i
di+1=di+αipi
更新最优解迭代点di,第23行计算
r
i
+
1
=
r
i
+
α
i
H
k
p
i
\boldsymbol{r}_{i+1}=\boldsymbol{r}_i+\alpha_i\boldsymbol{H}_k\boldsymbol{p}_i
ri+1=ri+αiHkpi
更新ri。第24行计算系数
β
i
=
r
i
+
1
⊤
H
k
p
i
p
i
⊤
H
k
p
i
\beta_i=\frac{\boldsymbol{r}_{i+1}^\top\boldsymbol{H}_k\boldsymbol{p}_i}{\boldsymbol{p}_i\top\boldsymbol{H}_k\boldsymbol{p}_i}
βi=pi⊤Hkpiri+1⊤Hkpi
赋予bi。第25行计算
p
i
+
1
=
r
i
+
1
+
β
i
p
i
\boldsymbol{p}_{i+1}=\boldsymbol{r}_{i+1}+\beta_i\boldsymbol{p}_i
pi+1=ri+1+βipi
更新pi。第26行迭代次数i自增1。循环往复,直至被截断或检测到
∥
r
i
∥
≥
ε
.
\lVert\boldsymbol{r}_i\rVert\geq\varepsilon.
∥ri∥≥ε.
第27行返回最优解近似值di。
2、信赖域算法
在信赖域算法中,设第
k
k
k次迭代算得子问题最优解
d
k
=
arg
min
∥
d
∥
≤
Δ
k
q
k
(
d
)
≠
o
\boldsymbol{d}_k=\arg\min\limits_{\lVert\boldsymbol{d}\rVert\leq\Delta_k}q_k(\boldsymbol{d})\not=\boldsymbol{o}
dk=arg∥d∥≤Δkminqk(d)=o,记
Δ
f
k
=
f
(
x
k
)
−
f
(
x
k
+
d
k
)
\Delta f_k=f(\boldsymbol{x}_k)-f(\boldsymbol{x}_k+\boldsymbol{d}_k)
Δfk=f(xk)−f(xk+dk),
Δ
q
k
=
q
k
(
o
)
−
q
k
(
d
k
)
=
−
q
k
(
d
k
)
=
−
1
2
d
k
⊤
H
k
d
k
−
g
k
⊤
d
k
\Delta q_k=q_k(\boldsymbol{o})-q_k(\boldsymbol{d}_k)\\ \quad\quad\quad\quad\quad\quad\quad\quad\quad\quad=-q_k(\boldsymbol{d}_k)=-\frac{1}{2}\boldsymbol{d}_k^\top\boldsymbol{H}_k\boldsymbol{d}_k-\boldsymbol{g}_k^\top\boldsymbol{d}_k
Δqk=qk(o)−qk(dk)=−qk(dk)=−21dk⊤Hkdk−gk⊤dk
由二次型函数在一区域内最小值点的唯一性知
Δ
q
k
>
0
\Delta q_k>0
Δqk>0。考虑比值
r
k
=
Δ
f
k
Δ
q
k
r_k=\frac{\Delta f_k}{\Delta q_k}
rk=ΔqkΔfk
反映了
q
k
(
d
)
q_k(\boldsymbol{d})
qk(d)从
q
k
(
o
)
q_k(\boldsymbol{o})
qk(o)变化到
q
k
(
d
k
)
q_k(\boldsymbol{d}_k)
qk(dk)与
f
(
x
)
f(\boldsymbol{x})
f(x)从
f
(
x
k
)
f(\boldsymbol{x}_k)
f(xk)变化到
f
(
x
k
+
d
k
)
f(\boldsymbol{x}_k+\boldsymbol{d}_k)
f(xk+dk)的变化率。根据
r
k
r_k
rk的值,作如下判断和思考:
(1)若
r
k
<
0
r_k<0
rk<0,则意味着
d
k
\boldsymbol{d}_k
dk不是
f
(
x
)
f(\boldsymbol{x})
f(x)在
x
k
\boldsymbol{x}_k
xk处的下降方向。或
r
k
r_k
rk虽然大于零但其值很小,意味着
f
(
x
)
f(\boldsymbol{x})
f(x)从
x
k
\boldsymbol{x}_k
xk,沿
d
k
\boldsymbol{d}_k
dk到
x
k
+
d
k
\boldsymbol{x}_k+\boldsymbol{d}_k
xk+dk的下降幅度微不足道。因此,需缩小信赖半径
Δ
k
\Delta_k
Δk并重新计算
d
k
\boldsymbol{d}_k
dk。
(2)若
r
k
r_k
rk显著大于零,则意味着
q
k
(
d
)
q_k(\boldsymbol{d})
qk(d)在
x
k
\boldsymbol{x}_k
xk近旁比较接近
f
(
x
)
f(\boldsymbol{x})
f(x),
d
k
\boldsymbol{d}_k
dk作为
f
(
x
)
f(\boldsymbol{x})
f(x)在
x
k
\boldsymbol{x}_k
xk的下降方向是可信赖的,即
x
k
+
1
=
x
k
+
d
k
(
2
)
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k+\boldsymbol{d}_k\quad(2)
xk+1=xk+dk(2)
可作为下一个搜索点。
(3)
r
k
>
0
r_k>0
rk>0前提下,接近1,且
∥
d
k
∥
=
Δ
k
\lVert\boldsymbol{d}_k\rVert=\Delta_k
∥dk∥=Δk,则意味着还可以适当放大下一步迭代时的信赖半径
Δ
k
+
1
\Delta_{k+1}
Δk+1,以期提高搜索效率。
对于情形(2)和(3),进入下一轮迭代前,均需将
f
(
x
)
f(\boldsymbol{x})
f(x)的梯度及Hesse矩阵分别更新为
g
k
+
1
\boldsymbol{g}_{k+1}
gk+1及
H
k
+
1
\boldsymbol{H}_{k+1}
Hk+1。为界定
r
k
r_k
rk的“大小”,设置阀值
0
<
μ
1
<
μ
2
≤
1
0<\mu_1<\mu_2\leq1
0<μ1<μ2≤1。当
r
k
<
μ
1
r_k<\mu_1
rk<μ1时,认为
r
k
r_k
rk太小。当
r
k
≥
μ
2
r_k\geq\mu_2
rk≥μ2时,认为
r
k
r_k
rk接近于1。还可以设置信赖域半径
Δ
k
\Delta_k
Δk的缩放比例
0
<
τ
1
<
1
<
τ
2
0<\tau_1<1<\tau_2
0<τ1<1<τ2,用
τ
1
Δ
k
\tau_1\Delta_k
τ1Δk缩小半径,
τ
2
Δ
k
\tau_2\Delta_k
τ2Δk扩大半径。实践中,
μ
1
=
0.05
\mu_1=0.05
μ1=0.05,
μ
2
=
0.75
\mu_2=0.75
μ2=0.75,
τ
1
=
0.5
\tau_1=0.5
τ1=0.5,
τ
2
=
2
\tau_2=2
τ2=2,是这组参数的推荐值。信赖域半径初始值可取
Δ
‾
=
1
\overline{\Delta}=1
Δ=1。
下列代码实现信赖域算法。
import numpy as np
from scipy.optimize import OptimizeResult
def trust(f, x1, gtol=1e-6, D=1, **options):
mu1,mu2=0.05,0.75
t1,t2=0.25,2
xk=x1
fk,gk,Hk=f(xk),grad(f,xk),hess(f,xk)
Dk=D
k=1
while np.linalg.norm(gk)>gtol:
dk=tcg(Hk,gk,Dk)
df=fk-f(xk+dk)
dq=-(np.matmul(gk,dk)+np.matmul(np.matmul(dk,Hk),dk)/2)
rk=df/dq
if rk<mu1:
Dk=t1*Dk
else:
if rk>mu2 and abs(np.linalg.norm(dk)-Dk)<1e-6:
Dk=min(t2*Dk,D)
xk=xk+dk
fk,gk,Hk=f(xk),grad(f,xk),hess(f,xk)
k+=1
bestx=xk
besty=f(bestx)
return OptimizeResult(fun=besty, x=bestx, nit=k)
程序的第3~25行定义的函数trust实现信赖域算法,参数f表示目标函数
f
(
x
)
f(\boldsymbol{x})
f(x),x1表示初始点
x
1
\boldsymbol{x}_1
x1,命名参数eps表示容错误差
ε
\varepsilon
ε,缺省值为
1
0
−
6
10^{-6}
10−6,D表示信赖域半径
Δ
‾
\overline{\Delta}
Δ,缺省值为1。
第4~9行完成初始化操作:第4行设置阀值
μ
1
=
0.05
\mu_1=0.05
μ1=0.05赋予mu1,
μ
2
=
0.75
\mu_2=0.75
μ2=0.75赋予mu2。第5行设置信赖半径缩放系数
τ
1
=
0.25
\tau_1=0.25
τ1=0.25赋予t1,
τ
2
=
2
\tau_2=2
τ2=2赋予t2。第6行将表示迭代点
x
k
\boldsymbol{x}_k
xk的xk初始化为x1。第7行调用grad函数和hess函数(见博文《最优化方法Python计算:n元函数梯度与Hesse阵的数值计算》)用
f
(
x
1
)
f(\boldsymbol{x}_1)
f(x1)初始化fk,
∇
f
(
x
1
)
\nabla f(\boldsymbol{x}_1)
∇f(x1)初始化gk,
∇
2
f
(
x
1
)
\nabla^2f(\boldsymbol{x}_1)
∇2f(x1)初始化Hk。第8行用
Δ
‾
\overline{\Delta}
Δ初始化Dk。\par
第10~22行的while循环根据条件
∥
g
k
∥
>
ε
\lVert\boldsymbol{g}_k\rVert>\varepsilon
∥gk∥>ε执行迭代:第11行调用解子问题的tcg函数计算子问题最优解
d
k
=
arg
min
∥
d
∥
≤
Δ
k
q
k
(
d
)
=
arg
min
∥
d
∥
≤
Δ
k
(
1
2
d
⊤
H
k
d
+
g
k
⊤
d
)
\boldsymbol{d}_k=\arg\min\limits_{\lVert\boldsymbol{d}\rVert\leq\Delta_k}q_k(\boldsymbol{d})=\arg\min\limits_{\lVert\boldsymbol{d}\rVert\leq\Delta_k}(\frac{1}{2}\boldsymbol{d}^\top\boldsymbol{H}_k\boldsymbol{d}+\boldsymbol{g}_k^\top\boldsymbol{d})
dk=arg∥d∥≤Δkminqk(d)=arg∥d∥≤Δkmin(21d⊤Hkd+gk⊤d)
赋予dk。第12行计算
Δ
f
k
=
f
(
x
k
)
−
f
(
x
k
+
d
k
)
\Delta f_k=f(\boldsymbol{x}_k)-f(\boldsymbol{x}_k+\boldsymbol{d}_k)
Δfk=f(xk)−f(xk+dk)
赋予df。第13行计算
Δ
q
k
=
q
k
(
o
)
−
q
k
(
d
k
)
\Delta q_k=q_k(\boldsymbol{o})-q_k(\boldsymbol{d}_k)
Δqk=qk(o)−qk(dk)
赋予dq。第14行计算
r
k
=
Δ
f
k
Δ
q
k
r_k=\frac{\Delta f_k}{\Delta q_k}
rk=ΔqkΔfk
赋予rk。第15~22行的if-else分支根据条件
r
k
<
μ
1
r_k<\mu_1
rk<μ1决定是否重做本次迭代:若条件为真,第16行执行
Δ
k
=
τ
1
Δ
k
\Delta_k=\tau_1\Delta_k
Δk=τ1Δk
以缩小信赖域半径
Δ
k
\Delta_k
Δk。否则,第18~ 22行完成本次迭代:先用第18~19行的if语句根据条件
r
k
>
μ
2
且
∥
d
k
∥
=
Δ
k
r_k>\mu_2\text{且}\lVert\boldsymbol{d}_k\rVert=\Delta_k
rk>μ2且∥dk∥=Δk
决定是否执行
Δ
k
=
τ
2
Δ
k
\Delta_k=\tau_2\Delta_k
Δk=τ2Δk
以放大
Δ
k
\Delta_k
Δk。然后第20行继续进行迭代,用
x
k
+
1
=
x
k
+
d
k
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k+\boldsymbol{d}_k
xk+1=xk+dk
更新xk。第21行用新的xk(即
x
k
+
1
\boldsymbol{x}_{k+1}
xk+1)更新fk,gk,Hk为
f
k
+
1
f_{k+1}
fk+1,
g
k
+
1
\boldsymbol{g}_{k+1}
gk+1和
H
k
+
1
\boldsymbol{H}_{k+1}
Hk+1。\par
第23~25行用xk,f(xk)及k构造返回值返回。
例1 用trust函数计算Rosenbrock函数的最优解,给定信赖域半径
Δ
‾
=
3
\overline{\Delta}=3
Δ=3,容错误差
ε
=
1
0
−
6
\varepsilon=10^{-6}
ε=10−6,初始点
x
1
=
(
100
100
)
\boldsymbol{x}_1=\begin{pmatrix}100\\100\end{pmatrix}
x1=(100100)。
解:下列代码完成本例计算。
import numpy as np #导入numpy
from scipy.optimize import minimize,rosen #导入minimize,rosen
x1=np.array([100,100]) #设置初始点
res=minimize(rosen,x1,method=trust,options={'eps':1e-6,'D':3}) #计算最优解
print(res)
程序的第3行设置初始点 x 1 = ( 100 100 ) \boldsymbol{x}_1=\begin{pmatrix}100\\100\end{pmatrix} x1=(100100)。第4行调用minimize函数(第2行导入),传递rosen(第2行导入)给表示目标函数的参数,x1给表示初始点的参数,传递trust给表示算法的参数method,并设置表示容错误差 ε \varepsilon ε的eps为 1 0 − 6 10^{-6} 10−6,表示信赖域半径 Δ ‾ \overline{\Delta} Δ的D为3,计算Rosenbrock函数的最优解。运行程序,输出
fun: 8.970641906878568e-16
nit: 125
x: array([1.00000003, 1.00000005])
意味着trust从
x
1
=
(
100
100
)
\boldsymbol{x}_1=\begin{pmatrix}100\\100\end{pmatrix}
x1=(100100)开始,迭代125次,算得Rosenbrock函数的最优解
x
0
=
(
1
1
)
\boldsymbol{x}_0=\begin{pmatrix}1\\1\end{pmatrix}
x0=(11)的近似值。
应当指出,scipy.optimize为用户提供了包括trust-ncg、trust-krylov、trust-exact等若干个信赖域方法。使用这些方法时,需向minimize的参数jac传递目标函数的梯度,向参数hess传递目标函数的Hess阵。
例2 以
ε
=
1
0
−
6
\varepsilon=10^{-6}
ε=10−6为容错误差,以
x
1
=
(
100
100
)
\boldsymbol{x}_1=\begin{pmatrix}100\\100\end{pmatrix}
x1=(100100)为初始点,用trust-ncg方法计算Rosenbrock函数的最优解。\par
解:下列代码完成本例计算。
import numpy as np #导入numpy
from scipy.optimize import minimize,rosen,rosen_der, rosen_hess #导入minimize等
x1=np.array([100,100]) #设置初始点
res=minimize(rosen, x1, method='trust-ncg', #计算最优解
jac=rosen_der, hess=rosen_hess,options={'gtol': 1e-6})
print(res)
程序中的第4~5行调用minimize函数(第2行导入)计算Rosenbrock函数的最优解。传递给目标函数为rosen(第2行导入),传递给初始点向量为x1(第3行定义),传递给表示算法的参数method为’trust-ngc’,传递给表示目标函数梯度的参数jac为rosen_{}der(第2行导入),传递给表示目标函数Hess矩阵的参数hess为rosen_{}hess(第2行导入)传递给表示容错误差的参数gtol为 1 0 − 6 10^{-6} 10−6。运行程序,输出
fun: 2.25873063877735e-28
hess: array([[ 802., -400.],
[-400., 200.]])
jac: array([ 1.44328993e-14, -2.22044605e-14])
message: 'Optimization terminated successfully.'
nfev: 126
nhev: 108
nit: 125
njev: 109
status: 0
success: True
x: array([1., 1.])
比较例1和例2可见,系统提供的trust-ngc方法与我们编制的trust方法在计算效率上不分仲伯(相同的容错误差下均迭代125次)。然而用我们的trust时无需向minimize提供目标函数的梯度和和Hesse阵作为参数(trust内部调用der和hess函数计算),使得调用形式更加简洁。
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!