BFGS优化算法简介

本文介绍了BFGS算法,一种广泛用于数值优化的二阶优化方法,尤其在机器学习中的逻辑回归等算法拟合中。通过实例演示如何使用Python的Scipy库实现BFGS和L-BFGS-B算法,以及它们在寻找目标函数极小值中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         【翻译自 : A Gentle Introduction to the BFGS Optimization Algorithm

       【说明:Jason Brownlee PhD大神的文章个人很喜欢,所以闲暇时间里会做一点翻译和学习实践的工作,这里是相应工作的实践记录,希望能帮到有需要的人!】

       Broyden、Fletcher、Goldfarb 和 Shanno 或 BFGS 算法是一种局部搜索优化算法。

       它是一种二阶优化算法,意味着它利用目标函数的二阶导数,属于一类被称为近似二阶导数的拟牛顿方法(称为 Hessian)的算法用于无法计算二阶导数的优化问题。

       BFGS算法也许是用于数值优化的最广泛使用的二阶算法之一,并且通常用于拟合机器学习算法,例如逻辑回归算法。

      在本教程中,您将了解 BFGS 二阶优化算法。完成本教程后,您将了解:

二阶优化算法是利用二阶导数的算法,称为多元目标函数的 Hessian 矩阵。
BFGS 算法可能是最流行的数值优化二阶算法,属于一类称为拟牛顿法的算法。
如何使用 Python 中的 BFGS 和 L-BFGS-B 算法最小化目标函数。

教程概述

       本教程分为三个部分;他们是:

二阶优化算法
BFGS 优化算法
BFGS 的工作示例
二阶优化算法

        优化涉及寻找最大化或最小化目标函数的输入参数值。牛顿法优化算法是那些利用目标函数的二阶导数的算法。

       您可能从微积分中回忆,函数的一阶导数是函数在特定点的变化率或曲率。可以通过优化算法朝着函数的最小值(导致目标函数的最小输出的输入值)下坡(或上坡)跟踪导数。

      利用一阶导数的算法称为一阶优化算法。一阶算法的一个例子是梯度下降优化算法。

一阶方法:优化算法利用一阶导数来找到目标函数的最优值。
二阶导数是导数的导数,或变化率的变化率。

         可以遵循二阶导数以更有效地定位目标函数的最优值。这更普遍,因为我们掌握的关于目标函数的信息越多,优化它就越容易。

          二阶导数使我们既可以知道要移动的方向(如一阶),还可以估计在该方向上移动的距离,称为步长。

        利用二阶导数的算法称为二阶优化算法。

二阶方法:利用二阶导数来寻找目标函数最优值的优化算法。
二阶优化算法的一个例子是牛顿法。

       当一个目标函数有多个输入变量时,输入变量一起可以被认为是一个向量,这在线性代数中可能很熟悉。

       同样,多个输入变量的一阶导数也可以是一个向量,其中每个元素称为偏导数。 这个偏导数向量被称为梯度。

梯度:目标函数的多个输入变量的偏一阶导数向量。

        这个想法推广到多元输入的二阶导数,这是一个包含二阶导数的矩阵,称为 Hessian 矩阵。

Hessian:目标函数的多个输入变量的偏二阶导数矩阵。

         如果二阶导数在我们计算导数的点上都是连续的,则 Hessian 矩阵是正方形且对称的。 在解决实值优化问题时经常出现这种情况,而在使用许多二阶方法时则是期望值。

        因此,通常描述二阶优化算法利用或遵循 Hessian 到目标函数的最优值。既然我们对二阶优化算法有了高层次的了解,那么让我们仔细看看 BFGS 算法。

BFGS 优化算法

       BFGS 是一种二阶优化算法。它是一个首字母缩写词,以该算法的四个共同发现者命名:Broyden、Fletcher、Goldfarb 和 Shanno。

      它是一种局部搜索算法,用于具有单个最优解的凸优化问题。

      BFGS 算法最好理解为属于一组算法,这些算法是牛顿法优化算法的扩展,称为拟牛顿法。牛顿法是一种利用 Hessian 矩阵的二阶优化算法。牛顿法的一个局限是它需要计算 Hessian 矩阵的逆。这是一个计算成本很高的操作,并且可能不稳定,具体取决于目标函数的属性。拟牛顿方法是二阶优化算法,它使用梯度近似 Hessian 矩阵的逆矩阵,这意味着 Hessian 矩阵及其逆矩阵不需要为算法的每个步骤提供或精确计算。

        不同拟牛顿优化算法的主要区别在于计算逆Hessian近似的具体方式。BFGS 算法是更新逆 Hessian 计算的一种特定方式,而不是每次迭代都重新计算。 它或其扩展可能是最流行的拟牛顿算法之一,甚至是用于数值优化的二阶优化算法。

       如果可用,使用 Hessian 的一个好处是它可用于确定移动的方向和步长,以便更改输入参数以最小化(或最大化)目标函数。像 BFGS 这样的拟牛顿方法近似于逆 Hessian,然后可以用它来确定移动的方向,但我们不再有步长。BFGS 算法通过在所选方向上使用线搜索来确定在该方向上移动多远来解决这个问题。

       对于 BFGS 算法使用的推导和计算,我推荐本教程末尾的进一步阅读部分中的资源。Hessian 的大小及其倒数与目标函数的输入参数数量成正比。 因此,对于数百、数千或数百万个参数,矩阵的大小可能变得非常大。

        有限内存 BFGS(或 L-BFGS)是 BFGS 算法的扩展,它解决了拥有大量参数的成本。 它通过假设算法的前一次迭代中的逆 Hessian 的简化(在近似中使用)不需要存储逆矩阵的整个近似值来做到这一点。现在我们从高层次上熟悉了 BFGS 算法,让我们看看如何使用它。

