Экспоненциальная подгонка: optimize.curve_fit и stats.expon.fit дают разные результаты - PullRequest
0 голосов
/ 28 апреля 2020

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

Следуя приведенному здесь ответу ( Гистограмма соответствует python), я использую метод fit scipy.stats.expon распределение.

import glob
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns

fig, ax = plt.subplots(5, 1, sharex = True)
j = 0

for files in glob.glob("data_*"):

    time = []
    hist = []

    with open(files, 'r') as f:
         for line in f:
             line = line.split(' ')
             time.append(float(line[0]))
             H.append(float(line[1]))

    P  = ss.expon.fit(H, floc = 0)
    T  = np.linspace(0,200, 1000)
    rP = ss.expon.pdf(T, *P)

    ax[j].plot(T, rP, lw = 3.0)
    ax[j].hist(H,bins = 30, alpha = 0.6, label = r"$\lambda = $" + str(1/P[1]), density = True, stacked = True)
    ax[j].set_yticks([])
    ax[j].legend()

    j = j +1 

sns.despine(top = True, left = True, right = True)
plt.xlabel("Time")
plt.show()

Таким образом, я получаю следующий график:

enter image description here

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

Этот вопрос уже задавался здесь ( Есть ли способ получить ошибку при подборе параметров из scipy.stats.norm .Поставить ). В принятом ответе предложено использовать кривую_картины вместо гистограммы. Поэтому, следуя инструкции (https://riptutorial.com/scipy/example/31081/fitting-a-function-to-data-from-a-histogram), я попытался использовать curve_fit. Вот модифицированный код (я вставил эти строки вместо использования scipy.stats.expon):


    def func(x, a):
        return a*np.exp(-a*x)

    bins = np.linspace(0, 200, 201)
    data_entries, bins = np.histogram(np.array(H), bins = bins)
    binscenters = np.array([0.5 * (bins[i] + bins[i + 1]) for i in range (len(bins)-1)])
    popt, pcov = curve_fit(func, xdata = binscenters, ydata = data_entries)

    ax[j].plot(T, func(T, *popt))
    ax[j].hist(H, bins = 30, alpha = 0.6, label = r"$\lambda = $" + str(popt[0]), density = True, stacked = True)

Эта подгонка дает результаты, которые сильно отличаются от stats.expon.fit, и, кажется, (по крайней мере, качественно) хуже соответствуют данным.

enter image description here

Я неправильно использую Curve_fit? Я считаю, что в некоторых пределах curve_fit и expon.fit должны давать одинаковые результаты. Есть ли способ получить ошибку в оценочной лямбда от expon.fit? Я имею в виду вычисление относительной погрешности между средним значением данных и лямбда-выражением, оцененным из начального соответствия, но я не знаю, будет ли это правильно. Любая подсказка будет принята с благодарностью.

1 Ответ

0 голосов
/ 05 мая 2020

Мне удалось решить мою проблему. Оказывается, мне не хватает density = True на numpy.histogram.

Функция

def func(x, a):
        return a*np.exp(-a*x)

является экспоненциальным PDF. Поскольку мои данные не были нормализованы (следовательно, не PDF), подгонка с использованием curve_fit была неправильной. С этой модификацией ss.expon.fit и curve_fit выдают одно и то же значение лямбды.

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