оптимизатор scipy взрывается / расходится при изменении способа задания параметров - PullRequest
0 голосов
/ 14 марта 2019

У меня есть функция отрицательного логарифмического правдоподобия, чтобы минимизировать. Я хочу установить массив наблюдений как параметр функции для оптимизации, а не напрямую в функцию, но, как ни странно, оптимизатор взрывается. Может кто-нибудь объяснить мне, почему, и в конечном итоге сказать мне, что изменить, чтобы иметь сходящийся оптимизатор? Я установил наблюдения как параметры функции следующим образом: 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 голосов
/ 14 марта 2019

Часть 1

Сначала позвольте мне ответить на явный вопрос:

Может кто-нибудь объяснить, почему, и, в конце концов, сказать, что нужно изменить, чтобы получить конвергентный оптимизатор?

Функция - n * np.log(alfa) * lambda_ + alfa * sum(d) не может быть свернута. Для данной конечной лямбды функция имеет уникальный минимум по альфа-каналу, поскольку члены -log(alfa) и +alfa растут с разной скоростью. Теперь давайте посмотрим на лямбду изолированно. Функция является линейной в лямбде и поэтому имеет минимум только при lambda_ = +inf.

Оптимизатор пытается увеличить лямбду к бесконечности, но увеличение лямбды также увеличивает альфа-минимум, и вещи быстро расходятся ...

По крайней мере, в теории. На практике рано или поздно оптимизатор пробует отрицательную альфа, что приводит к тому, что логарифм становится недействительным. По какой-то причине это заставляет оптимизатора думать, что это хорошая идея, чтобы уменьшить альфа еще больше.

Два шага для достижения конвергентного оптимизатора:

  1. Используйте функцию стоимости, которую можно свести к минимуму (например, сделайте фиксированную лямбду или наложите штраф на большие лямбды)
  2. Скажите, что альфа оптимизатора не должен быть отрицательным с bounds=[(0, np.inf), (-np.inf, np.inf)])

Часть 2

То, что происходит в сценарии «не как параметр», это совершенно другая история. С y = np.random.exponential(2 , n) функция стоимости генерирует новые случайные значения каждый раз, когда она вызывается. Это делает функцию стоимости стохастической , но оптимизатор ожидает детерминированную функцию.

Каждый раз, когда оптимизатор вызывает функцию, он получает частично случайный результат. Это сбивает с толку оптимизатор и после трех итераций (nit: 3) он сдается. В три этапа оценка незначительно отклонялась от начальных значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...