自学内容网 自学内容网

数值优化 | 详解拟牛顿法之SR1、DFP、BFGS、L-BFGS(附案例分析与Python实现)

0 专栏介绍

🔥课设、毕设、创新竞赛必备!🔥本专栏涉及更高阶的运动规划算法轨迹优化实战,包括:曲线生成、碰撞检测、安全走廊、优化建模(QP、SQP、NMPC、iLQR等)、轨迹优化(梯度法、曲线法等),每个算法都包含代码实现加深理解

🚀详情:运动规划实战进阶:轨迹优化篇


1 拟牛顿法框架

数值优化 | 图解牛顿法、阻尼牛顿法与高斯牛顿法(附案例分析与Python实现)中我们介绍了经典牛顿法的迭代公式

x k + 1 = x k − H − 1 ( x k ) ∇ F ( x k ) \boldsymbol{x}_{k+1}=\boldsymbol{x}_k-\boldsymbol{H}^{-1}\left( \boldsymbol{x}_k \right) \nabla F\left( \boldsymbol{x}_k \right) xk+1=xkH1(xk)F(xk)

可以看到,经典牛顿法需要对目标函数求Hessian矩阵的逆矩阵,矩阵求逆的时间复杂度是 O ( n 3 ) O(n^3) O(n3),其中 n n n为矩阵维度,因此牛顿法计算复杂度高、数值稳定性较差。同时,无法保证对于任意 f ( x ) f\left( \boldsymbol{x} \right) f(x)的Hessian矩阵可逆且正定。

为了克服牛顿法的缺陷,引入拟牛顿法(quasi-Newton method):根据迭代点处的梯度信息求 H ( x ) \boldsymbol{H}\left( \boldsymbol{x} \right) H(x)的近似值 B k ( x ) \boldsymbol{B}_k\left( \boldsymbol{x} \right) Bk(x) H − 1 ( x ) \boldsymbol{H}^{-1}\left( \boldsymbol{x} \right) H1(x)的近似值 H k ( x ) \boldsymbol{H}_k\left( \boldsymbol{x} \right) Hk(x)来降低计算量,算法流程如图所示。根据近似矩阵更新算法的不同,拟牛顿法有若干子算法

在这里插入图片描述

2 SR1算法推导

秩一公式(Symmetric Rank-One, SR1)是结构最简单的拟牛顿矩阵更新算法,考虑

H k + 1 = H k + Δ H k \boldsymbol{H}_{k+1}=\boldsymbol{H}_k+\varDelta \boldsymbol{H}_k Hk+1=Hk+ΔHk

期望 H k + 1 ≈ H ( x k + 1 ) \boldsymbol{H}_{k+1}\approx \boldsymbol{H}\left( \boldsymbol{x}_{k+1} \right) Hk+1H(xk+1) H k ≈ H ( x k ) \boldsymbol{H}_k\approx \boldsymbol{H}\left( \boldsymbol{x}_k \right) HkH(xk),所以 Δ H k ≈ H ( x k + 1 ) − H ( x k ) \varDelta \boldsymbol{H}_k\approx \boldsymbol{H}\left( \boldsymbol{x}_{k+1} \right) -\boldsymbol{H}\left( \boldsymbol{x}_k \right) ΔHkH(xk+1)H(xk)。由于Hessian矩阵对称,所以 Δ H k \varDelta \boldsymbol{H}_k ΔHk也应对称,不妨令 Δ H k = β u u T \varDelta \boldsymbol{H}_k=\beta \boldsymbol{uu}^T ΔHk=βuuT;接着,对 ∇ F ( x ) \nabla F\left( \boldsymbol{x} \right) F(x) x k + 1 \boldsymbol{x}_{k+1} xk+1处一阶泰勒展开可得

∇ F ( x ) = ∇ F ( x k + 1 ) + H ( x k + 1 ) ( x − x k + 1 ) \nabla F\left( \boldsymbol{x} \right) =\nabla F\left( \boldsymbol{x}_{k+1} \right) +\boldsymbol{H}\left( \boldsymbol{x}_{k+1} \right) \left( \boldsymbol{x}-\boldsymbol{x}_{k+1} \right) F(x)=F(xk+1)+H(xk+1)(xxk+1)

s k = x k + 1 − x k \boldsymbol{s}_k=\boldsymbol{x}_{k+1}-\boldsymbol{x}_k sk=xk+1xk y k = ∇ F ( x k + 1 ) − ∇ F ( x k ) \boldsymbol{y}_k=\nabla F\left( \boldsymbol{x}_{k+1} \right) -\nabla F\left( \boldsymbol{x}_k \right) yk=F(xk+1)F(xk),则

