(оценка максимального правдоподобия) ошибка scipy.optimize.minize - PullRequest
0 голосов
/ 28 марта 2019

Я получил ошибку

  File "C:/Users/", line 70, in <module>
    cal_PIN()
  File "C:/Users/", line 67, in cal_PIN
    cal_likelihood(selling_5_tick, buying_5_tick)
  File "C:/Users/", line 48, in cal_likelihood
    raise valueErr(result.message)
valueErr: Desired error not necessarily achieved due to precision loss.

Я хочу оценить параметр в модели вывода. Функция логарифмического преобразования правдоподобия аналогична приложенной фотографии. Оцениваемые параметры (α, δ, μ, εB, εS). Я кодировал 3 шага для утверждения, чтобы установить начальное значение. Я пытаюсь использовать scipy.optimize.minimize для оценки параметра, применяя оценку максимального правдоподобия.

import time
import scipy
from scipy.optimize import minimize

def f(params, *args):
    # args={k1, k2, k3, kmi, buying_array[i], selling_array[i]}
    k1 = args[0]
    k2 = args[1]
    k3 = args[2]
    kmi = args[3]
    buying_array = args[4]
    selling_array = args[5]

    ini_a, ini_h, ini_eS, ini_eB = params
    return (-1) * (ini_a * ini_h * scipy.exp(k1 - kmi) + ini_a * (1 - ini_h) * scipy.exp(k2 - kmi) + (
                1 - ini_a) * scipy.exp(k3 - kmi) +
                   (buying_array * scipy.log(ini_eB + ini_h) + selling_array * scipy.log(ini_eS + ini_h) - (
                               ini_eB + ini_eS) + kmi))


def cal_likelihood(selling_array, buying_array):
    for ini_a in [0.1, 0.3, 0.5, 0.7, 0.9]:
        for ini_h in [0.1, 0.3, 0.5, 0.7, 0.9]:
            for z in [0.1, 0.3, 0.5, 0.7, 0.9]:
                time.sleep(1)
                i = 0
                for i in range(0, len(buying_array)):
                    ini_eB = z * selling_array[i]

                    cal_u = (buying_array[i] - ini_eB) / (ini_a * (1 - ini_h))
                    ini_eS = selling_array[i] - (ini_a * ini_h * cal_u)

                    k1 = ((-1.0) * (cal_u) - buying_array[i] * scipy.log(1 + (cal_u / ini_eB)))
                    k2 = ((-1.0) * (cal_u) - selling_array[i] * scipy.log(1 + (cal_u / ini_eS)))
                    k3 = (-1.0) * buying_array[i] * scipy.log(1 +
                                                              (cal_u / ini_eB)) - selling_array[i] * scipy.log(
                        1 + (cal_u / ini_eS))
                    kmi = max(k1, k2, k3)

                    initial_guess = [ini_a, ini_h, ini_eB, ini_eS]

                    result = minimize(f, initial_guess, args=(k1, k2,
                                                              k3, kmi, buying_array[i], selling_array[i]))
                    if result.success:
                        fitted_params = result.x
                        print(fitted_params[0])
                    else:
                        raise ValueError(result.message)


def cal_PIN():
    buying_5_tick = []
    selling_5_tick = []

    buying_5_tick.append(4035)
    buying_5_tick.append(3522)
    buying_5_tick.append(4073)
    buying_5_tick.append(3154)
    buying_5_tick.append(9556)

    selling_5_tick.append(1840)
    selling_5_tick.append(2827)
    selling_5_tick.append(4095)
    selling_5_tick.append(2602)
    selling_5_tick.append(2230)

    cal_likelihood(selling_5_tick, buying_5_tick)

Я ожидал значений, где 0 <α <1 и 0 <δ <1, но что-то не так. </p>

1 Ответ

0 голосов
/ 02 апреля 2019

