对二次型函数
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对称正定。
f
(
x
)
f(\boldsymbol{x})
f(x)的梯度
g
(
x
)
=
∇
f
(
x
)
=
H
x
−
b
\boldsymbol{g}(\boldsymbol{x})=\nabla f(\boldsymbol{x})=\boldsymbol{Hx}-\boldsymbol{b}
g(x)=∇f(x)=Hx−b,Hesse阵
∇
2
f
(
x
)
=
H
\nabla^2f(\boldsymbol{x})=\boldsymbol{H}
∇2f(x)=H。取定初始点
x
1
\boldsymbol{x}_1
x1,牛顿法的迭代式为
x
k
+
1
=
x
k
−
H
−
1
g
k
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k-\boldsymbol{H}^{-1}\boldsymbol{g}_k
xk+1=xk−H−1gk,其中
g
k
=
g
(
x
k
)
\boldsymbol{g}_k=\boldsymbol{g}(\boldsymbol{x}_k)
gk=g(xk)。由
g
k
=
H
x
k
−
b
\boldsymbol{g}_k=\boldsymbol{Hx}_k-\boldsymbol{b}
gk=Hxk−b,有
g
k
+
1
−
g
k
=
H
x
k
+
1
−
H
x
k
=
H
(
x
k
+
1
−
x
k
)
\boldsymbol{g}_{k+1}-\boldsymbol{g}_k=\boldsymbol{Hx}_{k+1}-\boldsymbol{Hx}_k=\boldsymbol{H}(\boldsymbol{x}_{k+1}-\boldsymbol{x}_k)
gk+1−gk=Hxk+1−Hxk=H(xk+1−xk)
或
H
−
1
(
g
k
+
1
−
g
k
)
=
x
k
+
1
−
x
k
.
\boldsymbol{H}^{-1}(\boldsymbol{g}_{k+1}-\boldsymbol{g}_k)=\boldsymbol{x}_{k+1}-\boldsymbol{x}_k.
H−1(gk+1−gk)=xk+1−xk.
若记
{
Δ
x
k
=
x
k
+
1
−
x
k
Δ
g
k
=
g
k
+
1
−
g
k
\begin{cases} \Delta\boldsymbol{x}_k=\boldsymbol{x}_{k+1}-\boldsymbol{x}_k\\ \Delta\boldsymbol{g}_k=\boldsymbol{g}_{k+1}-\boldsymbol{g}_k \end{cases}
{Δxk=xk+1−xkΔgk=gk+1−gk
则称
Δ
g
k
=
H
Δ
x
\Delta\boldsymbol{g}_k=\boldsymbol{H}\Delta\boldsymbol{x}
Δgk=HΔx
或
H
−
1
Δ
g
k
=
Δ
x
k
\boldsymbol{H}^{-1}\Delta\boldsymbol{g}_k=\Delta\boldsymbol{x}_k
H−1Δgk=Δxk
为牛顿方程。
牛顿法能正确工作的一个重要前提是初始点
x
1
\boldsymbol{x}_1
x1需与最优解点
x
0
\boldsymbol{x}_0
x0充分接近。因为这时迭代式
x
k
+
1
=
x
k
−
H
k
−
1
g
k
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k-\boldsymbol{H}_k^{-1}\boldsymbol{g}_k
xk+1=xk−Hk−1gk可能使得
f
(
x
k
+
1
)
f(\boldsymbol{x}_{k+1})
f(xk+1)未必小于
f
(
x
k
)
f(\boldsymbol{x}_k)
f(xk),
k
=
1
,
2
,
⋯
k=1,2,\cdots
k=1,2,⋯。这可以通过选取合理的步长
α
k
\alpha_k
αk加以改善,即把迭代式改为
x
k
+
1
=
x
k
−
α
k
H
k
−
1
g
k
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k-\alpha_k\boldsymbol{H}_k^{-1}\boldsymbol{g}_k
xk+1=xk−αkHk−1gk
其中
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)。选取合适的
α
k
\alpha_k
αk,譬如,
α
k
\alpha_k
αk为
ϕ
k
(
α
)
=
f
(
x
k
−
α
H
k
−
1
g
k
)
\phi_k(\alpha)=f(\boldsymbol{x}_k-\alpha\boldsymbol{H}_k^{-1}\boldsymbol{g}_k)
ϕk(α)=f(xk−αHk−1gk)的最小值点,使得
f
(
x
k
+
1
)
<
f
(
x
k
)
f(\boldsymbol{x}_{k+1})<f(\boldsymbol{x}_k)
f(xk+1)<f(xk),
k
=
1
,
2
,
⋯
k=1,2,\cdots
k=1,2,⋯。另一方面,有如下事实
定理1 设函数
f
(
x
)
,
x
∈
R
n
f(\boldsymbol{x}),\boldsymbol{x}\in\text{ℝ}^n
f(x),x∈Rn一阶连续可微,
Q
∈
R
n
×
n
\boldsymbol{Q}\in\text{ℝ}^{n\times n}
Q∈Rn×n,
Q
⊤
=
Q
\boldsymbol{Q}^\top=\boldsymbol{Q}
Q⊤=Q且正定。对
x
k
∈
R
n
\boldsymbol{x}_k\in\text{ℝ}^n
xk∈Rn,若
g
k
=
∇
f
(
x
k
)
≠
o
\boldsymbol{g}_k=\nabla f(\boldsymbol{x}_k)\not=\boldsymbol{o}
gk=∇f(xk)=o,记
α
k
=
arg
min
α
>
0
f
(
x
k
−
α
Q
g
k
)
\alpha_k=\arg\min\limits_{\alpha>0}f(\boldsymbol{x}_k-\alpha\boldsymbol{Q}\boldsymbol{g}_k)
αk=argα>0minf(xk−αQgk),
x
k
+
1
=
x
k
−
α
k
Q
g
k
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k-\alpha_k\boldsymbol{Q}\boldsymbol{g}_k
xk+1=xk−αkQgk。则
f
(
x
k
+
1
)
<
f
(
x
k
)
.
f(\boldsymbol{x}_{k+1})<f(\boldsymbol{x}_k).
f(xk+1)<f(xk).
对于非二次型函数
f
(
x
)
f(\boldsymbol{x})
f(x)而言,其Hesse矩阵
H
=
∇
2
f
(
x
)
\boldsymbol{H}=\nabla^2f(\boldsymbol{x})
H=∇2f(x),将依赖于
x
\boldsymbol{x}
x。当
n
n
n很大时,在牛顿算法的迭代计算中更新
H
k
=
∇
2
f
(
x
k
)
\boldsymbol{H}_k=\nabla^2f(\boldsymbol{x}_k)
Hk=∇2f(xk)会消耗大量资源。我们的目标是对迭代点
x
k
\boldsymbol{x}_k
xk寻求
H
k
\boldsymbol{H}_k
Hk的一个近似对称正定矩阵
Q
k
\boldsymbol{Q}_k
Qk,使得在迭代中更新
Q
k
\boldsymbol{Q}_{k}
Qk比更新
H
k
\boldsymbol{H}_{k}
Hk更高效,且矩阵
Q
k
\boldsymbol{Q}_{k}
Qk应满足牛顿方程
Q
k
−
1
Δ
g
k
−
1
≈
Δ
x
k
−
1
\boldsymbol{Q}_{k}^{-1}\Delta\boldsymbol{g}_{k-1}\approx\Delta\boldsymbol{x}_{k-1}
Qk−1Δgk−1≈Δxk−1或
g
k
−
1
≈
Q
k
Δ
x
k
−
1
\boldsymbol{g}_{k-1}\approx\boldsymbol{Q}_{k}\Delta\boldsymbol{x}_{k-1}
gk−1≈QkΔxk−1。其中,
Δ
x
k
−
1
=
x
k
−
x
k
−
1
\Delta\boldsymbol{x}_{k-1}=\boldsymbol{x}_{k}-\boldsymbol{x}_{k-1}
Δxk−1=xk−xk−1,
Δ
g
k
−
1
=
g
k
−
g
k
−
1
\Delta\boldsymbol{g}_{k-1}=\boldsymbol{g}_{k}-\boldsymbol{g}_{k-1}
Δgk−1=gk−gk−1。这样改造牛顿法所得算法称为拟牛顿法。
实现拟牛顿法最简单的是秩1法。
定理2 设目标函数
f
(
x
)
f(\boldsymbol{x})
f(x),
x
∈
∈
R
n
\boldsymbol{x}\in\in\text{ℝ}^n
x∈∈Rn有最小值点
x
0
\boldsymbol{x}_0
x0且一阶连续可微。
k
=
1
k=1
k=1时,令对称正定阵
Q
1
=
I
\boldsymbol{Q}_1=\boldsymbol{I}
Q1=I。对
k
>
1
k>1
k>1,令
Q
k
−
1
=
Q
k
−
1
−
1
+
E
k
−
1
\boldsymbol{Q}^{-1}_{k}=\boldsymbol{Q}^{-1}_{k-1}+\boldsymbol{E}_{k-1}
Qk−1=Qk−1−1+Ek−1,其中,
E
k
−
1
=
(
Δ
x
k
−
1
−
Q
k
−
1
−
1
Δ
g
k
−
1
)
(
Δ
x
k
−
1
−
Q
k
−
1
−
1
Δ
g
k
−
1
)
⊤
(
Δ
x
k
−
1
−
Q
k
−
1
−
1
Δ
g
k
−
1
)
⊤
Δ
g
k
−
1
\boldsymbol{E}_{k-1}=\frac{(\Delta\boldsymbol{x}_{k-1}-\boldsymbol{Q}^{-1}_{k-1}\Delta\boldsymbol{g}_{k-1})(\Delta\boldsymbol{x}_{k-1}-\boldsymbol{Q}^{-1}_{k-1}\Delta\boldsymbol{g}_{k-1})^\top}{(\Delta\boldsymbol{x}_{k-1}-\boldsymbol{Q}^{-1}_{k-1}\Delta\boldsymbol{g}_{k-1})^\top\Delta\boldsymbol{g}_{k-1}}
Ek−1=(Δxk−1−Qk−1−1Δgk−1)⊤Δgk−1(Δxk−1−Qk−1−1Δgk−1)(Δxk−1−Qk−1−1Δgk−1)⊤
则迭代式
Q
k
−
1
=
Q
k
−
1
−
1
+
E
k
−
1
\boldsymbol{Q}^{-1}_k=\boldsymbol{Q}^{-1}_{k-1}+\boldsymbol{E}_{k-1}
Qk−1=Qk−1−1+Ek−1
满足牛顿方程
Q
k
−
1
Δ
g
k
−
1
≈
Δ
x
k
−
1
\boldsymbol{Q}_{k}^{-1}\Delta\boldsymbol{g}_{k-1}\approx\Delta\boldsymbol{x}_{k-1}
Qk−1Δgk−1≈Δxk−1。
利用定理1和定理2。得到秩1法搜索点序列的迭代式
x
k
+
1
=
x
k
−
α
k
Q
k
−
1
g
k
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k-\alpha_k\boldsymbol{Q}_k^{-1}\boldsymbol{g}_k
xk+1=xk−αkQk−1gk
其中,
α
k
=
arg
min
α
>
0
f
(
x
k
−
α
Q
g
k
)
\alpha_k=\arg\min\limits_{\alpha>0}f(\boldsymbol{x}_k-\alpha\boldsymbol{Q}\boldsymbol{g}_k)
αk=argα>0minf(xk−αQgk)。下列Python函数实现秩1算法。
import numpy as np
from scipy.optimize import minimize_scalar,OptimizeResult
def rank1(f, x1, gtol, **options):
n=x1.size
xk=x1
gk=grad(f,xk)
Qk=np.eye(n)
dk=-np.matmul(Qk,gk)
phi=lambda a: f(xk+a*dk)
k=1
while np.linalg.norm(gk)>gtol:
ak=minimize_scalar(phi).x
dx=ak*dk
xk=xk+dx
dg=grad(f,xk)-gk
vk=dx-np.matmul(Qk,dg)
Ek=np.matmul(vk.reshape(n,1),vk.reshape(1,n))/np.dot(vk,dg)
Qk+=Ek
gk+=dg
dk=-np.matmul(Qk,gk)
k+=1
bestx=xk
besty=f(bestx)
return OptimizeResult(fun=besty, x=bestx, nit=k)
程序中第3~24行定义的rank1函数实现对称秩1算法。参数f表示目标函数
f
(
x
)
f(\boldsymbol{x})
f(x),x1表示初始点
x
1
\boldsymbol{x}_1
x1,eps表示容错误差
ε
\varepsilon
ε,options实现minimize与本函数的信息交换机制。
第4~10行执行初始化操作:第4行读取自变量维数n。第5行将表示迭代点的xk初始化为x1。第6行调用计算梯度的函数grad(见博文《最优化方法Python计算:n元函数梯度与Hesse阵的数值计算》)计算目标函数的梯度
g
k
=
∇
f
(
x
k
)
\boldsymbol{g}_k=\nabla f(\boldsymbol{x}_k)
gk=∇f(xk)
赋予变量gk。第7行调用numpy的eye函数将正定阵
Q
k
−
1
\boldsymbol{Q}_k^{-1}
Qk−1初始化为单位阵
I
n
\boldsymbol{I}_n
In赋予Qk。第8行调用numpy的matmul函数计算
d
k
=
−
Q
k
−
1
g
k
\boldsymbol{d}_k=-\boldsymbol{Q}_k^{-1}\boldsymbol{g}_k
dk=−Qk−1gk
赋予表示搜索刚想的变量dk。第9行用{\bf{lambda}}运算符定义一元函数
ϕ
(
α
)
=
f
(
x
k
+
α
d
k
)
\phi(\alpha)=f(\boldsymbol{x}_k+\alpha\boldsymbol{d}_k)
ϕ(α)=f(xk+αdk)
为phi。
第11~21行执行迭代的while循环中,第12行调用scipy.optimize的minimize_scalar函数(第2行导入),计算
α
k
=
arg
min
α
>
0
ϕ
(
α
)
\alpha_k=\arg\min\limits_{\alpha>0}\phi(\alpha)
αk=argα>0minϕ(α)
赋予ak。第13行计算
Δ
x
=
x
k
+
1
−
x
k
=
x
k
+
α
k
d
k
−
x
k
=
α
k
d
k
\Delta\boldsymbol{x}=\boldsymbol{x}_{k+1}-\boldsymbol{x}_k=\boldsymbol{x}_k+\alpha_k\boldsymbol{d}_k-\boldsymbol{x}_k=\alpha_k\boldsymbol{d}_k
Δx=xk+1−xk=xk+αkdk−xk=αkdk
赋予dx。第14行计算
x
k
+
1
=
x
k
+
α
d
k
=
x
k
+
Δ
x
k
\boldsymbol{x}_{k+1}=\boldsymbol{x}_k+\alpha\boldsymbol{d}_k=\boldsymbol{x}_k+\Delta\boldsymbol{x}_k
xk+1=xk+αdk=xk+Δxk
更新迭代点xk。第15行计算
Δ
g
k
=
g
k
+
1
−
g
k
\Delta\boldsymbol{g}_k=\boldsymbol{g}_{k+1}-\boldsymbol{g}_k
Δgk=gk+1−gk
dg。第16行调用numpy的matmul函数计算向量
v
k
=
Δ
x
k
−
Q
k
Δ
g
k
\boldsymbol{v}_k=\Delta\boldsymbol{x}_k-\boldsymbol{Q}_k\Delta\boldsymbol{g}_k
vk=Δxk−QkΔgk
赋予vk。第17行计算矩阵
E
k
=
v
k
⊤
v
k
v
k
Δ
g
⊤
\boldsymbol{E}_k=\frac{\boldsymbol{v}_k^\top\boldsymbol{v}_k}{\boldsymbol{v}_k\Delta\boldsymbol{g}^\top}
Ek=vkΔg⊤vk⊤vk
赋予Ek。第18行计算
Q
k
+
1
−
1
=
Q
k
−
1
+
E
k
\boldsymbol{Q}_{k+1}^{-1}=\boldsymbol{Q}_{k}^{-1}+\boldsymbol{E}_k
Qk+1−1=Qk−1+Ek
更新Qk。第19行计算
g
k
+
1
=
Δ
g
k
−
g
k
\boldsymbol{g}_{k+1}=\Delta\boldsymbol{g}_k-\boldsymbol{g}_k
gk+1=Δgk−gk
更新gk。第20行计算
Q
k
+
1
−
1
g
k
+
1
\boldsymbol{Q}_{k+1}^{-1}\boldsymbol{g}_{k+1}
Qk+1−1gk+1
更新dk。\par
第22~24用
f
(
x
k
)
f(\boldsymbol{x}_k)
f(xk),
x
k
\boldsymbol{x}_k
xk以及
k
k
k构造OptimizeResult(第2行导入)对象并返回。以下例子说明函数rank1的应用。
例1 设初始点
x
1
=
(
100
100
)
\boldsymbol{x}_1=\begin{pmatrix}100\\100\end{pmatrix}
x1=(100100),用rank1函数计算Rosenbrock函数的最优解,给定容错误差
ε
=
1
0
−
8
\varepsilon=10^{-8}
ε=10−8。
解:下列代码完成本例计算。
import numpy as np #导入numpy
from scipy.optimize import rosen, minimize #导入rosen, minimize
x=np.array([100,100]) #设置初始点
res=minimize(rosen,x,method=rank1,options={'gtol':1e-8})#计算最优解
print(res)
第3行设置初始点 x 1 = ( 100 100 ) \boldsymbol{x}_1=\begin{pmatrix}100\\100\end{pmatrix} x1=(100100)。第4行调用scipy.optimize的minimize函数(第2行导入),传递rank1给参数method,计算rosen(第2行导入)表示的Rosenbrock函数的最优解。运行程序,输出
fun: 4.889083789243004e-26
nit: 49
x: array([1., 1.])
即以
x
1
=
(
100
100
)
\boldsymbol{x}_1=\begin{pmatrix}100\\100\end{pmatrix}
x1=(100100)为初始点,
ε
=
1
0
−
8
\varepsilon=10^{-8}
ε=10−8为容错误差,实现对称秩1算法的rank1函数迭代49次,算得Rosenbrock函数的最优解
x
0
=
(
1
1
)
\boldsymbol{x}_0=\begin{pmatrix}1\\1\end{pmatrix}
x0=(11)。需提请注意的是,对牛顿法而言,以
x
1
=
(
100
100
)
\boldsymbol{x}_1=\begin{pmatrix}100\\100\end{pmatrix}
x1=(100100)为初始点是得不到最优解
x
0
\boldsymbol{x}_0
x0的,读者可自行验证。
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!