我正在寻找一种简单的方法来从Python 中的多变量 von Mises-Fisher 分布中进行采样。我查看了scipy和numpy 模块中的 stats 模块,但只找到了单变量 von Mises 分布。有可用的代码吗?我还没有找到。
显然,Wood (1994) 根据此链接设计了一种从 vMF 分布中采样的算法,但我找不到该论文。
--编辑为了精确,我对文献中很难找到的算法感兴趣(大多数论文都集中在上)。据我所知,无法免费找到这篇开创性的文章(Wood,1994)。
我正在寻找一种简单的方法来从Python 中的多变量 von Mises-Fisher 分布中进行采样。我查看了scipy和numpy 模块中的 stats 模块,但只找到了单变量 von Mises 分布。有可用的代码吗?我还没有找到。
显然,Wood (1994) 根据此链接设计了一种从 vMF 分布中采样的算法,但我找不到该论文。
--编辑为了精确,我对文献中很难找到的算法感兴趣(大多数论文都集中在上)。据我所知,无法免费找到这篇开创性的文章(Wood,1994)。
终于我明白了。这是我的答案。
我终于把我的手放在了方向统计(Mardia 和 Jupp,1999 年)和 Ulrich-Wood 的采样算法上。我在这里发布我从中理解的内容,即我的代码(在 Python 中)。
拒绝抽样方案:
def rW(n, kappa, m):
dim = m-1
b = dim / (np.sqrt(4*kappa*kappa + dim*dim) + 2*kappa)
x = (1-b) / (1+b)
c = kappa*x + dim*np.log(1-x*x)
y = []
for i in range(0,n):
done = False
while not done:
z = sc.stats.beta.rvs(dim/2,dim/2)
w = (1 - (1+b)*z) / (1 - (1-b)*z)
u = sc.stats.uniform.rvs()
if kappa*w + dim*np.log(1-x*w) - c >= np.log(u):
done = True
y.append(w)
return y
然后,所需的采样是,其中是拒绝采样方案的结果,并且在超球面上均匀采样。
def rvMF(n,theta):
dim = len(theta)
kappa = np.linalg.norm(theta)
mu = theta / kappa
result = []
for sample in range(0,n):
w = rW(n, kappa, dim)
v = np.random.randn(dim)
v = v / np.linalg.norm(v)
result.append(np.sqrt(1-w**2)*v + w*mu)
return result
而且,为了有效地使用此代码进行采样,这里有一个示例:
import numpy as np
import scipy as sc
import scipy.stats
n = 10
kappa = 100000
direction = np.array([1,-1,1])
direction = direction / np.linalg.norm(direction)
res_sampling = rvMF(n, kappa * direction)
(我为这里的格式道歉,我创建了一个帐户只是为了回答这个问题,因为我最近也在尝试解决这个问题)。
mic 的答案不太对,向量需要来自的切线空间中的,即应该是与正交的单位向量。否则,向量将没有范数。您可以在 mic 提供的示例中看到这一点。要解决此问题,请使用以下内容:
import scipy.linalg as la
def sample_tangent_unit(mu):
mat = np.matrix(mu)
if mat.shape[1]>mat.shape[0]:
mat = mat.T
U,_,_ = la.svd(mat)
nu = np.matrix(np.random.randn(mat.shape[0])).T
x = np.dot(U[:,1:],nu[1:,:])
return x/la.norm(x)
并更换
v = np.random.randn(dim)
v = v / np.linalg.norm(v)
在麦克风的示例中调用
v = sample_tangent_unit(mu)