DiscreteAliasUrn#
- класс scipy.stats.sampling.DiscreteAliasUrn(dist, *, область определения=None, urn_factor=1, random_state=None)#
Дискретный метод Alias-Urn.
Этот метод используется для выборки из одномерных дискретных распределений с конечной областью. Он использует вектор вероятностей размера \(N\) или функцией вероятностной массы с конечным носителем для генерации случайных чисел из распределения.
- Параметры:
- distarray_like или объект, опционально
Вероятностный вектор (PV) распределения. Если PV недоступен, экземпляр класса с
pmfожидается метод. Сигнатура PMF ожидается как:def pmf(self, k: int) -> float. т.е. он должен принимать целое число Python и возвращать число с плавающей точкой Python.- область определенияint, необязательный
Носитель PMF. Если вектор вероятностей (
pv) недоступен, должна быть задана конечная область. Т.е. PMF должен иметь конечную поддержку. По умолчаниюNone. КогдаNone:Если
supportметод предоставляется объектом распределения dist, используется для установки области определения распределения.В противном случае предполагается, что носитель
(0, len(pv)). Когда этот параметр передается в сочетании с вектором вероятности,domain[0]используется для перемещения распределения из(0, len(pv))to(domain[0], domain[0]+len(pv))иdomain[1]игнорируется. См. Примечания и учебник для более подробного объяснения.
- urn_factorfloat, опционально
Размер таблицы урны относительный к размеру вектора вероятностей. Он должен быть не меньше 1. Большие таблицы приводят к более быстрому времени генерации, но требуют более дорогой настройки. По умолчанию 1.
- random_state{None, int,
numpy.random.Generator, numpy.random.RandomState, опциональноГенератор случайных чисел NumPy или seed для базового генератора случайных чисел NumPy, используемого для генерации потока равномерных случайных чисел. Если random_state равно None (или np.random),
numpy.random.RandomStateиспользуется синглтон. Если random_state является int, новыйRandomStateиспользуется экземпляр, инициализированный с random_state. Если random_state уже являетсяGeneratorилиRandomStateэкземпляр, тогда этот экземпляр используется.
Методы
rvs([size, random_state])Выборка из распределения.
set_random_state([random_state])Установить базовый генератор равномерных случайных чисел.
Примечания
Этот метод работает, когда доступен либо конечный вектор вероятностей, либо функция вероятности распределения. Если доступна только функция вероятности, то конечный область определения (support) PMF также должна быть задана. Рекомендуется сначала получить вектор вероятностей, вычислив PMF в каждой точке области определения, а затем использовать его вместо этого.
Если задан вероятностный вектор, он должен быть одномерным массивом неотрицательных чисел с плавающей запятой без каких-либо
infилиnanзначения. Также должен быть хотя бы один ненулевой элемент, иначе будет вызвано исключение.По умолчанию вектор вероятностей индексируется, начиная с 0. Однако это можно изменить, передав
domainпараметр. Когдаdomainпри использовании в комбинации с PV, это приводит к перемещению распределения из(0, len(pv))to(domain[0],domain[0] + len(pv)).domain[1]игнорируется в этом случае.Параметр
urn_factorможет быть увеличена для более быстрой генерации за счёт увеличения времени настройки. Этот метод использует таблицу для генерации случайных величин.urn_factorуправляет размером этой таблицы относительно размера вектора вероятностей (или ширины носителя, если вектор вероятностей недоступен). Поскольку эта таблица вычисляется во время настройки, увеличение этого параметра линейно увеличивает время, необходимое для настройки. Рекомендуется держать этот параметр ниже 2.Ссылки
[1]Справочное руководство UNU.RAN, раздел 5.8.2, “DAU - (Discrete) Alias-Urn method”, http://statmath.wu.ac.at/software/unuran/doc/unuran.html#DAU
[2]A.J. Walker (1977). An efficient method for generating discrete random variables with general distributions, ACM Trans. Math. Software 3, pp. 253-256.
Примеры
>>> from scipy.stats.sampling import DiscreteAliasUrn >>> import numpy as np
Чтобы создать генератор случайных чисел с использованием вектора вероятностей, используйте:
>>> pv = [0.1, 0.3, 0.6] >>> urng = np.random.default_rng() >>> rng = DiscreteAliasUrn(pv, random_state=urng)
Генератор случайных чисел был настроен. Теперь мы можем использовать
rvsметод для генерации выборок из распределения:>>> rvs = rng.rvs(size=1000)
Чтобы проверить, что случайные величины следуют заданному распределению, можно использовать критерий хи-квадрат (как меру соответствия):
>>> from scipy.stats import chisquare >>> _, freqs = np.unique(rvs, return_counts=True) >>> freqs = freqs / np.sum(freqs) >>> freqs array([0.092, 0.292, 0.616]) >>> chisquare(freqs, pv).pvalue 0.9993602047563164
Поскольку p-значение очень высоко, мы не можем отвергнуть нулевую гипотезу о том, что наблюдаемые частоты совпадают с ожидаемыми частотами. Следовательно, мы можем безопасно предположить, что величины были сгенерированы из заданного распределения. Обратите внимание, что это проверяет корректность алгоритма, а не качество выборок.
Если PV недоступен, также можно передать экземпляр класса с методом PMF и конечной областью определения.
>>> urng = np.random.default_rng() >>> class Binomial: ... def __init__(self, n, p): ... self.n = n ... self.p = p ... def pmf(self, x): ... # note that the pmf doesn't need to be normalized. ... return self.p**x * (1-self.p)**(self.n-x) ... def support(self): ... return (0, self.n) ... >>> n, p = 10, 0.2 >>> dist = Binomial(n, p) >>> rng = DiscreteAliasUrn(dist, random_state=urng)
Теперь мы можем выполнить выборку из распределения, используя
rvsметод а также измеряет качество соответствия выборок:>>> rvs = rng.rvs(1000) >>> _, freqs = np.unique(rvs, return_counts=True) >>> freqs = freqs / np.sum(freqs) >>> obs_freqs = np.zeros(11) # some frequencies may be zero. >>> obs_freqs[:freqs.size] = freqs >>> pv = [dist.pmf(i) for i in range(0, 11)] >>> pv = np.asarray(pv) / np.sum(pv) >>> chisquare(obs_freqs, pv).pvalue 0.9999999999999999
Чтобы проверить, что выборки были взяты из правильного распределения, мы можем визуализировать гистограмму выборок:
>>> import matplotlib.pyplot as plt >>> rvs = rng.rvs(1000) >>> fig = plt.figure() >>> ax = fig.add_subplot(111) >>> x = np.arange(0, n+1) >>> fx = dist.pmf(x) >>> fx = fx / fx.sum() >>> ax.plot(x, fx, 'bo', label='true distribution') >>> ax.vlines(x, 0, fx, lw=2) >>> ax.hist(rvs, bins=np.r_[x, n+1]-0.5, density=True, alpha=0.5, ... color='r', label='samples') >>> ax.set_xlabel('x') >>> ax.set_ylabel('PMF(x)') >>> ax.set_title('Discrete Alias Urn Samples') >>> plt.legend() >>> plt.show()
Чтобы установить
urn_factor, используйте:>>> rng = DiscreteAliasUrn(pv, urn_factor=2, random_state=urng)
Это использует таблицу вдвое больше вектора вероятностей для генерации случайных величин из распределения.