scipy.optimize.

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 的输出作为其初始猜测的位置参数,并将 bruteargs 输入值作为关键字参数,否则将引发错误。它还可以额外接受 full_output 和/或 disp 作为关键字参数。

brute 假设 finish 函数返回一个 OptimizeResult 对象或一个形式为 (xmin, Jmin, ... , statuscode) 的元组,其中 xmin 是参数的最小化值,Jmin 是目标函数的最小值,“…”可能是其他返回值(brute 不使用),而 statuscodefinish 程序的状态码。

请注意,当 finish 不为 None 时,返回的值是 finish 程序的值,而不是网格点的值。因此,虽然 brute 将其搜索范围限制在输入网格点上,但 finish 程序的结果通常不会与任何网格点重合,并且可能会落在网格边界之外。因此,如果只需要在提供的网格点上找到最小值,请确保传入 finish=None

备注 2: 点网格是一个 numpy.mgrid 对象。对于 bruterangesNs 输入具有以下效果。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。