蛮力#
- scipy.optimize.brute(func, ranges, args=(), Ns=20, full_output=0, finish=<function fmin>, disp=False, workers=1)[源代码][源代码]#
通过暴力方法在给定范围内最小化一个函数。
使用“暴力”方法,即,在多维网格的每个点上计算函数值,以找到函数的全局最小值。
该函数在整个范围内以首次调用该函数的数据类型进行评估,这是由
vectorize
NumPy 函数强制执行的。当full_output=True
时,函数评估返回的值和类型还会受到finish
参数的影响(参见注释)。暴力求解方法效率低下,因为网格点的数量呈指数增长——需要评估的网格点数量为
Ns ** len(x)
。因此,即使使用粗网格间距,即使是中等规模的问题也可能需要很长时间才能运行,和/或遇到内存限制。- 参数:
- 函数可调用
要最小化的目标函数。必须采用
f(x, *args)
的形式,其中x
是以 1-D 数组形式表示的参数,args
是包含任何额外固定参数的元组,这些参数是完整定义函数所必需的。- 范围元组
ranges 元组的每个组成部分必须是“切片对象”或形式为
(low, high)
的范围元组。程序使用这些来创建目标函数将在其上计算的点网格。更多细节请参见 Note 2。- 参数tuple, 可选
完全指定函数所需的任何额外固定参数。
- 命名空间int, 可选
轴上的网格点数量,如果未另行指定。参见 Note2。
- 完整输出bool, 可选
如果为真,返回评估网格和目标函数在其上的值。
- 完成可调用,可选
一个优化函数,使用暴力最小化的结果作为初始猜测来调用。finish 应将 func 和初始猜测作为位置参数,并将 args 作为关键字参数。它还可以额外接受 full_output 和/或 disp 作为关键字参数。如果没有要使用的“抛光”函数,请使用 None。有关更多详细信息,请参见注释。
- dispbool, 可选
设置为 True 以打印来自 finish 可调用对象的收敛消息。
- 工人int 或类似映射的可调用对象,可选
如果 workers 是一个整数,网格将被细分为 workers 部分并在并行中进行评估(使用
multiprocessing.Pool
)。提供 -1 以使用进程可用的所有核心。或者提供一个类似映射的可调用对象,例如 multiprocessing.Pool.map 用于并行评估网格。此评估按照workers(func, iterable)
进行。要求 func 是可序列化的。Added in version 1.3.0.
- 返回:
- x0ndarray
一个包含目标函数在其最小值处的点的坐标的1维数组。(返回哪个点的说明见 Note 1。)
- fval浮动
函数在点 x0 处的值。(当 full_output 为 True 时返回。)
- 网格元组
评估网格的表示。它的长度与 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。