Python

從 Python 中的 von Mises-Fisher 分佈中採樣?

  • June 12, 2015

我正在尋找一種簡單的方法來從Python 中的多變量 von Mises-Fisher 分佈中進行採樣。我查看了scipynumpy 模塊中的 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)

引用自:https://stats.stackexchange.com/questions/156729

comments powered by Disqus