scipy优化器在更改指定参数的方式时爆炸/发散

时间:2019-03-14 09:43:34

标签: python optimization scipy log-likelihood

我具有负面的对数似然函数以将其最小化。我想将观察值数组设置为函数的 参数 来进行优化,而不是直接进入函数,但奇怪的是,优化器会爆炸。有人可以向我解释原因,最后告诉我要使用聚合优化器进行哪些更改吗? 我通过这种方式将观察值设置为函数的参数: 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 个答案:

答案 0 :(得分:0)

第1部分

首先,让我回答一个明确的问题:

  

有人可以向我解释原因,最后告诉我要使用聚合优化器进行哪些更改吗?

函数class TestSample { @Mock private lateinit var filmsPresenter: GetFlimsContract.Presenter @Mock private lateinit var filmsView: GetFlimsContract.View private lateinit var api: API @Mock private lateinit var disposable: Disposable @Mock lateinit var repoTest: RepoTest @Before fun setup() { RxAndroidPlugins.setMainThreadSchedulerHandler { scheduler -> Schedulers.trampoline() } RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler -> Schedulers.trampoline() } RxJavaPlugins.setIoSchedulerHandler { t -> Schedulers.trampoline() } MockitoAnnotations.initMocks(this) repoTest = Mockito.mock(RepoTest::class.java) filmsView = Mockito.mock(GetFlimsContract.View ::class.java) filmsPresenter = FlimsPresenter(filmsView,repoTest ) } @Test fun `should lod item into views`() { Mockito.`when`(repoTest.filmm()).thenReturn(Observable.just(Response("","",7, listOf(ResultsItem())))) filmsPresenter.fetchFilms() Mockito.verify(filmsView).showLoader(true) Mockito.verify(filmsView).setAdapter(anyList()) Mockito.verify(filmsView).showLoader(false) } @Test fun `should show error if network call fails`(){ Mockito.`when`(repoTest.filmm()).thenReturn(Observable.error(Exception("t"))) filmsPresenter.fetchFilms() Mockito.verify(filmsView).showLoader(true) Mockito.verify(filmsView).showError("t") Mockito.verify(filmsView).showLoader(false) } } 不能被最小化。对于给定的有限lambda,该函数在alpha中具有唯一的最小值,因为项- n * np.log(alfa) * lambda_ + alfa * sum(d)-log(alfa)的增长率不同。现在让我们单独看一下lambda。该函数在lambda中是线性的,因此仅在+alfa处具有最小值。

优化器正在尝试将lambda增大到无穷大,但是增加lambda也会增加alfa-minimum,并且事情很快会发散...

至少在理论上。实际上,优化器迟早会尝试使用负的alpha,这会使对数变为无效。由于某种原因,这使优化器认为进一步降低alpha值是一个好主意。

实现融合优化器的两个步骤:

  1. 使用可以最小化的成本函数(例如,固定lambda或对较大的lambda进行惩罚)
  2. 告诉优化器Alpha值不能与lambda_ = +inf相同

第2部分

“不作为参数”方案中发生的事情是完全不同的故事。用 bounds=[(0, np.inf), (-np.inf, np.inf)])每次调用成本函数都会生成新的随机值。这使成本函数成为随机函数,但优化程序需要一个确定性函数。

每次优化器调用该函数时,它都会得到部分随机的结果。这会使优化器感到困惑,并且在三遍迭代(y = np.random.exponential(2 , n))之后它放弃了。在三个步骤中,估算值仅与初始值略有偏差。