Python 四维球面上均匀分布点

9

我需要在一个四维球体上均匀分布点。我知道这不像挑选三个角度并使用极坐标那么简单。

在三维空间中,我使用以下方法:

from random import random

u=random()
costheta = 2*u -1 #for distribution between -1 and 1
theta = acos(costheta)
phi = 2*pi*random

x=costheta
y=sin(theta)*cos(phi)
x=sin(theta)*sin(phi)

这将提供 x、y 和 z 的均匀分布。

我如何获得类似的 4 维分布?


如何在N维球面上随机生成均匀分布的点:http://en.wikipedia.org/wiki/N-sphere#Uniformly_at_random_from_the_.28n.C2.A0.E2.88.92.C2.A01.29-sphere - unutbu
1
等等,你想让这些点在一个球体上均匀分布,但是在x、y、z(第四维)上也均匀分布?我觉得这不太对。我认为在球体上均匀分布的点不会映射到4D空间中均匀分布。 - Nicu Stiurca
@SchighSchagh,所以你不能在四维空间中运行蒙特卡罗模拟吗? - Sameer Patel
@SameerPatel 这与蒙特卡罗或任何其他采样方法无关。这里有两个不同的空间(一个是R^4,另一个是4-球面的表面),我们需要知道你想要在哪个空间中进行均匀随机分布。 - Nicu Stiurca
4个回答

11

一种标准的方式是使用Muller的方法在N-球面上生成均匀分布的点,尽管这可能不是最快的

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as axes3d

N = 600
dim = 3

norm = np.random.normal
normal_deviates = norm(size=(dim, N))

radius = np.sqrt((normal_deviates**2).sum(axis=0))
points = normal_deviates/radius

fig, ax = plt.subplots(subplot_kw=dict(projection='3d'))
ax.scatter(*points)
ax.set_aspect('equal')
plt.show()

enter image description here

只需将 dim = 3 改为 dim = 4 即可在四维球面上生成点。


采用均匀分布会产生一个密度向立方体角落聚集的球形样本。如何证明使用高斯分布不会导致这个问题呢?如果我在脑海中想象一下,似乎很有道理,但真的是这样吗?当指定大小时,我假设numpy的高斯分布对于每个坐标都是独立的。 - Guillaume Chevalier
那么除以零怎么办? - Guillaume Chevalier
2
@GuillaumeChevalier:我承认我不太理解具体细节,但也许你会发现这个证明概述很有用。关于除以零的问题:我相信被除数为0的概率本身就是0。在实际应用中,NumPy通过发出警告并返回NaN(而Matplotlib跳过等于NaN的点)来处理除以零。 - unutbu
很棒的解决方案,但如何更改球体的中心和最大半径? - user3379482
@user3379482:您可以使用points = new_radius * points + new_locationpoints移动到新位置并使用新半径,其中new_radius是标量,而new_location是序列(例如元组、列表或NumPy数组)。 - unutbu
显示剩余2条评论

2

取一个在4D空间中坐标服从正态分布的点,并计算它的单位向量。这将位于单位4-球上。

from random import random
import math
x=random.normalvariate(0,1)
y=random.normalvariate(0,1)
z=random.normalvariate(0,1)
w=random.normalvariate(0,1)
r=math.sqrt(x*x + y*y + z*z + w*w)
x/=r
y/=r
z/=r
w/=r
print (x,y,z,w)

当然,这将在4维球面上生成一个随机点,但分布是否均匀? - Nicu Stiurca
@SchighSchagh:均匀分布的?是的。 - Manishearth
1
x、y、z、w最初在R ^ 4上是均匀随机的,但然后它们经历了非线性变换,我仍然不确定OP是否希望它们与球面或R ^ 4的表面相对均匀地随机。编辑:您能否具体说明与何种均匀随机相关,并加以证明? - Nicu Stiurca
@SchighSchagh:糟糕,我忘记了要对它们进行正常分布。请参见http://enwp.org/N-sphere#Uniformly_at_random_from_the_.28n.C2.A0.E2.88.92.C2.A01.29-sphere。 - Manishearth
除以零怎么办? - Guillaume Chevalier

1
如果高斯采样确实创建了一个均匀分布的球形分布(而不是从立方体中采样),我喜欢@unutbu的答案,但为了避免在高斯分布上采样并且需要证明它,有一个简单的解决方案:在球面上进行均匀分布采样(而不是在立方体上)。
  1. 生成均匀分布的点。
  2. 计算每个点的平方半径(避免使用平方根)。
  3. 丢弃点:
    • 丢弃平方半径大于1的点(因此,半径大于1的非平方点)。
    • 丢弃太靠近零半径的点,以避免与下一步中的除法相关的数值不稳定性。
  4. 对于每个保留的采样点,将采样点除以其范数,以便将其重新归一化为单位半径。
  5. 洗涤和重复更多点,因为已丢弃的样本。

显然,这适用于n维空间,因为在高维度中,半径始终是L2范数。

它很快,因此避免了平方根和高斯分布采样,但它不是矢量化算法。

0
我发现了一个很好的解决方案,可以从N维球面中进行采样。主要思路是:
如果从非相关多元正态分布中抽取Y,则S = Y / ||Y||在单位d-球面上具有均匀分布。将S乘以U1/d,其中U在单位区间(0,1)上具有均匀分布,就可以在单位d-球体中创建均匀分布。
以下是Python代码:
Y = np.random.multivariate_normal(mean=[0], cov=np.eye(1,1), size=(n_dims, n_samples))
Y = np.squeeze(Y, -1)
Y /= np.sqrt(np.sum(Y * sample_isotropic, axis=0))
U = np.random.uniform(low=0, high=1, size=(n_samples)) ** (1/n_dims)
Y *= distr * radius # in my case radius is one

这是我得到的球体:

sphere


1
变量distrsample_isotropic是什么?您能修改代码示例使其正常工作吗? - n1k31t4
这个概念上与unutbu的答案有什么不同?为什么你生成了U却没有使用它? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接