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 是个好主意。

实现收敛优化器的两个步骤:

  1. 使用可以最小化的成本函数(例如固定 lambda,或对大的 lambda 进行惩罚)
  2. 告诉优化器 a​​lpha 不能为负 bounds=[(0, np.inf), (-np.inf, np.inf)])

第 2 部分

"not as parameter" 场景中发生的情况完全不同。和 y = np.random.exponential(2 , n) 每次调用成本函数都会生成新的随机值。这使得成本函数 随机 但优化器期望 确定性 函数。

每次优化器调用该函数时,它都会得到一个部分随机的结果。这使优化器感到困惑,并且在三次迭代 (nit: 3) 之后它放弃了。分三步,估计与初始值的偏差很小。