scipy.optimize.minimize 选择无视约束的参数

Posted

技术标签:

【中文标题】scipy.optimize.minimize 选择无视约束的参数【英文标题】:scipy.optimize.minimize choosing parameters that defy constraints 【发布时间】:2022-01-15 09:12:52 【问题描述】:

我正在运行 scipy.optimize.minimize 试图最大化 Gompertz 分布上左截断数据的可能性。由于数据在1 处被左截断,我得到这种可能性:

# for a single point x_i, the left-truncated log-likelihood is:
#   ln(tau) + tau*(ln(theta) - ln(x_i)) - (theta / x_i) ** tau - ln(x_i) - ln(1 - exp(-(theta / d) ** tau))
def to_minimize(args, data, d=1):
  theta, tau = args
  if tau <= 0 or theta <= 0 or theta / d < 0 or np.exp(-(theta / d) ** tau) >= 1:
    print('ERROR')
  term1 = len(data) * (np.log(tau) + tau * np.log(theta) - np.log(1 - np.exp(-(theta / d) ** tau)))
  term2 = 0
  for x in data:
    term2 += (-(tau + 1) * np.log(x)) - (theta / x) ** tau
  return term1 + term2

这将在if 语句为真的所有情况下失败。换句话说,tautheta 必须是严格正数,并且theta ** tau 必须离0 足够远,以便np.exp(-theta ** tau)1“足够远”,因为否则对数将是未定义的。

这些是我这样定义的约束。我将符号与dict 一起使用,而不是NonlinearConstraints 对象,因为这种方法似乎接受严格的不等式(np.exp(-x[0] ** x[1]) 必须严格小于1)。也许我误解了这方面的文档。

def constraints(x):
  return [1 - np.exp(-(x[0]) ** x[1])]

为了最大化可能性,我最小化负面可能性。

opt = minimize(lambda args: -to_minimize(args, data),
               x0=np.array((1, 1)), 
               constraints='type': 'ineq', 'fun': constraints,
               bounds=np.array([(1e-15, 10), (1e-15, 10)]))

在我看来,这两个参数不应该以我的代码失败的方式选择。然而,该算法试图将theta 移动到非常靠近其下限,并将tau 移动到非常靠近其上限,因此对数变得不确定。

是什么让我的代码失败了?

【问题讨论】:

需要注意的是,如果我稍微轻推一下边界,我已经检查过问题是否仍然存在。即使我在约束函数中使用[(1 - 1e-10) - np.exp(-(x[0]) ** x[1])],问题仍然存在。 能否提供一些data 来重现问题? 【参考方案1】:

两种形式的约束,即NonlinearConstraintdict 约束都不支持严格不等式。因此,通常使用g(x) &gt;= c + Ɛ 来模拟严格的不等式g(x) &gt; c,其中Ɛ 是一个足够小的数字。

另请注意,不能保证每次迭代都位于可行区域内。在内部,大多数方法都试图通过简单的边界裁剪将其带回可行区域。如果这不起作用,您可以尝试NonlinearConstraints keep_feasible 选项,然后使用trust-constr 方法:

import numpy as np
from scipy.optimize import NonlinearConstraint, minimize

def con_fun(x):
    return 1 - np.exp(-(x[0]) ** x[1])

# 1.0e-8 <= con_fun <= np.inf
con = NonlinearConstraint(con_fun, 1.0e-8, np.inf, keep_feasible=True)

x0 = np.array((1., 1.))
bounds = np.array([(1e-5, 10), (1e-5, 10)])

opt = minimize(lambda args: -to_minimize(args, data),
               x0=x0, constraints=(con,),
               bounds=bounds, method="trust-constr")

【讨论】:

这很有趣,我不知道这些细节,所以谢谢。我将尝试继续使用keep_feasible 选项和trust-constr 方法。

以上是关于scipy.optimize.minimize 选择无视约束的参数的主要内容,如果未能解决你的问题,请参考以下文章

当 scipy.optimize.minimize 可能用于相同的事情时,为啥 scipy.optimize.least_squares 存在?

`scipy.optimize.minimize` 中的 Jacobian 和 Hessian 输入

scipy.optimize.minimize 选择无视约束的参数

为啥 scipy.optimize.minimize (默认)在不使用 Skyfield 的情况下报告成功?

打印选择的 scipy.optimize.minimize 方法

将 scipy.optimize.minimize 限制为整数值