本文简要介绍 python 语言中 scipy.optimize.shgo
的用法。
用法:
scipy.optimize.shgo(func, bounds, args=(), constraints=None, n=100, iters=1, callback=None, minimizer_kwargs=None, options=None, sampling_method='simplicial', *, workers=1)#
使用 SHG 优化查找函数的全局最小值。
SHGO 代表“单纯同调全局优化”。
- func: 可调用的
要最小化的目标函数。必须采用
f(x, *args)
的形式,其中x
是一维数组形式的参数,而args
是完全指定函数所需的任何其他固定参数的元组。- bounds: 序列或
Bounds
变量的界限。有两种方法可以指定边界:
Bounds
类的实例。序列
(min, max)
中每个元素的对x.
- args: 元组,可选
完全指定目标函数所需的任何其他固定参数。
- constraints: {Constraint, dict} 或 {Constraint, dict} 列表,可选
约束定义。仅适用于 COBYLA、SLSQP 和trust-constr。有关指定约束的更多详细信息,请参阅教程 [5]。
注意
当前仅 COBYLA、SLSQP 和 trust-constr 局部最小化方法支持约束参数。如果局部优化问题中使用的
constraints
序列未在minimizer_kwargs
中定义,并且使用约束方法,则将使用全局constraints
。 (在minimizer_kwargs
中定义constraints
序列意味着不会添加constraints
,因此如果需要添加等式约束等,则constraints
中的不等式函数也需要添加到minimizer_kwargs
中)。 COBYLA 仅支持不平等约束。- n: 整数,可选
构造单纯复形时使用的采样点数量。对于默认的
simplicial
采样方式 生成2**dim + 1个采样点,而不是默认的n=100。对于所有其他指定值n生成采样点。为了sobol
,halton
和其他任意sampling_methods n=100或者生成其他指定数量的采样点。- iters: 整数,可选
用于构造单纯复形的迭代次数。默认值为 1。
- callback: 可调用的,可选的
每次迭代后调用,如
callback(xk)
,其中xk
是当前参数向量。- minimizer_kwargs: 字典,可选
要传递给最小化器的额外关键字参数
scipy.optimize.minimize
一些重要的选项可能是:- method str
The minimization method. If not given, chosen to be one of BFGS, L-BFGS-B, SLSQP, depending on whether or not the problem has constraints or bounds.
- args tuple
Extra arguments passed to the objective function (
func
) and its derivatives (Jacobian, Hessian).
- options dict, optional
Note that by default the tolerance is specified as
{ftol: 1e-12}
- options: 字典,可选
求解器选项字典。为全局例程指定的许多选项也传递给scipy.optimize.minimize 例程。也传递给本地例程的选项标有“(L)”。
停止条件,如果满足任何指定条件,算法将终止。但是,默认算法不需要指定任何内容:
- maxfev int (L)
可行域中函数评估的最大数量。 (请注意,只有支持此选项的方法才会在精确指定的值处终止例程。否则,标准将仅在全局迭代期间终止)
- f_min
指定最小目标函数值(如果已知)。
- f_tol float
停止准则中 f 值的精度目标。请注意,如果全局例程中的采样点在此容差范围内,全局例程也将终止。
- maxiter int
要执行的最大迭代次数。
- maxev int
要执行的最大抽样评估次数(包括在不可行点中搜索)。
- maxtime float
允许的最大处理运行时间
- minhgrd int
最小同源组等级差异。在每次迭代期间(近似地)计算目标函数的同调群。该组的排名与目标函数中局部凸子域的数量一一对应(在足够的采样点之后,每个子域都包含唯一的全局最小值)。如果
maxhgrd
指定迭代之间的 hgr 差异为 0,则算法将终止。
目标函数知识:
- symmetry list or bool
指定目标函数是否包含对称变量。在完全对称的情况下,搜索空间(以及因此的性能)最多减少 O(n!) 倍。如果指定 True,则所有变量将设置为与第一个变量对称。默认设置为 False。
例如: f(x) = (x_1 + x_2 + x_3) + (x_4)**2 + (x_5)**2 + (x_6)**2
在此方程中,x_2 和 x_3 与 x_1 对称,而 x_5 和 x_6 与 x_4 对称,这可以向求解器指定为:
- 对称性 = [0, # 变量 1
0, # 与变量 1 对称 0, # 与变量 1 对称 3, # 变量 4 3, # 与变量 4 对称 3, # 与变量 4 对称 ]
- jac bool or callable, optional
目标函数的雅可比(梯度)。仅适用于 CG、BFGS、Newton-CG、L-BFGS-B、TNC、SLSQP、dogleg、trust-ncg。如果
jac
是一个布尔值并且是 True,fun
假设与目标函数一起返回梯度。如果为 False,梯度将以数值方式估计。jac
也可以是返回目标梯度的可调用对象。在这种情况下,它必须接受与fun
. (传递给scipy.optimize.minmize自动地)
- hess, hessp callable, optional
目标函数的 Hessian(二阶导数矩阵)或目标函数的 Hessian 乘以任意向量 p。仅适用于Newton-CG、狗腿、trust-ncg。仅其中之一
hessp
或者hess
需要给予。如果hess
提供,然后hessp
将被忽略。如果两者都没有hess
也不hessp
提供,则 Hessian 乘积将使用有限差分来近似jac
.hessp
必须计算 Hessian 乘以任意向量。 (传递给scipy.optimize.minmize自动地)
算法设置:
- minimize_every_iter bool
如果为 True,那么有希望的全局采样点将在每次迭代时传递给局部最小化例程。如果为 True,则仅运行最终的最小化器池。默认为 True。
- local_iter int
每次迭代只评估几个最佳的最小化池候选者。如果为 False,则所有潜在点都将传递给局部最小化例程。
- infty_constraints bool
如果为真,那么在可行域之外生成的任何采样点都将被保存,并赋予目标函数值
inf
。如果为 False,那么这些点将被丢弃。在找到全局最小值之前,使用此函数可能会导致函数评估的性能更高,指定 False 将使用更少的内存,但性能会略有下降。默认为真。
回馈:
- disp bool (L)
设置为 True 以打印收敛消息。
- sampling_method: str 或函数,可选
当前内置的采样方法选项是
halton
,sobol
和simplicial
.默认simplicial
提供了在有限时间内收敛到全局最小值的理论保证。halton
和sobol
方法在采样点生成方面更快,但以损失保证收敛为代价。它更适合大多数收敛速度相对较快的“easier” 问题。用户定义的采样函数必须接受两个参数n
维度采样点dim
每次调用并输出具有形状的采样点数组n x dim.- workers: int 或 map-like 可调用,可选
并行采样并运行本地串行最小化。提供 -1 以使用所有可用的 CPU 内核,或提供 int 以使用多个进程(使用
multiprocessing.Pool
)。或者提供 map-like 可调用,例如多处理.Pool.map用于并行评估。本次评价按如下方式进行
workers(func, iterable)
.要求函数可以 pickle 。
- res: OptimizeResult
优化结果表示为
OptimizeResult
对象。重要的属性是:x
对应于全局最小值的解数组,fun
全局解处的函数输出,xl
局部最小值解的有序列表,funl
对应局部解处的函数输出,success
一个布尔标志,指示优化器是否成功退出,message
说明终止的原因,nfev
包括采样调用在内的目标函数评估总数,nlfev
目标函数评估总数从所有本地搜索优化中,nit
全局例程执行的迭代次数。
参数 ::
返回 ::
注意:
使用单纯同调全局优化的全局优化[1]。适用于解决通用 NLP 和黑盒优化问题到全局最优(低维问题)。
一般来说,优化问题的形式如下:
minimize f(x) subject to g_i(x) >= 0, i = 1,...,m h_j(x) = 0, j = 1,...,p
其中 x 是一个或多个变量的向量。
f(x)
是目标函数R^n -> R
,g_i(x)
是不等式约束,h_j(x)
是等式约束。或者,也可以使用 bounds 参数指定 x 中每个元素的下限和上限。
虽然 SHGO 的大多数理论优势仅在
f(x)
是 Lipschitz 平滑函数时得到证明,但该算法也被证明在f(x)
是非连续、非凸的更一般情况下收敛到全局最优如果使用默认采样方法 [1],则不平滑。可以使用传递给
scipy.optimize.minimize
的minimizer_kwargs
参数指定本地搜索方法。默认情况下,使用SLSQP
方法。通常,如果为问题定义了不等式约束,则建议使用SLSQP
或COBYLA
局部最小化,因为其他方法不使用约束。halton
和sobol
方法点是使用scipy.stats.qmc
生成的。可以使用任何其他 QMC 方法。参考:
[1] (1,2)Endres, SC, Sandrock, C, Focke, WW (2018) “一种简单的lipschitz 优化同源算法”,全局优化杂志。
[2]Joe, SW 和 Kuo, FY (2008) “使用更好的二维投影构建 Sobol 序列”,SIAM J. Sci。计算。 30, 2635-2654。
[3] (1,2)Hock, W 和 Schittkowski, K (1981)“非线性编程代码的测试示例”,经济学和数学系统讲义,187。Springer-Verlag,纽约。http://www.ai7.uni-bayreuth.de/test_problem_coll.pdf
[4]威尔士,DJ (2015) “透视:从势能景观中洞察反应坐标和动力学”,化学物理学杂志,142(13),2015。
例子:
首先考虑最小化 Rosenbrock 函数的问题,
rosen
:>>> from scipy.optimize import rosen, shgo >>> bounds = [(0,2), (0, 2), (0, 2), (0, 2), (0, 2)] >>> result = shgo(rosen, bounds) >>> result.x, result.fun (array([1., 1., 1., 1., 1.]), 2.920392374190081e-18)
请注意,边界确定目标函数的维度,因此是必需的输入,但是您可以使用
None
或将转换为大浮点数的对象(如np.inf
)指定空边界。>>> bounds = [(None, None), ]*4 >>> result = shgo(rosen, bounds) >>> result.x array([0.99999851, 0.99999704, 0.99999411, 0.9999882 ])
接下来,我们考虑 Eggholder 函数,这是一个具有多个局部最小值和一个全局最小值的问题。我们将演示参数的使用和
shgo
的函数。 (https://en.wikipedia.org/wiki/Test_functions_for_optimization)>>> import numpy as np >>> def eggholder(x): ... return (-(x[1] + 47.0) ... * np.sin(np.sqrt(abs(x[0]/2.0 + (x[1] + 47.0)))) ... - x[0] * np.sin(np.sqrt(abs(x[0] - (x[1] + 47.0)))) ... ) ... >>> bounds = [(-512, 512), (-512, 512)]
shgo
具有内置的低差异采样序列。首先,我们将输入 64 个初始采样点索博尔顺序:>>> result = shgo(eggholder, bounds, n=64, sampling_method='sobol') >>> result.x, result.fun (array([512. , 404.23180824]), -959.6406627208397)
shgo
还返回找到的任何其他局部最小值,可以使用以下命令调用:>>> result.xl array([[ 512. , 404.23180824], [ 283.0759062 , -487.12565635], [-294.66820039, -462.01964031], [-105.87688911, 423.15323845], [-242.97926 , 274.38030925], [-506.25823477, 6.3131022 ], [-408.71980731, -156.10116949], [ 150.23207937, 301.31376595], [ 91.00920901, -391.283763 ], [ 202.89662724, -269.38043241], [ 361.66623976, -106.96493868], [-219.40612786, -244.06020508]])
>>> result.funl array([-959.64066272, -718.16745962, -704.80659592, -565.99778097, -559.78685655, -557.36868733, -507.87385942, -493.9605115 , -426.48799655, -421.15571437, -419.31194957, -410.98477763])
这些结果在存在许多全局最小值并且需要其他全局最小值的值或局部最小值可以提供对系统的洞察力的应用中很有用(例如物理化学中的形态[4])。
如果我们想找到更多的局部最小值,我们可以增加采样点的数量或迭代次数。我们将采样点的数量增加到 64 个,并将迭代次数从默认值 1 增加到 3。使用
simplicial
这将为我们提供 64 x 3 = 192 个初始采样点。>>> result_2 = shgo(eggholder, ... bounds, n=64, iters=3, sampling_method='sobol') >>> len(result.xl), len(result_2.xl) (12, 23)
请注意,例如
n=192, iters=1
和n=64, iters=3
之间的区别。在第一种情况下,minimiser 池中包含的有希望的点只被处理一次。在后一种情况下,每 64 个采样点处理一次,总共处理 3 次。为了演示解决具有非线性约束的问题,请考虑以下来自 Hock 和 Schittkowski 问题 73 (cattle-feed) [3] 的示例:
minimize: f = 24.55 * x_1 + 26.75 * x_2 + 39 * x_3 + 40.50 * x_4 subject to: 2.3 * x_1 + 5.6 * x_2 + 11.1 * x_3 + 1.3 * x_4 - 5 >= 0, 12 * x_1 + 11.9 * x_2 + 41.8 * x_3 + 52.1 * x_4 - 21 -1.645 * sqrt(0.28 * x_1**2 + 0.19 * x_2**2 + 20.5 * x_3**2 + 0.62 * x_4**2) >= 0, x_1 + x_2 + x_3 + x_4 - 1 == 0, 1 >= x_i >= 0 for all i
[3] 中给出的近似答案是:
f([0.6355216, -0.12e-11, 0.3127019, 0.05177655]) = 29.894378
>>> def f(x): # (cattle-feed) ... return 24.55*x[0] + 26.75*x[1] + 39*x[2] + 40.50*x[3] ... >>> def g1(x): ... return 2.3*x[0] + 5.6*x[1] + 11.1*x[2] + 1.3*x[3] - 5 # >=0 ... >>> def g2(x): ... return (12*x[0] + 11.9*x[1] +41.8*x[2] + 52.1*x[3] - 21 ... - 1.645 * np.sqrt(0.28*x[0]**2 + 0.19*x[1]**2 ... + 20.5*x[2]**2 + 0.62*x[3]**2) ... ) # >=0 ... >>> def h1(x): ... return x[0] + x[1] + x[2] + x[3] - 1 # == 0 ... >>> cons = ({'type': 'ineq', 'fun': g1}, ... {'type': 'ineq', 'fun': g2}, ... {'type': 'eq', 'fun': h1}) >>> bounds = [(0, 1.0),]*4 >>> res = shgo(f, bounds, n=150, constraints=cons) >>> res message: Optimization terminated successfully. success: True fun: 29.894378159142136 funl: [ 2.989e+01] x: [ 6.355e-01 1.137e-13 3.127e-01 5.178e-02] xl: [[ 6.355e-01 1.137e-13 3.127e-01 5.178e-02]] nit: 1 nfev: 142 nlfev: 35 nljev: 5 nlhev: 0
>>> g1(res.x), g2(res.x), h1(res.x) (-5.062616992290714e-14, -2.9594104944408173e-12, 0.0)
相关用法
- Python SciPy optimize.show_options用法及代码示例
- Python SciPy optimize.rosen_der用法及代码示例
- Python SciPy optimize.line_search用法及代码示例
- Python SciPy optimize.rosen用法及代码示例
- Python SciPy optimize.minimize_scalar用法及代码示例
- Python SciPy optimize.root用法及代码示例
- Python SciPy optimize.fmin用法及代码示例
- Python SciPy optimize.NonlinearConstraint用法及代码示例
- Python SciPy optimize.KrylovJacobian用法及代码示例
- Python SciPy optimize.toms748用法及代码示例
- Python SciPy optimize.linprog_verbose_callback用法及代码示例
- Python SciPy optimize.bracket用法及代码示例
- Python SciPy optimize.milp用法及代码示例
- Python SciPy optimize.diagbroyden用法及代码示例
- Python SciPy optimize.bisect用法及代码示例
- Python SciPy optimize.isotonic_regression用法及代码示例
- Python SciPy optimize.golden用法及代码示例
- Python SciPy optimize.brute用法及代码示例
- Python SciPy optimize.newton用法及代码示例
- Python SciPy optimize.fsolve用法及代码示例
- Python SciPy optimize.Bounds用法及代码示例
- Python SciPy optimize.fixed_point用法及代码示例
- Python SciPy optimize.rosen_hess用法及代码示例
- Python SciPy optimize.nnls用法及代码示例
- Python SciPy optimize.broyden1用法及代码示例
注:本文由纯净天空筛选整理自scipy.org大神的英文原创作品 scipy.optimize.shgo。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。