Python의 von Mises-Fisher 배포에서 샘플링?


14

파이썬에서 다변량 von Mises-Fisher 분포 에서 샘플링하는 간단한 방법을 찾고 있습니다. scipynumpy 모듈통계 모듈을 살펴 보았지만 일 변량 폰 미제스 분포 만 찾았습니다. 사용 가능한 코드가 있습니까? 아직 찾지 못했습니다.

분명히 Wood (1994)는 이 링크 에 따라 vMF 배포에서 샘플링하기위한 알고리즘을 설계 했지만 논문을 찾을 수 없습니다.

-편집 정확성을 위해 문헌에서 찾기 어려운 알고리즘에 관심이 있습니다 (대부분의 논문은 중점을 둡니다 ). 중요한 기사 (Wood, 1994)는 제 지식으로는 무료로 찾을 수 없습니다.에스2


1
입력 scipy.stats.vonmises은 배열과 같을 수 있으므로 분포를로 지정할 수 있습니다 array. 이 참조
rightskewed

답변 주셔서 감사합니다. 그러나 실제 nD von Mises-Fisher보다 1D von Mises의 제품 인 것 같습니다 K = vonmises.pdf([x,x], kappa=[[1],[10]]). 2 차원 vMF에는 매개 변수로 하나의 실수 만 있어야합니다 . 동의하십니까? κ
마이크

원래 폰 미제스 피셔 분포 시뮬레이션 (Wood, 1994)에서 알고리즘 VM *을 찾고 있습니다. 누군가?
마이크

3
이 스레드의 답변이 실제로 유용하다는 것을 알았습니다. 나는이 패키지의 한 부분으로이 작업을 수행하는 약간 정리 유틸리티 기능을 제공했습니다 https://github.com/clara-labs/spherecluster/blob/develop/spherecluster/util.py을 , 사람들을 위해 여전히를 생성하기 위해 찾고 데이터.
Jaska

답변:


11

마침내 나는 그것을 얻었다. 여기 내 대답이 있습니다.

마지막으로 방향 통계 (Mardia and 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

그런 다음 원하는 샘플링은 V12+μV

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)

3
(+1) 답변을 공유해 주셔서 감사합니다 (특히 처음에 질문을 닫을 가능성이 낮음에도 불구하고)!
whuber

4

(여기서 형식화에 대해 사과드립니다. 최근 에이 문제를 파악하려고했기 때문에이 질문에 답하기 위해 계정을 만들었습니다.)

마이크의 대답은 옳지 않습니다, 벡터 V 에서 와야한다 에스2 접하는 공간에서 μ, 그건, V 에 직교하는 단위 벡터 여야합니다 μ. 그렇지 않으면 벡터V12+μ표준이 없습니다. 마이크가 제공 한 예제에서이를 확인할 수 있습니다. 이 문제를 해결하려면 다음과 같이 사용하십시오.

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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.