3D 高斯 generator/transform

3D gaussian generator/transform

如何生成 3 个高斯变量?我知道 Box-Muller algorithm 可用于将两个 (U1,U2) 统一变量转换为两个 (X,Y) 高斯变量,但如何生成第三个变量? (Z).

一个简单的方法:

在这种游戏中,您不太可能只需要一次 3 个高斯变量。

你需要一些存储变量,它可以包含高斯变量的三元组或 nothing(Null,Nothing,Empty,无论你的编程语言是什么,你都没有告诉我们是哪一个)。

最初,商店中没有任何东西(空的)。

当被问及三胞胎时:

  • 如果商店包含一个三胞胎,则 return 那个三胞胎。 并将商店标记为空。

  • 如果商店是空的,运行 Box-Muller 3次。 这给了你 2 个三胞胎。 将第二个三胞胎放在商店里。 Return第一个三胞胎。

适合喜欢数学的程序员的另一种方法:

如果只是尝试使 Box-Muller 适应 3 维,唯一棘手的部分是获得随机 3D 向量的 norm。剩下的就是关于2个球面角θ(theta)和φ(phi),这很容易。

事实证明,在 3 维中,该范数涉及 incomplete gamma function 的倒数。

如果您有 Python 和 Numpy/Scipy,这就是函数 scipy.special.gammaincinv

我们可以这样写代码:

import  math
import  numpy.random   as  rd
import  scipy.special  as  sp

# convert 3 uniform [0,1) variates into 3 unit Gaussian variates:
def boxMuller3d(u3):
    u0,u1,u2 = u3    # 3 uniform random numbers in [0,1)

    gamma = u0
    norm2 = 2.0 * sp.gammaincinv(1.5, gamma)  # "regularized" versions
    norm  = math.sqrt(norm2)
    zr    = (2.0 * u1) - 1.0         # sin(theta)
    hr    = math.sqrt(1.0 - zr*zr)   # cos(theta)
    phi   = 2.0 * math.pi * u2
    xr    = hr * math.cos(phi)
    yr    = hr * math.sin(phi)

    g3 = list(map(lambda c: c*norm, [xr, yr, zr]))
    return g3

# generate 3 uniform variates and convert them into 3 unit Gaussian variates:
def gauss3(rng):
    u3 = rng.uniform(0.0, 1.0, 3)
    g3 = boxMuller3d(u3)
    return g3

为了(部分)检查正确性,我们可以有这个小主程序,它显示生成的随机序列的 1 到 4 阶统计矩:

randomSeed = 42
rng = rd.default_rng(randomSeed)

count = 3000000  #  (X,Y,Z) triplet count
variates = []
for i  in  range(count):
    g3 = gauss3(rng)
    variates += g3

ln = len(variates)
print("length=%d\n" % ln)

# Checking statistical moments of order 1 to 4:

m1 = sum(variates) / ln
m2 = sum( map(lambda x: x*x,   variates) ) / ln
m3 = sum( map(lambda x: x**3,  variates) ) / ln
m4 = sum( map(lambda x: x**4,  variates) ) / ln

print("m1=%g  m2=%g  m3=%g  m4=%g\n" % (m1,m2,m3,m4))

测试程序输出:

length=9000000
m1=-0.000455911  m2=1.00025  m3=-0.000563454  m4=3.00184

因此我们可以看到这些矩相当接近它们的数学预期值,分别为 0、1、0、3。