y k = B k + 1 s k ⇒ H k + 1 y k = s k \boldsymbol{y}_k=\boldsymbol{B}_{k+1}\boldsymbol{s}_k\Rightarrow \boldsymbol{H}_{k+1}\boldsymbol{y}_k=\boldsymbol{s}_k yk=Bk+1skHk+1yk=sk

注意到 s k T B k + 1 s k = s k T y k \boldsymbol{s}_{k}^{T}\boldsymbol{B}_{k+1}\boldsymbol{s}_k=\boldsymbol{s}_{k}^{T}\boldsymbol{y}_k skTBk+1sk=skTyk,为了使 H k \boldsymbol{H}_k Hk B k \boldsymbol{B}_k Bk正定,需要在迭代过程中保证 s k T y k > 0 \boldsymbol{s}_{k}^{T}\boldsymbol{y}_k>0 skTyk>0。基于上式,在 Δ H k = β u u T \varDelta \boldsymbol{H}_k=\beta \boldsymbol{uu}^T ΔHk=βuuT两边同时右乘 y k \boldsymbol{y}_k yk

u = γ ( s k − H k y k ) \boldsymbol{u}=\gamma \left( \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k \right) u=γ(skHkyk)

其中

γ = 1 β u T y k \gamma =\frac{1}{\beta \boldsymbol{u}^T\boldsymbol{y}_k} γ=βuTyk1

u = γ ( s k − H k y k ) \boldsymbol{u}=\gamma \left( \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k \right) u=γ(skHkyk)反代回 H k + 1 y k = H k y k + β u u T y k \boldsymbol{H}_{k+1}\boldsymbol{y}_k=\boldsymbol{H}_k\boldsymbol{y}_k+\beta \boldsymbol{uu}^T\boldsymbol{y}_k Hk+1yk=Hkyk+βuuTyk可得

s k − H k y k = β γ 2 ( s k − H k y k ) T y k ( s k − H k y k ) \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k=\beta \gamma ^2\left( \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k \right) ^T\boldsymbol{y}_k\left( \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k \right) skHkyk=βγ2(skHkyk)Tyk(skHkyk)

显见 β γ 2 = 1 / ( s k − H k y k ) T y k \beta \gamma ^2={{1}/{\left( \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k \right) ^T\boldsymbol{y}_k}} βγ2=1/(skHkyk)Tyk,从而得到SR1的更新公式

H k + 1 = H k + ( s k − H k y k ) ( s k − H k y k ) T ( s k − H k y k ) T y k \boldsymbol{H}_{k+1}=\boldsymbol{H}_k+\frac{\left( \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k \right) \left( \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k \right) ^T}{\left( \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k \right) ^T\boldsymbol{y}_k} Hk+1=Hk+(skHkyk)Tyk(skHkyk)(skHkyk)T

代码实现为

gx = g_func(x)
d = (H @ gx).squeeze()
alpha = self.line_searcher_.search(func, g_func, x, -d)

x_next = x - alpha * d
s = x_next - x
y = g_func(x_next) - gx

item = s - H @ y
H = H + item @ item.T / (item.T @ y)

3 DFP算法推导

DFP算法是SR1算法的拓展版本,引入了更大的自由度

H k + 1 = H k + β u u T + γ v v T \boldsymbol{H}_{k+1}=\boldsymbol{H}_k+\beta \boldsymbol{uu}^T+\gamma \boldsymbol{vv}^T Hk+1=Hk+βuuT+γvvT

与SR1算法推导类似,方程两边同时右乘 y k \boldsymbol{y}_k yk得到

s k = H k + 1 y k = H k y k + β u u T y k + γ v v T y k \boldsymbol{s}_k=\boldsymbol{H}_{k+1}\boldsymbol{y}_k=\boldsymbol{H}_k\boldsymbol{y}_k+\beta \boldsymbol{uu}^T\boldsymbol{y}_k+\gamma \boldsymbol{vv}^T\boldsymbol{y}_k sk=Hk+1yk=Hkyk+βuuTyk+γvvTyk

