36

我正在尝试使用scipy.optimize函数来找到具有多个参数的复杂函数的全局最小值。scipy.optimize.minimize似乎做得最好,即“Nelder-Mead”方法。但是,它往往会进入参数域之外的区域(将负值分配给只能为正的参数),因此在这种情况下会返回错误。有没有办法限制函数本身的参数范围?scipy.optimize.minimize或者可能在其他scipy.optimize功能中?

我找到了以下建议:

当参数超出允许范围时,返回一个非常大的数字(远离要拟合的数据)。这将(希望)严重惩罚这种参数选择,从而curve_fit将其他一些可接受的参数集确定为最优。

在上一个答案中给出,但在我的情况下,该过程将花费大量计算时间。

4

4 回答 4

41

minimize函数有一个bounds参数,可用于在使用 L-BFGS-B、TNC、COBYLA 或 SLSQP 方法时限制每个变量的界限。

例如,

import scipy.optimize as optimize

fun = lambda x: (x[0] - 1)**2 + (x[1] - 2.5)**2
res = optimize.minimize(fun, (2, 0), method='TNC', tol=1e-10)
print(res.x)
# [ 1.          2.49999999]

bnds = ((0.25, 0.75), (0, 2.0))
res = optimize.minimize(fun, (2, 0), method='TNC', bounds=bnds, tol=1e-10)
print(res.x)
# [ 0.75  2.  ]
于 2013-10-08T10:29:12.113 回答
31

Nelder-Mead 求解器不支持约束优化,但还有其他几个支持。

TNC 和 L-BFGS-B 都只支持有界约束(例如x[0] >= 0),这对您的情况应该没问题。COBYLA 和 SLSQP 更加灵活,支持边界、等式和基于不等式的约束的任意组合。

您可以通过查看独立函数的文档来找到有关求解器的更多详细信息,scipy.optimize.fmin_slsqp例如method='SLSQP'.

您可以在此处查看我之前的答案,了解使用 SLSQP 进行约束优化的示例。

于 2013-10-08T10:30:16.130 回答
8

您正在寻找的论点是:constraints这是传递给scipy.minimize. 滚动您自己的 lambda 函数,该函数接收要约束的参数,如下所示:

#A function to define the space where scipy.minimize should 
#confine its search:
def apply_sum_constraint(inputs):
    #return value must come back as 0 to be accepted
    #if return value is anything other than 0 it's rejected
    #as not a valid answer.
    total = 50.0 - np.sum(inputs)
    return total

my_constraints = ({'type': 'eq', "fun": apply_sum_constraint })
result = spo.minimize(f, 
                      guess, 
                      method='SLSQP', 
                      args=(a, b, c),
                      bounds=((-1.0, 1.0), (-1.0, 1.0)),
                      options={'disp': True},
                      constraints=my_constraints)

上面的示例断言,最后一个搜索项目附近的所有新候选者最好加起来为 50。更改该方法以定义允许的搜索空间,并且 scipy.minimize 函数在考虑这些答案时不会浪费任何能量。

于 2016-09-06T00:18:23.930 回答
1

我知道这是游戏后期,但也许看看mystic。您可以将任意 python 函数用作惩罚函数,或应用边界约束等等……在任何优化器上(包括来自 的算法scipy.optimize.fmin)。

https://github.com/uqfoundation/mystic

于 2015-07-07T02:09:00.323 回答