作为求解目标函数 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)充分下降。
对二阶连续可微的目标函数 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。
在信赖域算法中,设第 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函数计算),使得调用形式更加简洁。