scipy.stats.qmc.

泊松盘#

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

泊松盘采样。

参数:
d整数

参数空间的维度。

半径浮动

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

超球面{“体积”, “表面积”}, 可选

生成潜在候选者以加入最终样本的采样策略。默认是“体积”。

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

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

ncandidates整数

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

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

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

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

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

Added in version 1.10.0.

种子 : {None, int, numpy.random.Generator}, 可选{None, int,}

如果 seed 是 int 或 None,将使用 np.random.default_rng(seed) 创建一个新的 numpy.random.Generator。如果 seed 已经是 Generator 实例,则使用提供的实例。

方法

fast_forward(n)

将序列快进 n 个位置。

fill_space()

在区间 [0, 1] 中绘制 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()

将引擎重置为基础状态。

注释

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

样本可以包含的点数的最大值直接与 半径 相关。随着空间的维度增加,更大的半径使点分布更广,有助于克服维度灾难。更多详情请参见 准蒙特卡罗教程

警告

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

一些代码来自 [2],原作者 Shamis 于 2021 年 3 月 31 日书面同意,可在 SciPy 下免费使用,遵循 3-clause BSD 许可证。

参考文献

[1]

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

示例

使用 radius 为 0.2 生成一个二维样本。

>>> 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, seed=rng)
>>> sample = engine.random(20)

可视化二维样本并展示没有点之间的距离小于 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 方法可以用来添加样本,直到不能再添加更多样本为止。这是一个难题,可能需要手动调整参数。注意维度:随着维度的增加,填充空间所需的样本数量呈指数增长(维度灾难)。