Python'da von Mises-Fisher dağıtımından örnekleme?


14

Python'da çok değişkenli von Mises-Fisher dağıtımından örneklemenin basit bir yolunu arıyorum . Scipy ve numpy modülündeki istatistik modülüne baktım ama sadece tek değişkenli von Mises dağılımını buldum. Herhangi bir kod var mı? Henüz bulamadım.

Görünüşe göre, Wood (1994) bu bağlantıya göre vMF dağılımından örnekleme için bir algoritma tasarladı , ancak kağıdı bulamıyorum.

- edit Kesinlik için, literatürde bulmak zor olan algoritma ile ilgileniyorum (makalelerin çoğu odaklanıyor ). Seminal makale (Wood, 1994) bildiğim kadarıyla ücretsiz bulunamaz.S2


1
Girdi scipy.stats.vonmisesdizisi gibi olabilir, böylece dağıtımı bir olarak belirtebilirsiniz array. Bu örneğe
rightskewed

Cevabınız için teşekkürler. Ama, gerçek bir nD von Mises-Fisher 1'den-D von Mises daha bir ürünü olduğu görünüyor: K = vonmises.pdf([x,x], kappa=[[1],[10]]). 2-D vMF'nin parametre olarak yalnızca bir adet gerçek olması gerekir . Katılıyor musun? κ
mikrofon

Başlangıçta von Mises Fisher dağıtımının Simülasyonunda VM * algoritmasını arıyorum (Wood, 1994). Kimse?
mikrofon

3
Burada bu konudaki cevapları gerçekten yararlı buldum. Bunu bu paketin bir parçası olarak yapmak için biraz temizlenmiş bir yardımcı program işlevi sağladım: https://github.com/clara-labs/spherecluster/blob/develop/spherecluster/util.py , hala bunu oluşturmak isteyenler için veri.
Jaska

Yanıtlar:


11

Sonunda anladım. İşte cevabım.

Sonunda ellerimi Yön İstatistikleri'ne (Mardia ve Jupp, 1999) ve Ulrich-Wood'un örnekleme algoritmasına koydum. Burada ondan ne anladım, yani benim kod (Python) sonrası.

Ret örnekleme şeması:

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

Daha sonra, istenen örnekleme ; burada , reddetme örnekleme şemasından kaynaklanır ve , hiper kürenin üzerinde düzgün bir şekilde örneklenir.wvv1w2+wμwv

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

Ve bu kodla etkili bir şekilde örnekleme yapmak için bir örnek:

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)

3
(+1) Cevabınızı paylaştığınız için teşekkür ederiz (özellikle sorunuzun başlangıçta kapanma olasılığına rağmen)!
whuber

4

(Buradaki biçimlendirme için özür dilerim, bu soruyu yanıtlamak için bir hesap oluşturdum, çünkü son zamanlarda da anlamaya çalışıyordum).

vSp2μvμv1w2+wμ

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)

ve değiştir

v = np.random.randn(dim)
v = v / np.linalg.norm(v)

mikrofon örneğinde

v = sample_tangent_unit(mu)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.