Scipy 优化器 explodes/diverges 改变指定参数的方式
Scipy optimizer explodes/diverges at changing way of specifying parameters
我有一个负对数似然函数要最小化。我想将观察数组设置为函数的参数来优化而不是直接进入函数,但奇怪的是,优化器爆炸了。我有兴趣发现这是为什么,并最终了解需要更改什么才能拥有收敛优化器。
我以这种方式将观察值设置为函数的参数:
mn 代表 scipy.optimize.minimize
def f(x, d ):
alfa = x[0]
lambda_ = x[1]
return - n * np.log(alfa) * lambda_ + alfa * sum(d)
n = 2000 #number of observations
y = np.random.exponential(2 , n) #vector of observations
res = mn(f, x0 = [2,1/2], args = y)
结果是:
fun: nan
hess_inv: array([[0.67448386, 0.61331579],
[0.61331579, 0.55866767]])
jac: array([nan, nan])
message: 'Desired error not necessarily achieved due to precision loss.'
nfev: 452
nit: 2
njev: 113
status: 2
success: False
x: array([-2947.66055677, -2680.19131049])
而如果我在内部设置观察值并且 不作为参数
def f(x):
alfa = x[0]
lambda_ = x[1]
n = 2000
y = np.random.exponential(2 , n)
return - n * np.log(alfa) * lambda_ + alfa * sum(y)
mn(f, x0 = [2,2])
我得到了一些很好的估计
fun: 5072.745186459168
hess_inv: array([[ 3.18053796e-16, -1.07489375e-15],
[-1.07489371e-15, 3.63271745e-15]])
jac: array([1.65160556e+10, 1.11412293e+10])
message: 'Desired error not necessarily achieved due to precision loss.'
nfev: 122
nit: 3
njev: 28
status: 2
success: False
x: array([1.99998635, 1.99999107])
即使优化器不认为它是成功的。
第 1 部分
首先,让我回答这个明确的问题:
Could someone please explain me why, and eventually tell me what to change to have a converging optimizer ?
函数- n * np.log(alfa) * lambda_ + alfa * sum(d)
无法最小化。对于给定的有限 lambda,该函数在 alpha 中具有唯一的最小值,因为项 -log(alfa)
和 +alfa
以不同的速率增长。现在让我们单独来看一下 lambda。该函数在 lambda 中是线性的,因此仅在 lambda_ = +inf
.
处具有最小值
优化器正在尝试将 lambda 增加到无穷大,但增加 lambda 也会增加 alfa 最小值,并且事情会迅速发散...
至少理论上是这样。实际上,优化器迟早会尝试负 alpha,这会导致对数无效。出于某种原因,这使得优化器认为进一步降低 alpha 是个好主意。
实现收敛优化器的两个步骤:
- 使用可以最小化的成本函数(例如固定 lambda,或对大的 lambda 进行惩罚)
- 告诉优化器 alpha 不能为负
bounds=[(0, np.inf), (-np.inf, np.inf)])
第 2 部分
"not as parameter" 场景中发生的情况完全不同。和
y = np.random.exponential(2 , n)
每次调用成本函数都会生成新的随机值。这使得成本函数 随机 但优化器期望 确定性 函数。
每次优化器调用该函数时,它都会得到一个部分随机的结果。这使优化器感到困惑,并且在三次迭代 (nit: 3
) 之后它放弃了。分三步,估计与初始值的偏差很小。
我有一个负对数似然函数要最小化。我想将观察数组设置为函数的参数来优化而不是直接进入函数,但奇怪的是,优化器爆炸了。我有兴趣发现这是为什么,并最终了解需要更改什么才能拥有收敛优化器。
我以这种方式将观察值设置为函数的参数: mn 代表 scipy.optimize.minimize
def f(x, d ):
alfa = x[0]
lambda_ = x[1]
return - n * np.log(alfa) * lambda_ + alfa * sum(d)
n = 2000 #number of observations
y = np.random.exponential(2 , n) #vector of observations
res = mn(f, x0 = [2,1/2], args = y)
结果是:
fun: nan
hess_inv: array([[0.67448386, 0.61331579],
[0.61331579, 0.55866767]])
jac: array([nan, nan])
message: 'Desired error not necessarily achieved due to precision loss.'
nfev: 452
nit: 2
njev: 113
status: 2
success: False
x: array([-2947.66055677, -2680.19131049])
而如果我在内部设置观察值并且 不作为参数
def f(x):
alfa = x[0]
lambda_ = x[1]
n = 2000
y = np.random.exponential(2 , n)
return - n * np.log(alfa) * lambda_ + alfa * sum(y)
mn(f, x0 = [2,2])
我得到了一些很好的估计
fun: 5072.745186459168
hess_inv: array([[ 3.18053796e-16, -1.07489375e-15],
[-1.07489371e-15, 3.63271745e-15]])
jac: array([1.65160556e+10, 1.11412293e+10])
message: 'Desired error not necessarily achieved due to precision loss.'
nfev: 122
nit: 3
njev: 28
status: 2
success: False
x: array([1.99998635, 1.99999107])
即使优化器不认为它是成功的。
第 1 部分
首先,让我回答这个明确的问题:
Could someone please explain me why, and eventually tell me what to change to have a converging optimizer ?
函数- n * np.log(alfa) * lambda_ + alfa * sum(d)
无法最小化。对于给定的有限 lambda,该函数在 alpha 中具有唯一的最小值,因为项 -log(alfa)
和 +alfa
以不同的速率增长。现在让我们单独来看一下 lambda。该函数在 lambda 中是线性的,因此仅在 lambda_ = +inf
.
优化器正在尝试将 lambda 增加到无穷大,但增加 lambda 也会增加 alfa 最小值,并且事情会迅速发散...
至少理论上是这样。实际上,优化器迟早会尝试负 alpha,这会导致对数无效。出于某种原因,这使得优化器认为进一步降低 alpha 是个好主意。
实现收敛优化器的两个步骤:
- 使用可以最小化的成本函数(例如固定 lambda,或对大的 lambda 进行惩罚)
- 告诉优化器 alpha 不能为负
bounds=[(0, np.inf), (-np.inf, np.inf)])
第 2 部分
"not as parameter" 场景中发生的情况完全不同。和
y = np.random.exponential(2 , n)
每次调用成本函数都会生成新的随机值。这使得成本函数 随机 但优化器期望 确定性 函数。
每次优化器调用该函数时,它都会得到一个部分随机的结果。这使优化器感到困惑,并且在三次迭代 (nit: 3
) 之后它放弃了。分三步,估计与初始值的偏差很小。