brute#
- scipy.optimize.brute(func, ranges, args=(), Ns=20, full_output=0, finish=<function fmin>, disp=False, workers=1)[源代码]#
通过蛮力方法在给定范围内最小化函数。
使用“蛮力”方法,即计算多维网格中每个点的函数值,以找到函数的全局最小值。
该函数在整个范围内进行评估,数据类型由第一次调用该函数决定,由 NumPy 的
vectorize
函数强制执行。当full_output=True
时,函数评估的返回值和类型还会受到finish
参数的影响(请参阅 Notes)。蛮力方法效率低下,因为网格点的数量呈指数增长 - 要评估的网格点数量为
Ns ** len(x)
。因此,即使网格间距较粗,即使是中等规模的问题也可能需要很长时间才能运行,和/或遇到内存限制。- 参数:
- func可调用对象
要最小化的目标函数。必须采用
f(x, *args)
的形式,其中x
是以 1-D 数组形式的参数,而args
是完全指定该函数所需的任何其他固定参数的元组。- ranges元组
ranges 元组的每个组件必须是“切片对象”或
(low, high)
形式的范围元组。程序使用它们来创建计算目标函数的点网格。有关更多详细信息,请参阅 Note 2。- args元组,可选
完全指定该函数所需的任何其他固定参数。
- Nsint,可选
如果未另行指定,则为沿轴的网格点数。请参阅 Note2。
- full_outputbool,可选
如果为 True,则返回评估网格和目标函数的值。
- finish可调用对象,可选
一个优化函数,使用蛮力最小化的结果作为初始猜测进行调用。finish 应该将 func 和初始猜测作为位置参数,并将 args 作为关键字参数。它还可以将 full_output 和/或 disp 作为关键字参数。如果不需要使用“精修”函数,则使用 None。有关更多详细信息,请参阅 Notes。
- dispbool,可选
设置为 True 以打印来自 finish 可调用对象的收敛消息。
- workersint 或类似 map 的可调用对象,可选
如果 workers 是一个整数,则将网格细分为 workers 个部分并并行评估(使用
multiprocessing.Pool
)。提供 -1 以使用该进程可用的所有核心。或者,提供一个类似于 map 的可调用对象,例如 multiprocessing.Pool.map 以并行评估网格。此评估作为workers(func, iterable)
执行。要求 func 可被 pickle 化。在 1.3.0 版本中添加。
- 返回:
- x0ndarray
一个 1-D 数组,其中包含目标函数具有最小值的点的坐标。(有关返回哪个点,请参阅 Note 1。)
- fvalfloat
在点 x0 处的函数值。(当 full_output 为 True 时返回。)
- grid元组
评估网格的表示形式。它的长度与 x0 相同。(当 full_output 为 True 时返回。)
- Joutndarray
评估网格中每个点的函数值,即
Jout = func(*grid)
。(当 full_output 为 True 时返回。)
注释
Note 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。