使用python进行拉丁超立方体采样

use*_*987 6 python random sampling

我想对一个函数定义的分布进行多维(2、3、4)采样:

f(x, y, ...) = ...
Run Code Online (Sandbox Code Playgroud)

分布可能是丑陋的,非标准的(例如数据上的3D样条曲线,高斯之和等)。为此,我想对2..4维空间进行统一采样,而不是使用一个额外的随机数来接受或拒绝该空间的给定点进入样本。

  1. 是否有为此目的准备使用python lib?

  2. 是否有python lib可以通过拉丁超立方体采样或其他统一采样方法在2..4维空间中生成点?具有独立随机数的Bruteforce采样通常会导致空间密度越来越小。

  3. 如果1)和2)不存在,那么是否有人善良地分享相同或相似问题的实现。

我将在python代码中使用它,但也认可到其他解决方案的链接。

Y0d*_*0da 8

自 1.7 版起,拉丁超立方采样现已成为 SciPy 的一部分。请参阅文档

from scipy.stats.qmc import LatinHypercube

engine = LatinHypercube(d=2)
sample = engine.random(n=100)
Run Code Online (Sandbox Code Playgroud)

它支持居中、强度和优化。


Sah*_*l M 6

我想这是一个较晚的答案,但这也适用于将来的访客。我刚刚在git上实现了多维统一的Latin Hypercube采样的实现。它很小,但是非常易于使用。如果变量是独立的,则可以使用Latin Hypercube Sampling生成在n个维度上采样的统一随机变量。下面是一个示例图,该图在零相关性的两个维度中比较了具有多维均匀性(LHS-MDU)的蒙特卡洛和拉丁超立方体采样。

import lhsmdu
import matplotlib.pyplot as plt
import numpy

l = lhsmdu.sample(2,10) # Latin Hypercube Sampling of two variables, and 10 samples each.
k = lhsmdu.createRandomStandardUniformMatrix(2,10) # Monte Carlo Sampling

fig = plt.figure()
ax = fig.gca()
ax.set_xticks(numpy.arange(0,1,0.1))
ax.set_yticks(numpy.arange(0,1,0.1))
plt.scatter(k[0], k[1], color="b", label="LHS-MDU")
plt.scatter(l[0], l[1], color="r", label="MC")
plt.grid()
plt.show()
Run Code Online (Sandbox Code Playgroud)

MCS与LHS

  • 之前不在 pip 上。我现在已经把它放好了。你能再检查一次吗? (2认同)

Qia*_*ini 5

现在 pyDOE 库提供了一个工具来生成基于拉丁超立方体的样本。

https://pythonhosted.org/pyDOE/randomized.html

生成 n 维样本:

lhs(n, [samples, criterion, iterations])
Run Code Online (Sandbox Code Playgroud)

其中n为维数,samples为样本空间的总数。

  • 如何指定种子值以便每次都能得到相同的结果? (2认同)

BKa*_*Kay 1

这个二维示例在二维上均匀采样,以恒定概率选择每个点(从而保持二项式分布的点数),从样本空间中随机且无替换地选择这些点,并生成一对向量,然后您可以使用它们传递给你的函数 f:

import numpy as np
import random
resolution = 10
keepprob = 0.5
min1, max1 = 0., 1.
min2, max2 = 3., 11. 
keepnumber = np.random.binomial(resolution * resolution, keepprob,1)
array1,array2  = np.meshgrid(np.linspace(min1,max1,resolution),np.linspace(min2,max2,resolution))
randominixes  = random.sample(list(range(resolution * resolution)), int(keepnumber))
randominixes.sort()
vec1Sampled,vec2Sampled  = array1.flatten()[randominixes],array2.flatten()[randominixes]
Run Code Online (Sandbox Code Playgroud)