scipy.optimize.minimize 选择不受限制的参数
scipy.optimize.minimize choosing parameters that defy constraints
我正在 运行 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
非常接近其上限,以便对数变得不确定。
是什么导致我的代码失败?
两种形式的约束,即 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")
我正在 运行 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
非常接近其上限,以便对数变得不确定。
是什么导致我的代码失败?
两种形式的约束,即 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")