Ну, так как вы сами поднимаете ошибку, становится очевидным, что минимизация завершается ошибкой из-за ошибки Warning: Desired error not necessarily achieved due to precision loss.

Взято из скупой вопрос :

Это предупреждение возникает, когда при поиске строки не удается найти размер шага удовлетворение как условий Вулфа, так и условий спуска Полак-Рибьер в течение определенного числа итераций.

Результаты вашей минимизации, похоже, не имеют никакой границы, поскольку ваша целевая функция - это просто *-1 некоторые значения. Это приводит к довольно большим производным и может привести к некоторому плохо обусловленному гессиану. Такая плохо обусловленная матрица затем приводит к краху линии поиска. Одним из вариантов будет изменение цели возврата на

return 1 / (ini_a * ini_h * scipy.exp(k1 - kmi) + ini_a * (1 - ini_h) * scipy.exp(k2 - kmi) + (
            1 - ini_a) * scipy.exp(k3 - kmi) +
               (buying_array * scipy.log(ini_eB + ini_h) + selling_array * scipy.log(ini_eS + ini_h) - (
                           ini_eB + ini_eS) + kmi))

Это приводит к тому, что результаты отображаются в требуемом диапазоне 0 <значение <1. </p>

Если это не оптимальное решение для вас, попробуйте сменить решатели. Найдите некоторые опции в документации .

Также некоторые советы и рекомендации по программированию. Вы можете использовать itertools.product, чтобы избежать таких вложенных циклов. Вместо добавления каждого значения просто объявите список.

Вот предложения и рабочий код.

import time
import scipy
from scipy.optimize import minimize
import itertools

def f(params, *args):
    # args={k1, k2, k3, kmi, buying_array[i], selling_array[i]}
    k1 = args[0]
    k2 = args[1]
    k3 = args[2]
    kmi = args[3]
    buying_array = args[4]
    selling_array = args[5]

    ini_a, ini_h, ini_eS, ini_eB = params
    return 1 / (ini_a * ini_h * scipy.exp(k1 - kmi) + ini_a * (1 - ini_h) * scipy.exp(k2 - kmi) + (
                1 - ini_a) * scipy.exp(k3 - kmi) +
                   (buying_array * scipy.log(ini_eB + ini_h) + selling_array * scipy.log(ini_eS + ini_h) - (
                               ini_eB + ini_eS) + kmi))


def cal_likelihood(selling_array, buying_array):
    list_iteration = [0.1, 0.3, 0.5, 0.7, 0.9]
    for (ini_a, ini_h, z) in itertools.product(*[list_iteration,list_iteration,list_iteration]):
        time.sleep(1)
        for i in range(0, len(buying_array)):
            ini_eB = z * selling_array[i]

            cal_u = (buying_array[i] - ini_eB) / (ini_a * (1 - ini_h))
            ini_eS = selling_array[i] - (ini_a * ini_h * cal_u)

            k1 = ((-1.0) * (cal_u) - buying_array[i] * scipy.log(1 + (cal_u / ini_eB)))
            k2 = ((-1.0) * (cal_u) - selling_array[i] * scipy.log(1 + (cal_u / ini_eS)))
            k3 = (-1.0) * buying_array[i] * scipy.log(1 +
                                                      (cal_u / ini_eB)) - selling_array[i] * scipy.log(
                1 + (cal_u / ini_eS))
            kmi = max(k1, k2, k3)

            initial_guess = [ini_a, ini_h, ini_eB, ini_eS]

            result = minimize(f, initial_guess, args=(k1, k2,
                                                      k3, kmi, buying_array[i], selling_array[i]))
            if result.success:
                fitted_params = result.x
                print(fitted_params[0])
            else:
                raise ValueError(result.message)


def cal_PIN():
    buying_5_tick = [4035, 3522, 4073, 3154, 9556]
    selling_5_tick = [1840, 2827, 4095, 2602, 2230]

    cal_likelihood(selling_5_tick, buying_5_tick)

cal_PIN()
...