Выборка из дистрибутива фон Мизеса-Фишера в Python?

14

Я ищу простой способ выбрать из многомерного дистрибутива фон Мизеса-Фишера в Python. Я просмотрел модуль stats в scipy и numpy module, но нашел только одномерное распределение фон Мизеса. Есть ли код? Я еще не нашел.

Очевидно, Вуд (1994) разработал алгоритм для выборки из распределения vMF по этой ссылке , но я не могу найти статью.

- edit Для точности меня интересует алгоритм, который трудно найти в литературе (большинство статей посвящено ). Насколько мне известно, оригинальная статья (Wood, 1994) не может быть найдена бесплатно.S2

микрофон
источник
1
Входные данные scipy.stats.vonmisesмогут быть в виде массива, поэтому вы можете указать распределение как array. Посмотрите на этот пример
права искал
Спасибо за Ваш ответ. Но, похоже, это больше произведение 1-й фон Мизес, чем настоящий н-фон Мизес-Фишер K = vonmises.pdf([x,x], kappa=[[1],[10]]). 2-D vMF должен иметь только один реальный качестве параметра. Вы согласны? κ
микрофон
Я ищу алгоритм VM * первоначально в моделировании распределения Мизера Фишера (Wood, 1994). Кто-нибудь?
микрофон
3
Я нашел ответы в этой теме здесь действительно полезными. Я предоставил слегка очищенную служебную функцию, чтобы сделать это как часть этого пакета: https://github.com/clara-labs/spherecluster/blob/develop/spherecluster/util.py , для тех, кто все еще хочет создать это данные.
Яска

Ответы:

11

Наконец то я понял. Вот мой ответ.

Наконец, я положил руки на Статистику Направления (Mardia and Jupp, 1999) и алгоритм Ульриха-Вуда для отбора проб. Я публикую здесь то, что понял из него, т.е. мой код (на 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

v1w2+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

И, для эффективной выборки с этим кодом, вот пример:

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

(Я прошу прощения за форматирование здесь, я создал учетную запись, чтобы ответить на этот вопрос, так как я также пытался выяснить это в последнее время).

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)

и заменить

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

в примере с микрофоном с призывом к

v = sample_tangent_unit(mu)
Kevin
источник