scipy.stats.DiscreteAliasUrn¶
- class scipy.stats.DiscreteAliasUrn(dist, *, domain=None, urn_factor=1, random_state=None)¶
离散别名-骨灰盒方法。
该方法适用于有限域的单变量离散分布的抽样。它使用大小的概率向量 \(N\) 或具有有限支持的概率质量函数以从分布生成随机数。
- 参数
- distARRAY_LIKE或OBJECT,可选
分布的概率向量(PV)。如果PV不可用,则使用
pmf
方法是必需的。预计PMF的签名为:def pmf(self, k: int) -> float
。即它应该接受Python整数并返回Python浮点。- domain整型,可选
对PMF的支持。如果概率向量 (
pv
)不可用,则必须给出有限域。即PMF必须具有有限支撑。默认值为None
。什么时候None
:如果一个
support
方法由分发对象提供 dist ,用于设置分布的域。否则,将假定支持为
(0, len(pv))
。当该参数与概率向量组合传递时,domain[0]
用于将分发从(0, len(pv))
至(domain[0], domain[0]+len(pv))
和domain[1]
被忽略。有关更详细的说明,请参阅注释和教程。
- urn_factor浮动,可选
骨灰盒表格的大小 相对的 到概率向量的大小。它不能小于1。表越大,生成时间越快,但需要更昂贵的设置。默认值为1。
- random_state :{无,整型,
numpy.random.Generator
,{无,整型, 用于生成均匀随机数流的基础NumPy随机数生成器的NumPy随机数生成器或种子。如果 random_state 为无(或 np.random )、
numpy.random.RandomState
使用的是Singleton。如果 random_state 是一个整型、一个新的RandomState
实例,其种子设定为 random_state 。如果 random_state 已经是一个Generator
或RandomState
实例,则使用该实例。
注意事项
当有限概率向量可用或分布的PMF可用时,此方法起作用。如果只有PMF可用,则 有限的 还必须提供PMF的支持(域)。建议首先通过评估支撑中每个点的PMF,然后使用它来获得概率向量。
如果给定了概率向量,则它必须是非负浮点数的一维数组,不带任何
inf
或nan
价值。此外,必须至少有一个非零条目,否则会引发异常。默认情况下,概率向量从0开始编制索引。但是,这可以通过传递一个
domain
参数。什么时候domain
与pv结合使用时,它的效果是将分布从(0, len(pv))
至(domain[0]
,domain[0] + len(pv))
。domain[1]
在这种情况下被忽略。该参数
urn_factor
可以增加以增加设置时间为代价来更快地生成。该方法使用表格生成随机变量。urn_factor
控制此表格相对于概率向量大小的大小(如果PV不可用,则控制支撑的宽度)。由于此表是在设置时计算的,因此增加此参数会线性增加设置所需的时间。建议将此参数控制在2以下。参考文献
- 1
联合国参考手册,第5.8.2节,“DAU-(离散)别名-URN方法”,http://statmath.wu.ac.at/software/unuran/doc/unuran.html#DAU
- 2
A.J.沃克(1977)。一种产生具有一般分布的离散随机变量的有效方法ACM Trans。数学课。软件3,第253-256页。
示例
>>> from scipy.stats import DiscreteAliasUrn
要使用概率向量创建随机数生成器,请使用:
>>> pv = [0.1, 0.3, 0.6] >>> urng = np.random.default_rng() >>> rng = DiscreteAliasUrn(pv, random_state=urng)
已设置RNG。现在,我们可以使用 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)
这使用两倍于概率向量大小的表从分布生成随机变量。
方法:
rvs
\([size] )分发的样本。
set_random_state
\([random_state] )设置基础均匀随机数生成器。