brute#
- scipy.optimize.brute(func, ranges, args=(), Ns=20, full_output=0, finish=<function fmin>, disp=False, workers=1)[source]#
通过暴力法在给定范围内最小化函数。
采用“暴力法”,即计算函数在多维网格中每个点的值,以找到函数的全局最小值。
函数在整个范围内都会使用第一次调用时的数据类型进行评估,这由
vectorize
NumPy 函数强制执行。当full_output=True
时,返回的函数评估值和类型还会受到finish
参数的影响(参见备注)。暴力法效率低下,因为网格点数量呈指数级增长——要评估的网格点数量为
Ns ** len(x)
。因此,即使网格间距粗糙,中等规模的问题也可能运行很长时间,并且/或者遇到内存限制。- 参数:
- func可调用对象
要最小化的目标函数。必须是
f(x, *args)
的形式,其中x
是一个一维数组形式的参数,args
是一个元组,包含完全指定函数所需的任何额外固定参数。- ranges元组
ranges 元组的每个组件必须是“切片对象”或
(low, high)
形式的范围元组。程序使用这些来创建计算目标函数的点网格。有关更多详细信息,请参见备注 2。- args元组,可选
完全指定函数所需的任何额外固定参数。
- Ns整数,可选
如果未另行指定,沿轴的网格点数量。参见备注 2。
- full_output布尔值,可选
如果为 True,则返回评估网格及其上的目标函数值。
- finish可调用对象,可选
一个优化函数,它以暴力最小化的结果作为初始猜测进行调用。finish 应将 func 和初始猜测作为位置参数,并将 args 作为关键字参数。它还可以将 full_output 和/或 disp 作为关键字参数。如果不使用“优化”函数,则使用 None。有关更多详细信息,请参见备注。
- disp布尔值,可选
设置为 True 可打印来自 finish 可调用对象的收敛消息。
- workers整数或类 map 可调用对象,可选
如果 workers 是一个整数,则网格被细分为 workers 个部分并并行评估(使用
multiprocessing.Pool
)。提供 -1 以使用进程可用的所有核心。或者提供一个类 map 可调用对象,例如 multiprocessing.Pool.map 用于并行评估网格。此评估以workers(func, iterable)
的形式进行。要求 func 可被 pickle 化。在 1.3.0 版本中添加。
- 返回:
- x0ndarray
一个一维数组,包含目标函数取最小值的点的坐标。(返回哪个点,请参见备注 1。)
- fval浮点数
在点 x0 处的函数值。(当 full_output 为 True 时返回。)
- grid元组
评估网格的表示。它与 x0 具有相同的长度。(当 full_output 为 True 时返回。)
- Joutndarray
评估网格上每个点的函数值,即
Jout = func(*grid)
。(当 full_output 为 True 时返回。)
备注
备注 1: 程序会找到目标函数值最低的网格点。如果 finish 为 None,则返回该点。当全局最小值出现在网格边界内(或不远超出)且网格足够精细时,该点将位于全局最小值的附近。
然而,用户通常会使用其他优化程序来“优化”网格点值,即在 brute 的最佳网格点附近寻找更精确的(局部)最小值。
brute
函数的 finish 选项提供了一种便捷的方式来完成此操作。任何使用的优化程序都必须将 brute 的输出作为其初始猜测的位置参数,并将 brute 的 args 输入值作为关键字参数,否则将引发错误。它还可以额外接受 full_output 和/或 disp 作为关键字参数。brute
假设 finish 函数返回一个OptimizeResult
对象或一个形式为(xmin, Jmin, ... , statuscode)
的元组,其中xmin
是参数的最小化值,Jmin
是目标函数的最小值,“…”可能是其他返回值(brute
不使用),而statuscode
是 finish 程序的状态码。请注意,当 finish 不为 None 时,返回的值是 finish 程序的值,而不是网格点的值。因此,虽然
brute
将其搜索范围限制在输入网格点上,但 finish 程序的结果通常不会与任何网格点重合,并且可能会落在网格边界之外。因此,如果只需要在提供的网格点上找到最小值,请确保传入finish=None
。备注 2: 点网格是一个
numpy.mgrid
对象。对于brute
,ranges 和 Ns 输入具有以下效果。ranges 元组的每个组件可以是切片对象,也可以是给出值范围的双元组,例如 (0, 5)。如果组件是切片对象,brute
直接使用它。如果组件是双元组范围,brute
会在内部将其转换为一个切片对象,该对象从其低值到高值(包括)内插 Ns 个点。示例
我们通过示例展示如何使用
brute
寻找一个二元函数的全局最小值,该函数由一个正定二次函数和两个深度“高斯形”凹坑的总和给出。具体来说,将目标函数 f 定义为其他三个函数f = f1 + f2 + f3
的总和。我们假设每个函数都有一个签名(z, *params)
,其中z = (x, y)
,params
和函数定义如下。>>> import numpy as np >>> params = (2, 3, 7, 8, 9, 10, 44, -1, 2, 26, 1, -2, 0.5) >>> def f1(z, *params): ... x, y = z ... a, b, c, d, e, f, g, h, i, j, k, l, scale = params ... return (a * x**2 + b * x * y + c * y**2 + d*x + e*y + f)
>>> def f2(z, *params): ... x, y = z ... a, b, c, d, e, f, g, h, i, j, k, l, scale = params ... return (-g*np.exp(-((x-h)**2 + (y-i)**2) / scale))
>>> def f3(z, *params): ... x, y = z ... a, b, c, d, e, f, g, h, i, j, k, l, scale = params ... return (-j*np.exp(-((x-k)**2 + (y-l)**2) / scale))
>>> def f(z, *params): ... return f1(z, *params) + f2(z, *params) + f3(z, *params)
因此,目标函数在其组成的三函数各自的最小值附近可能存在局部最小值。要使用
fmin
来优化其网格点结果,我们可以继续如下操作:>>> rranges = (slice(-4, 4, 0.25), slice(-4, 4, 0.25)) >>> from scipy import optimize >>> resbrute = optimize.brute(f, rranges, args=params, full_output=True, ... finish=optimize.fmin) >>> resbrute[0] # global minimum array([-1.05665192, 1.80834843]) >>> resbrute[1] # function value at global minimum -3.4085818767
请注意,如果 finish 被设置为 None,我们将得到网格点 [-1.0 1.75],其中四舍五入后的函数值为 -2.892。