Моделирование будем делать с помощью библиотеки scipy.
Полный список доступных распределений можно посмотреть по здесь: https://docs.scipy.org/doc/scipy/reference/stats.html
Далее на нормальном распределении будут приведены примеры работы с библиотекой.
1) Промоделируем случайную величину
2) Построим гистограмму и плостность распределения
3) Нарисуем графики функции распределения и накопленных частот
Для начала импортируем библиотеку:
from scipy import stats
Для моделирования распредения воспользуемся функцией .rvs()
Промоделируем одномерное нормальное распределение $N(0, 1)$:
normal = stats.norm(loc=0, scale=1)
sample = normal.rvs(size=1000, random_state=42)
Теперь, в массиве sample у нас находится выборка из нормального распределения, размера $1000$.
Построим гистограмму, для этого воспользуемся библиотекой matplotlib:
import matplotlib.pyplot as plt
%matplotlib inline
plt.hist(sample, bins=20) # Параметр bins - отвечает за количество разбиений в гистограмме
plt.title('Гистограмма выборки из нормального распределения')
plt.show()
Поверх гистограммы построим график функции плотности распределения, чтобы получить значение плотности распределения в заданной точке (или наборе точек), воспользуемся функцией pdf():
import numpy as np
x = np.linspace(-5, 5, 100) # Отрезок на котором будем строить график
plt.hist(sample, density=True, bins=20, label='histogram')
plt.plot(x, normal.pdf(x), 'r-', lw=3, label='frozen pdf')
plt.legend()
plt.show()
Построим графики накопленных частот и функции распределения, для этого воспользуемся функцией ECDF библиотеки statsmodels:
from statsmodels.distributions.empirical_distribution import ECDF
ecdf = ECDF(sample)
x = np.linspace(min(sample), max(sample))
plt.step(x, ecdf(x), label='Empirical CDF')
plt.plot(x, normal.cdf(x), label='Theoretical CDF')
plt.legend()
plt.show()
Для этого сгенерируем выборку размером 10000 из стандартного нормального распределения, чтобы это было наглядно, увеличим количество разбиений в гистограмме:
sample = stats.norm(loc=0, scale=1).rvs(size=10000, random_state=42)
x = np.linspace(-5, 5, 100) # Отрезок на котором будем строить график
plt.hist(sample, density=True, bins=50, label='histogram')
plt.plot(x, normal.pdf(x), 'r-', lw=3, label='frozen pdf')
plt.legend()
plt.show()
Для моделирования распредения воспользуемся функцией .rvs()
Промоделируем распределение Пуассона с параметром $\lambda = 1$:
lmbda = 1
pois = stats.poisson(lmbda)
sample = pois.rvs(size=1000, random_state=42)
Теперь, в массиве sample у нас находится выборка из распределения Пуассона, размера $1000$.
Построим гистограмму:
values, counts = np.unique(sample, return_counts=True)
В массиве values находятся отсортированные уникальные значения смодедированной выборки, а в массиве counts -- количество повторений элементов из массива values.
plt.vlines(values, 0, counts, color='r', lw=4)
plt.title('Emperical Poisson Probability Mass Function (PMF)')
plt.show()
Добавим на график теоретические значения функции вероятности:
plt.vlines(values, 0, counts/sum(counts), lw=3, color='r', label='Emperical Poisson PMF')
plt.vlines(values, 0, pois.pmf(values), colors='k', linestyles='dashdot', lw=2, label='Poisson PMF')
plt.legend()
plt.show()
ecdf = ECDF(sample)
x = np.linspace(min(sample), max(sample))
plt.plot(x, ecdf(x), color='r', label='Empirical CDF')
plt.plot(x, pois.cdf(x), label='Theoretical CDF')
plt.legend(loc='lower right')
plt.show()
Иногда требуется стандартизировать дискретное распределение (например для того, чтобы более осмысленно сравнивать разные по природе выборки или, например, "похожесть" дискретного распределения на нормальное). Это делается несложным преобразованием: вычитанием среднего и делением на стандартное отклонение
$$\frac{X_i - \bar x}{s},$$где $X_i$ - элемент из выборки $\{X_i\}_{i = 1}^n,$ $\bar x$ - среднее, а $s$ - стандартное отклонение.
Промоделируем выборку из Пуассоновского распределения с достаточно большим параметром $\lambda = 100.$
lmbda = 100
pois = stats.poisson(lmbda)
sample = pois.rvs(size=100000, random_state=42)
_, bins, _nvm = plt.hist(sample, density=True, bins=15, label='histogram')
# в переменной bins теперь разбиения гистограммы
plt.show()
Допустим, мы хотим сравнить это дискретное распределение со стандартным нормальным распределением, хотя бы визуально. Для этого нужно стандартизировать нашу выборку и построить гистограмму вместе с плотностью нормального распределения.
stand_sample = (sample - sample.mean())/ sample.std()
Заметин, что вместе со стандартизацией выборки, мы также применим тоже преобразование и к вектору bins, чтобы сохранить ширину и позицию столбцов гистограммы при стандартизации
new_bins = (bins - sample.mean()) / sample.std()
x = np.linspace(-4, 4, 100)
plt.hist(stand_sample, density=True, bins=new_bins)
plt.title('Гистограмма стандартизированной выборки и плотность N(0, 1)')
plt.plot(x, stats.norm.pdf(x), 'r-', lw=3)
plt.show()
В данном случае можно сделать интересное наблюдение, которое соответсвует действительности: при больших $\lambda$ Пуассоновское распределение неплохо аппроксимируется нормальным распределением со средним и диспресией, равными $\lambda$