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
语句为真的所有情况下失败。换句话说,tau
和theta
必须是严格正数,并且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】:
两种形式的约束,即NonlinearConstraint
和dict
约束都不支持严格不等式。因此,通常使用g(x) >= c + Ɛ
来模拟严格的不等式g(x) > c
,其中Ɛ
是一个足够小的数字。
另请注意,不能保证每次迭代都位于可行区域内。在内部,大多数方法都试图通过简单的边界裁剪将其带回可行区域。如果这不起作用,您可以尝试NonlinearConstraint
s 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 的情况下报告成功?