In [449]: timeit sample_trig(1000)
1000 loops, best of 3: 236 µs per loop
In [450]: timeit sample_normals(1000)
10000 loops, best of 3: 172 µs per loop
In [451]: timeit sample_reject(1000)
100 loops, best of 3: 13.7 ms per loop
def sample_trig_loop(npoints):
x = np.zeros(npoints)
y = np.zeros(npoints)
z = np.zeros(npoints)
for k in xrange(npoints):
theta = 2*np.pi*np.random.rand()
phi = np.arccos(2*np.random.rand()-1)
x[k] = np.cos(theta) * np.sin(phi)
y[k] = np.sin(theta) * np.sin(phi)
z[k] = np.cos(phi)
return np.array([x,y,z])
def sample_normals_loop(npoints):
vec = np.zeros((3,npoints))
for k in xrange(npoints):
tvec = np.random.randn(3)
vec[:,k] = tvec/np.linalg.norm(tvec)
return vec
In [464]: timeit sample_trig(1000)
1000 loops, best of 3: 236 µs per loop
In [465]: timeit sample_normals(1000)
10000 loops, best of 3: 173 µs per loop
In [466]: timeit sample_reject(1000)
100 loops, best of 3: 14 ms per loop
In [467]: timeit sample_trig_loop(1000)
100 loops, best of 3: 7.92 ms per loop
In [468]: timeit sample_normals_loop(1000)
100 loops, best of 3: 10.9 ms per loop
基于the last approach on this page,您可以简单地从三个标准正态分布生成一个由独立样本组成的向量,然后对该向量进行规范化,使其大小为1:
例如:
同样的方法也推广到单位圆(
ndim=2
)或高维单位超球表面上的均匀分布点的提取。球面上的点可以用两个球坐标来表示,
theta
和phi
,用0 < theta < 2pi
和0 < phi < pi
。将公式转换为笛卡尔坐标:
其中
r
是球体的半径。因此,程序可以在它们的范围内以均匀分布随机采样
theta
和phi
,并由此生成笛卡尔坐标。但是这些点在球体的极点上分布得更为密集。为了使点在球面上均匀分布,需要选择
phi
作为phi = acos(a)
,其中-1 < a < 1
选择均匀分布。对于Numpy代码,它将与Sampling uniformly distributed random points inside a spherical volume中的相同,只是变量
radius
有一个固定值。在与@Soonts进行了一些讨论之后,我对答案中使用的三种方法的性能感到好奇:一种是生成随机角度,一种是使用正态分布坐标,还有一种是拒绝均匀分布的点。
以下是我试图进行的比较:
然后1000分
注意,在基于拒绝的实现中,我首先生成了
npoints
样本并丢弃了坏的样本,并且我只使用了一个循环来生成其余的点。似乎是这样的,直接一步一步的拒绝需要更长的时间。我还删除了除法为零的检查,以便与sample_normals
情况进行更清晰的比较。从两种直接方法中删除矢量化会将它们放在同一个问题上:
相关问题 更多 >
编程相关推荐