机器学习优化算法—L-BFGS

L-BFGS是优化算法的一种,针对大规模优化问题,它改进了拟牛顿法中的BFGS算法,仅存储最近m次迭代的曲率信息以减少计算和存储开销。通过线性收敛,保持近似矩阵正定,实现快速且鲁棒的优化过程。在实际工程中,L-BFGS表现出高效性能。
部署运行你感兴趣的模型镜像

关于优化算法的求解,书上已经介绍了很多的方法,比如有梯度下降法,坐标下降法,牛顿法和拟牛顿法。梯度下降法是基于目标函数梯度的,算法的收敛速度是线性的,并且当问题是病态时或者问题规模较大时,收敛速度尤其慢(几乎不适用);坐标下降法虽然不用计算目标函数的梯度,但是其收敛速度依然很慢,因此它的适用范围也有局限;牛顿法是基于目标函数的二阶导数(海森矩阵)的,其收敛速度较快,迭代次数较少,尤其是在最优值附近时,收敛速度是二次的。但牛顿法的问题在于当海森矩阵稠密时,每次迭代的计算量比较大,因为每次都会计算目标函数的海森矩阵的逆,这样一来,当问题规模较大时,不仅计算量大(有时大到不可计算),而且需要的存储空间也多,因此牛顿法在面对海量数据时由于每一步迭代的开销巨大而变得不适用;拟牛顿法是在牛顿法的基础上引入了海森矩阵的近似矩阵,避免每次迭代都要计算海森矩阵的逆,拟牛顿法的收敛速度介于梯度下降法和牛顿法之间,是超线性的。拟牛顿法的问题也是当问题规模很大时,近似矩阵变得很稠密,在计算和存储上也有很大的开销,因此变得不实用。

另外需要注意的是,牛顿法在每次迭代时不能总是保证海森矩阵是正定的,一旦海森矩阵不是正定的,优化方向就会“跑偏”,从而使得牛顿法失效,也说明了牛顿法的鲁棒性较差。拟牛顿法用海森矩阵的逆矩阵来替代海森矩阵,虽然每次迭代不能保证是最优的优化方向,但是近似矩阵始终是正定的,因此算法总是朝着最优值的方向在搜索。

从上面的描述可以看出,很多优化算法在理论上有很好的结果,并且当优化问题的规模较小时,上面的任何算法都能够很好地解决问题。而在实际工程中,很多算法却失效了。比如说,在实际工程中,很多问题是病态的,这样一来,基于梯度的方法肯定会失效,即便迭代上千上万次也未必收敛到很好的结果;另外,当数据量大的时候,牛顿法和拟牛顿法需要保存矩阵的内存开销和计算矩阵的开销都很大,因此也会变得不适用。

本文将介绍一种在实际工程中解决大规模优化问题时必然会用到的优化算法:L-BFGS算法。

上面已经提到了在面对大规模优化问题时,由于近似矩阵往往是稠密的,在计算和存储上都是n2的增长,因此拟牛顿法变得不适用。

L-BFGS算法就是对拟牛顿算法的一个改进。它的名字已经告诉我们它是基于拟牛顿法BFGS算法的改进。L-BFGS算法的基本思想是:算法只保存并利用最近m次迭代的曲率信息来构造海森矩阵的近似矩阵。

在介绍L-BFGS算法之前,我们先来简单回顾下BFGS算法。

在算法的每一步迭代,有如下式:

,      k = 0, 1, 2,…,           (1)

式(1)中ak是步长,Hk的更新通过如下公式:

 (2)

在式(2)中

 (3)

 (4)

 (5)

(6)

从式(2)到式(6)可以看出Hk+1是用{sk, yk}修正Hk来得到的。需要注意的是,这里Hk表示海森矩阵的逆的近似矩阵。

在BFGS算法中,由于Hk随着迭代次数的增加会越来越稠密,当优化问题的规模很大时,存储和计算矩阵Hk将变得不可行。

为了解决上述问题,我们可以不存储矩阵Hk,而是存储最近m次迭代的曲率信息,即{sk, yk}。每当完成一次迭代,最旧的曲率信息{si, yi}将被删除,而最新的曲率信息被保存下来。通过这种方式,算法保证了保存的曲率信息是来自于最近的m次迭代。在实际工程中,m取3到20往往能有很好的结果。除了更新矩阵Hk的策略和初始化Hk的方式不同外,L-BFGS算法和BFGS算法是一样的。

下面将会详细介绍一下矩阵Hk的更新步骤。

在第k次迭代,算法求得了xk,并且保存的曲率信息为{si, yi},其中i = k-m, …, k-1。为了得到Hk,算法首先选择一个初始的矩阵Hk0,这是不同于BFGS算法的一个地方,L-BFGS算法允许每次迭代选取一个初始的矩阵,然后用最近的m次曲率信息对该初始矩阵进行修正,从而得到Hk

通过反复利用式(2),我们可以得到下式:

     (7)

关于每次迭代时Hk0的初始值的设定,一个在实践中经常用到的有效方法为:

 (8)

(9)

