scipy, логнормальное распределение - параметры - PullRequest
24 голосов
/ 05 января 2012

Я хочу приспособить логнормальное распределение к моим данным, используя python scipy.stats.lognormal.fit. В соответствии с руководством , fit возвращает форму, loc, масштаб параметры. Но для логнормального распределения обычно требуется только два параметра : среднее значение и стандартное отклонение.

Как интерпретировать результаты функции scipy fit? Как получить подлость и std.dev.?

Ответы [ 3 ]

30 голосов
/ 05 января 2012

Распределения в scipy кодируются общим способом с двумя параметрами местоположения и масштаба, так что местоположение является параметром (loc), который сдвигает распределение влево или вправо, тогда как scale является параметром, который сжимает или растягивает распределение.

Для двухпараметрического логнормального распределения «среднее» и «стандартное отклонение» соответствуют log (scale) и shape (можно указать loc=0).

Ниже показано, как согласовать логнормальное распределение, чтобы найти два интересующих параметра:

In [56]: import numpy as np

In [57]: from scipy import stats

In [58]: logsample = stats.norm.rvs(loc=10, scale=3, size=1000) # logsample ~ N(mu=10, sigma=3)

In [59]: sample = np.exp(logsample) # sample ~ lognormal(10, 3)

In [60]: shape, loc, scale = stats.lognorm.fit(sample, floc=0) # hold location to 0 while fitting

In [61]: shape, loc, scale
Out[61]: (2.9212650122639419, 0, 21318.029350592606)

In [62]: np.log(scale), shape  # mu, sigma
Out[62]: (9.9673084420467362, 2.9212650122639419)
7 голосов
/ 09 июля 2013

Я просто потратил некоторое время на разработку этого и хотел документировать это здесь: Если вы хотите получить плотность вероятности (в точке x) из трех возвращаемых значений lognorm.fit (давайте назовем их (shape, loc, scale))вам нужно использовать эту формулу:

x = 1 / (shape*((x-loc)/scale)*sqrt(2*pi)) * exp(-1/2*(log((x-loc)/scale)/shape)**2) / scale

Таким образом, в качестве уравнения (loc равно µ, shape равно σ и scale равно α):

x = \frac{1}{(x-\mu)\cdot\sqrt{2\pi\sigma^2}}  \cdot e^{-\frac{log(\frac{x-\mu}{\alpha})^2}{2\sigma^2}}

0 голосов
/ 10 февраля 2018

Я думаю, что это поможет. Я долго искал ту же проблему и, наконец, нашел решение для моей проблемы .В моем случае Я пытался вписать некоторые данные в логнормальное распределение с помощью модуля scipy.stats.lognorm. Однако, когда я наконец получил параметры модели, я не смог найти способ повторить свои результаты, используя среднее значениеи std из y data.

В приведенном ниже коде я объясняю из параметров mean и std, как создать нормально распределенную выборку данных с использованием модуля scipy.stats.norm.Используя эти данные, я подгоняю нормальную модель (norm_dist_fitted), а также создаю нормальную модель, используя среднее значение и стандартное отклонение (mu, sigma), извлеченные из данных.

Исходная модель, производящая данные, подгоняемая и производимая-by- (mu-sigma) -pair сравнивается на графике.

Fig1


В следующем разделе кода я использую обычныйданные для получения логнормально-распределенной выборки.Для этого обратите внимание, что логнормальные выборки будут экспоненциальными по сравнению с исходной выборкой.Следовательно, среднее и стандартное отклонение экспоненциальной выборки будет (exp(mu) и exp(sigma)).

Я поместил полученные данные в lognormal (так как журнал моей выборки (exp (x)) обычно распределяется и следует предположениям логнормальной модели.

Чтобы создать логнормальную модель из среднего значения и стандартного отклонения исходных данных (x), код будет:

lognorm_dist = scipy.stats.lognorm(s=sigma, loc=0, scale=np.exp(mu))

Однако, если ваши данные уже находятся в экспоненциальном пространстве (exp (x)), вам необходимо использовать:

muX = np.mean(np.log(x))
sigmaX = np.std(np.log(x))
scipy.stats.lognorm(s=sigmaX, loc=0, scale=muX)

Fig2

import scipy
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

mu = 10 # Mean of sample !!! Make sure your data is positive for the lognormal example 
sigma = 1.5 # Standard deviation of sample
N = 2000 # Number of samples

norm_dist = scipy.stats.norm(loc=mu, scale=sigma) # Create Random Process
x = norm_dist.rvs(size=N) # Generate samples

# Fit normal
fitting_params = scipy.stats.norm.fit(x)
norm_dist_fitted = scipy.stats.norm(*fitting_params)
t = np.linspace(np.min(x), np.max(x), 100)

# Plot normals
f, ax = plt.subplots(1, sharex='col', figsize=(10, 5))
sns.distplot(x, ax=ax, norm_hist=True, kde=False, label='Data X~N(mu={0:.1f}, sigma={1:.1f})'.format(mu, sigma))
ax.plot(t, norm_dist_fitted.pdf(t), lw=2, color='r',
        label='Fitted Model X~N(mu={0:.1f}, sigma={1:.1f})'.format(norm_dist_fitted.mean(), norm_dist_fitted.std()))
ax.plot(t, norm_dist.pdf(t), lw=2, color='g', ls=':',
        label='Original Model X~N(mu={0:.1f}, sigma={1:.1f})'.format(norm_dist.mean(), norm_dist.std()))
ax.legend(loc='lower right')
plt.show()


# The lognormal model fits to a variable whose log is normal
# We create our variable whose log is normal 'exponenciating' the previous variable

x_exp = np.exp(x)
mu_exp = np.exp(mu)
sigma_exp = np.exp(sigma)

fitting_params_lognormal = scipy.stats.lognorm.fit(x_exp, floc=0, scale=mu_exp)
lognorm_dist_fitted = scipy.stats.lognorm(*fitting_params_lognormal)
t = np.linspace(np.min(x_exp), np.max(x_exp), 100)

# Here is the magic I was looking for a long long time
lognorm_dist = scipy.stats.lognorm(s=sigma, loc=0, scale=np.exp(mu))

# The trick is to understand these two things:
# 1. If the EXP of a variable is NORMAL with MU and STD -> EXP(X) ~ scipy.stats.lognorm(s=sigma, loc=0, scale=np.exp(mu))
# 2. If your variable (x) HAS THE FORM of a LOGNORMAL, the model will be scipy.stats.lognorm(s=sigmaX, loc=0, scale=muX)
# with:
#    - muX = np.mean(np.log(x))
#    - sigmaX = np.std(np.log(x))


# Plot lognormals
f, ax = plt.subplots(1, sharex='col', figsize=(10, 5))
sns.distplot(x_exp, ax=ax, norm_hist=True, kde=False,
             label='Data exp(X)~N(mu={0:.1f}, sigma={1:.1f})\n X~LogNorm(mu={0:.1f}, sigma={1:.1f})'.format(mu, sigma))
ax.plot(t, lognorm_dist_fitted.pdf(t), lw=2, color='r',
        label='Fitted Model X~LogNorm(mu={0:.1f}, sigma={1:.1f})'.format(lognorm_dist_fitted.mean(), lognorm_dist_fitted.std()))
ax.plot(t, lognorm_dist.pdf(t), lw=2, color='g', ls=':',
        label='Original Model X~LogNorm(mu={0:.1f}, sigma={1:.1f})'.format(lognorm_dist.mean(), lognorm_dist.std()))
ax.legend(loc='lower right')
plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...