最优化方法Python计算:信赖域算法

作为求解目标函数 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=argdΔkmin(21dHkd+gkd)
其中, 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)=21dHkd+gkds.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=piHkpiripi为第 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=ririri+1ri+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 piHkpi0,即 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 piHkpi>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 piHkpi>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} 106。\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 piHkpi0
真假决定是否调截断迭代:若该条件为真,则第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=piHkpiripi
赋予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=piHkpiri+1Hkpi
赋予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=argdΔ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)=21dkHkdkgkdk
由二次型函数在一区域内最小值点的唯一性知 Δ 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<μ21。当 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} 106,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=argdΔkminqk(d)=argdΔkmin(21dHkd+gkd)
赋予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>μ2dk=Δ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} ε=106,初始点 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} 106,表示信赖域半径 Δ ‾ \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} ε=106为容错误差,以 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} 106。运行程序,输出

     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函数计算),使得调用形式更加简洁。
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

以下是使用Python实现的光滑牛顿法求解信赖子问题的代码: ```python import numpy as np from numpy.linalg import norm from scipy.optimize import minimize_scalar def smooth_newton(trust_radius, x0, f, g, h): x = x0 while True: # Compute the gradient and Hessian at the current point grad = g(x) H = h(x) # Solve the trust region subproblem p = compute_step(grad, H, trust_radius) x_new = x + p # Compute the actual reduction and predicted reduction actual_reduction = f(x) - f(x_new) predicted_reduction = -grad.dot(p) - 0.5 * p.dot(H.dot(p)) # Compute the ratio of actual reduction to predicted reduction rho = actual_reduction / predicted_reduction # Update the trust region radius if rho < 0.25: trust_radius /= 2 elif rho > 0.75 and norm(p) == trust_radius: trust_radius = min(2*trust_radius, 1e8) # Update the iterate if rho > 0: x = x_new # Check for convergence if norm(grad) < 1e-6: break return x def compute_step(grad, H, trust_radius): # Solve the trust region subproblem using the dogleg method p_u = -np.linalg.solve(H, grad) if norm(p_u) <= trust_radius: return p_u else: p_b = -grad.dot(grad) / grad.dot(H.dot(grad)) * grad if norm(p_b) >= trust_radius: return trust_radius / norm(grad) * grad else: a = norm(p_u - p_b)**2 b = 2 * p_b.dot(p_u - p_b) c = norm(p_b)**2 - trust_radius**2 tau = (-b + np.sqrt(b**2 - 4*a*c)) / (2*a) return p_b + tau * (p_u - p_b) # Example usage def f(x): return x[0]**2 + x[1]**2 def g(x): return np.array([2*x[0], 2*x[1]]) def h(x): return np.array([[2, 0], [0, 2]]) x0 = np.array([1, 1]) trust_radius = 1.0 x = smooth_newton(trust_radius, x0, f, g, h) print("Optimal solution:", x) ``` 在上面的代码中,`smooth_newton`函数实现了光滑牛顿法的迭代过程,包括求解信赖子问题、更新信赖半径、更新迭代点等步骤。`compute_step`函数实现了用狗腿方法求解信赖子问题的过程。在示例中,我们使用了一个简单的二次函数作为目标函数,以演示光滑牛顿法的使用方法
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值