BFGS 的工作示例

       在本节中,我们将看一些使用 BFGS 优化算法的示例。我们可以使用 minimum() SciPy 函数实现 BFGS 算法来优化 Python 中的任意函数。该函数接受多个参数,但最重要的是,我们可以将目标函数的名称指定为第一个参数,将搜索的起点指定为第二个参数,并将“方法”参数指定为“BFGS”。 可以通过“ jac”自变量指定用于计算目标函数导数的函数名称。

# perform the bfgs algorithm search
result = minimize(objective, pt, method='BFGS', jac=derivative)

       让我们看一个例子。

       首先,我们可以定义一个简单的二维目标函数,一个碗函数,例如 x ^ 2。 最简单的平方输入变量的总和在 f(0, 0) = 0.0 处具有最优值。

# objective function
def objective(x):
	return x[0]**2.0 + x[1]**2.0

       接下来,让我们为函数的导数定义一个函数,即 [x*2, y*2]。

# derivative of the objective function
def derivative(x):
	return [x[0] * 2, x[1] * 2]

       我们将函数的边界定义为每个维度的范围为 -5 和 5 的框。

# define range for input
r_min, r_max = -5.0, 5.0

       搜索的起点将是搜索域中随机生成的位置。

# define the starting point as a random sample from the domain
pt = r_min + rand(2) * (r_max - r_min)

       然后我们可以通过指定目标函数的名称、初始点、我们想要使用的方法(BFGS)和导函数的名称来应用 BFGS 算法来找到目标函数的最小值。

# perform the bfgs algorithm search
result = minimize(objective, pt, method='BFGS', jac=derivative)

        然后,我们可以查看结果,报告一条关于算法是否成功完成以及执行的目标函数评估总数的消息。

# summarize the result
print('Status : %s' % result['message'])
print('Total Evaluations: %d' % result['nfev'])

        最后,我们可以报告找到的输入变量及其对目标函数的评估。

# evaluate solution
solution = result['x']
evaluation = objective(solution)
print('Solution: f(%s) = %.5f' % (solution, evaluation))

        完整实例如下:

# bfgs algorithm local optimization of a convex function
from scipy.optimize import minimize
from numpy.random import rand

# objective function
def objective(x):
	return x[0]**2.0 + x[1]**2.0

# derivative of the objective function
def derivative(x):
	return [x[0] * 2, x[1] * 2]

# define range for input
r_min, r_max = -5.0, 5.0
# define the starting point as a random sample from the domain
pt = r_min + rand(2) * (r_max - r_min)
# perform the bfgs algorithm search
result = minimize(objective, pt, method='BFGS', jac=derivative)
# summarize the result
print('Status : %s' % result['message'])
print('Total Evaluations: %d' % result['nfev'])
# evaluate solution
solution = result['x']
evaluation = objective(solution)
print('Solution: f(%s) = %.5f' % (solution, evaluation))

        运行示例将 BFGS 算法应用于我们的目标函数并报告结果。

       注意:由于算法或评估程序的随机性或数值精度的差异,您的结果可能会有所不同。 考虑多次运行该示例并比较平均结果。

      在这种情况下,我们可以看到执行了算法的四次迭代,并且发现了一个非常接近最优值 f(0.0, 0.0) = 0.0 的解决方案,至少达到了有用的精度水平。

Status: Optimization terminated successfully.
Total Evaluations: 4
Solution: f([0.00000000e+00 1.11022302e-16]) = 0.00000

        minimum() 函数还支持内存需求比 BFGS 低的 L-BFGS 算法。

       具体来说,算法的 L-BFGS-B 版本,其中 -B 后缀表示算法的“盒装”版本,可以指定域的边界。

       这可以通过将“方法”参数指定为“L-BFGS-B”来实现。

# perform the l-bfgs-b algorithm search
result = minimize(objective, pt, method='L-BFGS-B', jac=derivative)

        完整实例如下:

# l-bfgs-b algorithm local optimization of a convex function
from scipy.optimize import minimize
from numpy.random import rand

# objective function
def objective(x):
	return x[0]**2.0 + x[1]**2.0

# derivative of the objective function
def derivative(x):
	return [x[0] * 2, x[1] * 2]

# define range for input
r_min, r_max = -5.0, 5.0
# define the starting point as a random sample from the domain
pt = r_min + rand(2) * (r_max - r_min)
# perform the l-bfgs-b algorithm search
result = minimize(objective, pt, method='L-BFGS-B', jac=derivative)
# summarize the result
print('Status : %s' % result['message'])
print('Total Evaluations: %d' % result['nfev'])
# evaluate solution
solution = result['x']
evaluation = objective(solution)
print('Solution: f(%s) = %.5f' % (solution, evaluation))

        运行示例应用程序将 L-BFGS-B 算法应用于我们的目标函数并报告结果。

       注意:由于算法或评估程序的随机性或数值精度的差异,您的结果可能会有所不同。 考虑多次运行该示例并比较平均结果。

        再次,我们可以看到函数的最小值是在很少的评估中找到的。

Status : b'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL'
Total Evaluations: 3
Solution: f([-1.33226763e-15 1.33226763e-15]) = 0.00000

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值