Scipy 最小化约束函数

Posted

技术标签:

【中文标题】Scipy 最小化约束函数【英文标题】:Scipy minimize constrained function 【发布时间】:2016-05-27 17:27:26 【问题描述】:

我正在解决以下优化问题:

使用此 Python 代码:

from scipy.optimize import minimize
import math

def f(x):
    return math.log(x[0]**2 + 1) + x[1]**4 + x[0]*x[2]

x0 = [0, 0, 0]

cons=('type': 'ineq',
       'fun': lambda x: x[0]**3 - x[1]**2 - 1,
      'type': 'ineq',
       'fun': lambda x: x[0],
      'type': 'ineq',
       'fun': lambda x: x[2])

res = minimize(f, x0, constraints=cons)
print res

我遇到了一个错误

消息:'不等式约束不兼容'

什么会导致这个错误?

【问题讨论】:

FWIW,在另一个问题***.com/questions/55543140/… 我发现降低容忍度以帮助options='ftol':1e-15 但在这里似乎没有帮助。但是在你的情况下,我确实发现初始值确实很重要,当初始值太远时,SLSQPtrust-const 都不适合我。 【参考方案1】:

问题似乎与您最初的猜测有关。如果我将您的起始值更改为

x0 = [1.0, 1.0, 1.0]

那么你的代码会执行得很好(至少在我的机器上)

Win32 上的 Python 3.5.1(v3.5.1:37a07cee5969,2015 年 12 月 6 日,01:54:25)[MSC v.1900 64 位 (AMD64)]

 message: 'Optimization terminated successfully.'
    njev: 10
     jac: array([ 1.,  0.,  1.,  0.])
     fun: 0.6931471805582502
     nit: 10
  status: 0
       x: array([  1.00000000e+00,  -1.39724765e-06,   1.07686548e-14])
 success: True
    nfev: 51

【讨论】:

它有效。您知道我的 x0 无法使用它的原因吗? @Rextuz 如果我没记错的话,你最初的猜测不满足约束,这将是函数失败的一个很好的理由。然而,Cory 最初的猜测似乎也不满足第一个约束。【参考方案2】:

Scipy 的优化模块有很多选项。请参阅the documentation 或this tutorial。由于您没有在此处指定方法,因此它将使用顺序最小二乘编程 (SLSQP)。或者,您可以使用 Trust-Region Constrained Algorithm (trust-const)。

对于这个问题,我发现trust-const 似乎比SLSQP 对起始值更健壮,处理从[-2,-2,-2][10,10,10] 的起始值,尽管负的初始值会导致迭代次数增加,正如你所说预计。低于-2 的负值超过了最大迭代次数,尽管我怀疑如果增加最大迭代次数可能仍会收敛,尽管为x1x3 指定负值有点愚蠢,当然,我只是这样做了解它对一系列起始值的稳健性。

SLSQPtrust-const 的规范在概念上是相同的,但语法略有不同(特别注意NonlinearConstraint 的使用)。

from scipy.optimize import minimize, NonlinearConstraint, SR1

def f(x):
    return math.log(x[0]**2 + 1) + x[1]**4 + x[0]*x[2]

constr_func = lambda x: np.array( [ x[0]**3 - x[1]**2 - 1,
                                    x[0],
                                    x[2] ] )

x0=[0.,0.,0.]

nonlin_con = NonlinearConstraint( constr_func, 0., np.inf )

res = minimize( f, x0, method='trust-constr',
                jac='2-point', hess=SR1(),
                constraints = nonlin_con )

以下是结果,为简洁起见进行了编辑:

    fun: 0.6931502233468916
message: '`gtol` termination condition is satisfied.'
      x: array([1.00000063e+00, 8.21427026e-09, 2.40956900e-06])

请注意,函数值和 x 值与@CoryKramer 的答案相同。 x 数组乍一看可能表面上有所不同,但两个答案都为[1, 0, 0]

【讨论】:

以上是关于Scipy 最小化约束函数的主要内容,如果未能解决你的问题,请参考以下文章

Scipy 最小化:如何将参数传递给目标和约束

scipy中的最小化,找到N维标量函数的所有局部最小值的算法

Python最小化函数:将附加参数传递给约束字典

Python中的约束最小二乘估计

使用 Scipy 在 Python 中进行约束优化

当我尝试使用 for 循环设置约束时,Scipy 优化未运行