其中rk表示比例系数,它利用最近一次的曲率信息来估计真实海森矩阵的大小,这就使得当前步的搜索方向较为理想,而不至于跑得“太偏”,从而使得步长ak = 1在大多数时候都是满足的,这样就省去了步长搜索的步骤,节省了时间。

在L-BFGS算法中,通过保存最近m次的曲率信息来更新近似矩阵的这种方法在实践中是很有效的。

虽然L-BFGS算法是线性收敛,但是每次迭代的开销非常小,因此L-BFGS算法执行速度还是很快的,而且由于每一步迭代都能保证近似矩阵的正定,因此算法的鲁棒性还是很强的。

百度最近提出了一个shooting算法,该算法比L-BFGS快了十倍。由于L-BFGS算法的迭代方向不是最优的,所以我猜想shooting算法应该是在迭代的方向上做了优化。

您可能感兴趣的与本文相关的镜像

ComfyUI

ComfyUI

AI应用
ComfyUI

ComfyUI是一款易于上手的工作流设计工具,具有以下特点:基于工作流节点设计,可视化工作流搭建,快速切换工作流,对显存占用小,速度快,支持多种插件,如ADetailer、Controlnet和AnimateDIFF等

<think>好的,用户想了解L-BFGS-B算法的实现或者如何在优化中使用它。首先,我需要回忆一下L-BFGS-B的基本概念。L-BFGS-B是L-BFGS的扩展版本,支持边界约束,也就是变量可以有上下限。这个算法属于拟牛顿法的一种,用于解决大规模非线性优化问题。 接下来,用户可能想知道具体的实现方式。常见的实现应该是在不同的编程语言中,比如Python的SciPy库。我需要确认SciPy中是否有对应的接口。是的,SciPy的optimize模块中的`minimize`函数支持method='L-BFGS-B',这里需要详细说明参数设置,比如func, x0, bounds, jac等。 然后,用户可能关心实际应用的例子,比如带约束的优化问题。比如最小化二次函数,但变量有上下限。给出具体的代码示例会很有帮助,这样用户可以直观地看到如何调用函数和设置边界。 另外,用户可能还想了解算法背后的原理,比如如何利用有限的存储来近似Hessian矩阵,以及如何处理边界约束。这部分需要简要说明,但不需要太深入数学细节,保持实用性。 还需要提到其他支持L-BFGS-B的库,比如TensorFlow的优化器,或者Julia的Optim包,这样用户知道在不同环境下如何应用。同时,要指出算法适用于变量较多但内存有限的情况,以及梯度计算的方法,比如用户提供或自动微分。 注意引用用户提供的参考内容,比如引用[1]提到使用L-BFGS优化图像初始化,这可能和用户的应用场景相关。结合这些引用,说明L-BFGS-B在机器学习中的应用,比如模型训练或超参数优化。 最后,生成相关问题时要覆盖原理、与其他优化算法的比较、实际应用中的问题和边界约束处理等,这样用户可以有进一步探索的方向。</think>### L-BFGS-B算法解析与实现 L-BFGS-B(Limited-memory Broyden-Fletcher-Goldfarb-Shanno with Bounds)是一种用于带边界约束的非线性优化问题的拟牛顿算法,特别适合大规模优化问题。其核心思想是通过有限内存存储历史梯度信息来近似Hessian矩阵,同时处理变量边界约束[^1]。 #### 1. 算法特点 - **边界支持**: 允许对变量设置上下限约束,例如 $x_i \in [l_i, u_i]$ - **低内存消耗**: 仅保存最近m次迭代的梯度信息(通常m=5-20) - **隐式Hessian近似**: 通过梯度变化构建Hessian矩阵的逆近似,避免直接存储 $O(n^2)$ 矩阵 #### 2. Python实现示例 SciPy库提供标准实现: ```python from scipy.optimize import minimize def objective(x): return (x[0]-1)**2 + (x[1]-2.5)**2 # 目标函数示例 # 定义变量边界:(lower, upper) bounds = [(0, None), (0, None)] # x1≥0, x2≥0 result = minimize(objective, x0=[0,0], method='L-BFGS-B', bounds=bounds, jac='2-point') # 自动计算梯度 print(f"最优解: {result.x}, 目标值: {result.fun}") ``` #### 3. 关键参数说明 | 参数 | 作用 | 典型值 | |------|------|-------| | `m` | 存储的历史梯度数 | 5-20 | | `factr` | 收敛精度阈值 | 1e7(低精度)-1e12(高精度) | | `maxls` | 最大线搜索次数 | 20-50 | #### 4. 应用场景 - 神经网络参数优化(结合自动微分) - 物理系统参数估计(带物理约束) - 金融组合优化(持仓量约束) - 图像生成优化(如引用[1]中白噪声初始化优化) #### 5. 梯度处理建议 ```python # 显式提供梯度可提升效率 def rosen_der(x): dx = -2*(1-x[0]) - 400*x[0]*(x[1]-x[0]**2) dy = 200*(x[1]-x[0]**2) return np.array([dx, dy]) minimize(rosen, x0, method='L-BFGS-B', jac=rosen_der) ```
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值