u = s k \boldsymbol{u}=\boldsymbol{s}_k u=sk v = H k y k \boldsymbol{v}=\boldsymbol{H}_k\boldsymbol{y}_k v=Hkyk,则 s k − H k y k = β s k s k T y k + γ H k y k y k T H k T y k \boldsymbol{s}_k-\boldsymbol{H}_k\boldsymbol{y}_k=\beta \boldsymbol{s}_k\boldsymbol{s}_{k}^{T}\boldsymbol{y}_k+\gamma \boldsymbol{H}_k\boldsymbol{y}_k\boldsymbol{y}_{k}^{T}\boldsymbol{H}_{k}^{T}\boldsymbol{y}_k skHkyk=βskskTyk+γHkykykTHkTyk,从而

{ β = 1 s k T y k γ = − 1 y k T H k T y k \begin{cases} \beta =\frac{1}{\boldsymbol{s}_{k}^{T}\boldsymbol{y}_k}\\ \gamma =-\frac{1}{\boldsymbol{y}_{k}^{T}\boldsymbol{H}_{k}^{T}\boldsymbol{y}_k}\\\end{cases} {β=skTyk1γ=ykTHkTyk1

得到DFP的更新公式

H k + 1 = H k + s k s k T s k T y k − H k y k y k T H k T y k T H k T y k \boldsymbol{H}_{k+1}=\boldsymbol{H}_k+\frac{\boldsymbol{s}_k\boldsymbol{s}_{k}^{T}}{\boldsymbol{s}_{k}^{T}\boldsymbol{y}_k}-\frac{\boldsymbol{H}_k\boldsymbol{y}_k\boldsymbol{y}_{k}^{T}\boldsymbol{H}_{k}^{T}}{\boldsymbol{y}_{k}^{T}\boldsymbol{H}_{k}^{T}\boldsymbol{y}_k} Hk+1=Hk+skTykskskTykTHkTykHkykykTHkT

代码实现为

gx = g_func(x)
d = (H @ gx).squeeze()
alpha = self.line_searcher_.search(func, g_func, x, -d)

x_next = x - alpha * d
s = x_next - x
y = g_func(x_next) - gx

sTy = float(s.T @ y)
H = H + s @ s.T / sTy - H @ y @ y.T @ H.T / float(y.T @ H.T @ y)

4 BFGS算法推导

BFGS算法是DFP的对偶版本,假设

B k + 1 = B k + β u u T + γ v v T \boldsymbol{B}_{k+1}=\boldsymbol{B}_k+\beta \boldsymbol{uu}^T+\gamma \boldsymbol{vv}^T Bk+1=Bk+βuuT+γvvT

类比DFP推导过程可得到

B k + 1 = B k + y k y k T y k T s k − B k s k s k T B k T s k T B k T s k \boldsymbol{B}_{k+1}=\boldsymbol{B}_k+\frac{\boldsymbol{y}_k\boldsymbol{y}_{k}^{T}}{\boldsymbol{y}_{k}^{T}\boldsymbol{s}_k}-\frac{\boldsymbol{B}_k\boldsymbol{s}_k\boldsymbol{s}_{k}^{T}\boldsymbol{B}_{k}^{T}}{\boldsymbol{s}_{k}^{T}\boldsymbol{B}_{k}^{T}\boldsymbol{s}_k} Bk+1=Bk+ykTskykykTskTBkTskBkskskTBkT

为了进一步计算 H k = B k − 1 \boldsymbol{H}_k=\boldsymbol{B}_{k}^{-1} Hk=Bk1,应用下面的引理

Shermann-Morrison-Woodbury公式 A \boldsymbol{A} A n × n n\times n n×n可逆矩阵,向量 u \boldsymbol{u} u v ∈ R n \boldsymbol{v}\in \mathbb{R} ^n vRn ,则 A + u v T \boldsymbol{A}+\boldsymbol{uv}^T A+uvT可逆当且仅当 1 + v T A − 1 u ≠ 0 1+\boldsymbol{v}^T\boldsymbol{A}^{-1}\boldsymbol{u}\ne 0 1+vTA1u=0,且

( A + u v T ) − 1 = A − 1 − A − 1 u v T A − 1 1 + v T A − 1 u \left( \boldsymbol{A}+\boldsymbol{uv}^T \right) ^{-1}=\boldsymbol{A}^{-1}-\frac{\boldsymbol{A}^{-1}\boldsymbol{uv}^T\boldsymbol{A}^{-1}}{1+\boldsymbol{v}^T\boldsymbol{A}^{-1}\boldsymbol{u}} (A+uvT)1=A11+vTA1uA1uvTA1

从而得到BFGS更新公式

H k + 1 = ( I − s k y k T s k T y k ) H k ( I − y k s k T s k T y k ) + s k s k T s k T y k \boldsymbol{H}_{k+1}=\left( \boldsymbol{I}-\frac{\boldsymbol{s}_k\boldsymbol{y}_{k}^{T}}{\boldsymbol{s}_{k}^{T}\boldsymbol{y}_k} \right) \boldsymbol{H}_k\left( \boldsymbol{I}-\frac{\boldsymbol{y}_k\boldsymbol{s}_{k}^{T}}{\boldsymbol{s}_{k}^{T}\boldsymbol{y}_k} \right) +\frac{\boldsymbol{s}_k\boldsymbol{s}_{k}^{T}}{\boldsymbol{s}_{k}^{T}\boldsymbol{y}_k} Hk+1=(IskTykskykT)Hk(IskTykykskT)+skTykskskT

代码实现为

gx = g_func(x)
d = (H @ gx).squeeze()
alpha = self.line_searcher_.search(func, g_func, x, -d)

x_next = x - alpha * d
s = x_next - x
y = g_func(x_next) - gx

sTy = float(s.T @ y)
H = (I - s @ y.T / sTy) @ H @ (I - y @ s.T / sTy) + s @ s.T / sTy

5 L-BFGS算法推导

在BFGS算法中,每次迭代需要上一轮的 H k \boldsymbol{H}_k Hk,而保存 H k \boldsymbol{H}_k Hk至少需要 O ( n 2 ) O(n^2) O(n2)的空间复杂度,这对于大规模数值优化问题而言无法接受。L-BFGS对BFGS的内存占用率进行了限制,记 ρ k = 1 / s k T y k \rho _k={{1}/{\boldsymbol{s}_{k}^{T}\boldsymbol{y}_k}} ρk=1/skTyk V k = I − ρ k y k s k T \boldsymbol{V}_k=\boldsymbol{I}-\rho _k\boldsymbol{y}_k\boldsymbol{s}_{k}^{T} Vk=IρkykskT,则递推地

H k + 1 = V k T H k V k + ρ k s k s k T = ( V k T ⋯ V 0 T ) H 0 ( V 0 ⋯ V k ) + ( V k T ⋯ V 1 T ) ρ 1 s 1 s 1 T ( V 1 ⋯ V k ) + ⋯ + ρ k s k s k T \begin{aligned}\boldsymbol{H}_{k+1}&=\boldsymbol{V}_{k}^{T}\boldsymbol{H}_k\boldsymbol{V}_k+\rho _k\boldsymbol{s}_k\boldsymbol{s}_{k}^{T}\\&=\left( \boldsymbol{V}_{k}^{T}\cdots \boldsymbol{V}_{0}^{T} \right) \boldsymbol{H}_0\left( \boldsymbol{V}_0\cdots \boldsymbol{V}_k \right) +\left( \boldsymbol{V}_{k}^{T}\cdots \boldsymbol{V}_{1}^{T} \right) \rho _1\boldsymbol{s}_1\boldsymbol{s}_{1}^{T}\left( \boldsymbol{V}_1\cdots \boldsymbol{V}_k \right) +\cdots +\rho _k\boldsymbol{s}_k\boldsymbol{s}_{k}^{T}\end{aligned} Hk+1=VkTHkVk+ρkskskT=(VkTV0T)H0(V0Vk)+(VkTV1T)ρ1s1s1T(V1Vk)++ρkskskT

仅保留最近 m m m步的结果

H k + 1 = ( V k T ⋯ V k − m + 1 T ) H 0 ( V k − m + 1 ⋯ V k )    + ( V k T ⋯ V k − m + 2 T ) ρ k − m + 1 s k − m + 1 s k − m + 1 T ( V k − m + 2 ⋯ V k )    + ⋯    + ρ k s k s k T \begin{aligned}\boldsymbol{H}_{k+1}&=\left( \boldsymbol{V}_{k}^{T}\cdots \boldsymbol{V}_{k-m+1}^{T} \right) \boldsymbol{H}_0\left( \boldsymbol{V}_{k-m+1}\cdots \boldsymbol{V}_k \right) \\\,\, &+\left( \boldsymbol{V}_{k}^{T}\cdots \boldsymbol{V}_{k-m+2}^{T} \right) \rho _{k-m+1}\boldsymbol{s}_{k-m+1}\boldsymbol{s}_{k-m+1}^{T}\left( \boldsymbol{V}_{k-m+2}\cdots \boldsymbol{V}_k \right) \\\,\, &+\cdots \\\,\, &+\rho _k\boldsymbol{s}_k\boldsymbol{s}_{k}^{T}\end{aligned} Hk+1=(VkTVkm+1T)H0(Vkm+1Vk)+(VkTVkm+2T)ρkm+1skm+1skm+1T(Vkm+2Vk)++ρkskskT

因此在L-BFGS算法中无需保留完整的 H k \boldsymbol{H}_k Hk,只需存储向量序列 { s i } i = k − m k \left\{ \boldsymbol{s}_i \right\} _{i=k-m}^{k} {si}i=kmk { y i } i = k − m k \left\{ \boldsymbol{y}_i \right\} _{i=k-m}^{k} {yi}i=kmk,占用存储空间 2 m n 2mn 2mn,空间复杂度为 O ( n ) O(n) O(n),下降了一个量级

代码实现为

 gx = g_func(x)

# two-iteration
a = []
d = g_func(x).reshape(-1, 1)
for i in range(len(S) - 1, -1, -1):
    s_i, y_i, p_i = S[i], Y[i], P[i]
    a_i = p_i * s_i.T @ d
    d = d - a_i * y_i
    a.append(a_i)
for i in range(len(S)):
    s_i, y_i, p_i = S[i], Y[i], P[i]
    a_i = a[len(S) - i - 1]
    beta = p_i * y_i.T @ d
    d = d + s_i * (a_i - beta)
d = d.squeeze()
alpha = self.line_searcher_.search(func, g_func, x, -d)

x_next = x - alpha * d

s = (x_next - x).reshape(-1, 1)
y = (g_func(x_next) - gx).reshape(-1, 1)

if len(S) == self.m:
    S.pop(0)
S.append(s)

if len(Y) == self.m:
    Y.pop(0)
Y.append(y)

if len(P) == self.m:
    P.pop(0)
P.append(1.0 / (s.T @ y))

6 案例分析

以曲线拟合为例展示三种牛顿类优化算法的效果

考虑如下方程:
y = e a x 2 + b x + c + w \boldsymbol{y}=e^{a\boldsymbol{x}^2+b\boldsymbol{x}+c}+\boldsymbol{w} y=eax2+bx+c+w
其中 a a a b b b c c c是待估计的曲线参数, w \boldsymbol{w} w是高斯噪声,假设有 n n n个观测样本 ( x i , y i ) (x_i,y_i) (xi,yi),希望根据这组样本得到最佳的曲线参数,构造如下的优化问题
F ( θ ) = min ⁡ 1 2 n ∑ i = 1 n ( y i − e a x i 2 + b x i + c ) 2 F(\boldsymbol{\theta})=\min \frac{1}{2n}\sum_{i=1}^{n}{(y_i-e^{ax_i^2+bx_i+c})^2} F(θ)=min2n1i=1n(yieaxi2+bxi+c)2

下面来看结果

  • SR1算法
    ===========================================================
    Method: SR1
    Iterations: 10, Using time: 0.27718114852905273
    Start Point: [ 2 -1  5]
    Start Value: 16427.297702943684
    End Point: [1.58470727 1.19606329 1.24535202]
    End Value: 0.492582013221927
    ===========================================================
    

在这里插入图片描述

  • DFP算法

    ===========================================================
    Method: DFP
    Iterations: 68, Using time: 1.8977277278900146
    Start Point: [ 2 -1  5]
    Start Value: 16427.297702943684
    End Point: [1.32228464 1.58602539 1.11512083]
    End Value: 0.4622062689277505
    ===========================================================
    

在这里插入图片描述

  • BFGS算法

    ===========================================================
    Method: BFGS
    Iterations: 19, Using time: 0.5240802764892578
    Start Point: [ 2 -1  5]
    Start Value: 16427.297702943684
    End Point: [1.32275944 1.58517781 1.11542359]
    End Value: 0.46220542143350907
    ===========================================================
    

    在这里插入图片描述

  • L-BFGS

    ===========================================================
    Method: LBFGS
    Iterations: 19, Using time: 0.5343437194824219
    Start Point: [ 2 -1  5]
    Start Value: 16427.297702943684
    End Point: [1.32204779 1.58592409 1.11533423]
    End Value: 0.46220620676321367
    ===========================================================
    

在这里插入图片描述

从结果来看,由于LBFGS在内存和计算上都有显著优势,因此它在许多实际问题中(如大规模数据优化、深度学习训练等)得到了广泛应用。它是许多优化库(如SciPyTensorFlowPyTorch等)中常用的优化算法之一

完整工程代码请联系下方博主名片获取


🔥 更多精彩专栏


👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

原文地址:https://blog.csdn.net/FRIGIDWINTER/article/details/144013803

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!