scipy.stats.qmc.

PoissonDisk#

class scipy.stats.qmc.PoissonDisk(d, *, radius=0.05, hypersphere='volume', ncandidates=30, optimization=None, rng=None, l_bounds=None, u_bounds=None)[源代码]#

泊松圆盘采样。

参数:
dint

参数空间的维度。

radiusfloat

采样新候选点时,点之间保持的最小距离。

hypersphere{“volume”, “surface”}, 可选

用于生成最终样本中要添加的潜在候选点的采样策略。默认值为“volume”。

  • volume: 如 [1] 中描述的原始 Bridson 算法。新的候选点在超球面内部采样。

  • surface: 仅采样超球面的表面。

ncandidatesint

每次迭代采样的候选点数量。更多的候选点会导致更密集的采样,因为每次迭代可以接受更多的候选点。

optimization{None, “random-cd”, “lloyd”}, 可选

是否使用优化方案来提高采样后的质量。请注意,这是一个后处理步骤,不保证样本的所有属性都将保留。默认值为 None。

  • random-cd:坐标的随机排列以降低中心差异。基于中心差异的最佳样本会不断更新。与使用其他差异度量相比,基于中心差异的采样在二维和三维子投影方面显示出更好的空间填充鲁棒性。

  • lloyd:使用修改后的 Lloyd-Max 算法扰动样本。该过程收敛到等距样本。

在 1.10.0 版本中添加。

rngnumpy.random.Generator, 可选

伪随机数生成器状态。当 rng 为 None 时,将使用操作系统的熵创建一个新的 numpy.random.Generator。除 numpy.random.Generator 之外的类型将传递给 numpy.random.default_rng 以实例化 Generator

在 1.15.0 版本中更改: 作为从使用 numpy.random.RandomState 过渡到 numpy.random.GeneratorSPEC-007 转换的一部分,此关键字从 seed 更改为 rng。在过渡期间,两个关键字都将继续工作,但一次只能指定一个。在过渡期结束后,使用 seed 关键字的函数调用将发出警告。在弃用期之后,seed 关键字将被删除。

l_bounds, u_boundsarray_like (d,)

目标样本数据的下限和上限。

注释

泊松圆盘采样是一种迭代采样策略。从种子样本开始,在种子周围的超球体中采样 ncandidates 个。拒绝低于某个 radius 或超出域的候选点。新的样本被添加到样本种子池中。当池为空或达到所需的样本数量时,该过程停止。

样本可以包含的最大点数与 radius 直接相关。随着空间维度的增加,更大的半径会进一步分散点,并有助于克服维度诅咒。有关更多详细信息,请参见 准蒙特卡洛教程

警告

由于其迭代性质和内存需求,该算法更适合于低维度和小采样大小。选择具有高维度的小半径意味着空间可以包含比使用较低维度或更大半径更多的样本。

部分代码取自 [2],原始作者 Shamis 于 2021 年 3 月 31 日给予书面同意,允许在 3 条款 BSD 下在 SciPy 中免费使用。

参考文献

[1]

Robert Bridson,“任意维度中的快速泊松圆盘采样。” SIGGRAPH,2007。

示例

使用 0.2 的 radius 生成 2D 样本。

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from matplotlib.collections import PatchCollection
>>> from scipy.stats import qmc
>>>
>>> rng = np.random.default_rng()
>>> radius = 0.2
>>> engine = qmc.PoissonDisk(d=2, radius=radius, rng=rng)
>>> sample = engine.random(20)

可视化 2D 样本并显示没有点比 radius 更近。radius/2 用于可视化不相交的圆。如果两个样本彼此之间的距离恰好为 radius,则它们的半径为 radius/2 的圆将相切。

>>> fig, ax = plt.subplots()
>>> _ = ax.scatter(sample[:, 0], sample[:, 1])
>>> circles = [plt.Circle((xi, yi), radius=radius/2, fill=False)
...            for xi, yi in sample]
>>> collection = PatchCollection(circles, match_original=True)
>>> ax.add_collection(collection)
>>> _ = ax.set(aspect='equal', xlabel=r'$x_1$', ylabel=r'$x_2$',
...            xlim=[0, 1], ylim=[0, 1])
>>> plt.show()
../../_images/scipy-stats-qmc-PoissonDisk-1_00_00.png

这种可视化可以看作是圆形堆积:我们可以在空间中放入多少个圆。这是一个 np 难题。可以使用方法 fill_space 添加样本,直到无法再添加样本为止。这是一个难题,可能需要手动调整参数。请注意维度:随着维度的增加,填充空间所需的样本数量呈指数级增长(维度诅咒)。

方法

fast_forward(n)

将序列快进 n 个位置。

fill_space()

在区间 [l_bounds, u_bounds] 中绘制 n 个样本。

integers(l_bounds, *[, u_bounds, n, ...])

l_bounds (包括)到 u_bounds (不包括)绘制 n 个整数,或者如果 endpoint=True,则从 l_bounds (包括)到 u_bounds (包括)。

random([n, workers])

在半开区间 [0, 1) 中绘制 n 个。

reset()

将引擎重置为基本状态。