Pythonでのフォンミーゼスフィッシャー分布からのサンプリング?


14

Pythonの多変量フォンミーゼスフィッシャー分布からサンプリングする簡単な方法を探しています。scipystatsモジュールnumpyモジュールを調べましたが、一変量のフォンミーゼス分布のみが見つかりました。利用可能なコードはありますか?まだ見つかりません。

どうやら、Wood(1994)は、このリンクに従ってvMF分布からサンプリングするためのアルゴリズムを設計しましたが、私は論文を見つけることができません。

-編集正確さのために、私は文献で見つけるのが難しいアルゴリズムに興味があります(ほとんどの論文は焦点を当てています)。私の知る限り、独創的な記事(Wood、1994)は無料で見つけることができません。S2


1
への入力scipy.stats.vonmisesは配列のようにすることができるため、分布をとして指定できますarray。この例を
-rightskewed

ご回答有難うございます。しかし、実際のnD von Mises-Fisherよりも1-D von Misesの積のようですK = vonmises.pdf([x,x], kappa=[[1],[10]])。2次元vMFには、パラメータとして1つの実数のみを含める必要があります。同意しますか?κ
マイク

私は元々フォン・ミーゼス・フィッシャー分布のシミュレーション(Wood、1994)でVM *アルゴリズムを探しています。誰でも?
マイク

3
ここでこのスレッドの答えは本当に便利だと思いました。私は、このパッケージの一部としてこれを行うには少しクリーンアップユーティリティ関数を提供してきました:https://github.com/clara-labs/spherecluster/blob/develop/spherecluster/util.py、それらはまだこれを生成するために探してデータ。
ジャスカ

回答:


11

ついにできた。これが私の答えです。

最終的に、Directional Statistics(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

その後、所望のサンプリングは、wは拒絶サンプリング・スキームの結果であり、そしてvは均一超球上にサンプリングされます。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

(ここで書式設定についておaび申し上げます。最近このことを理解しようとしていたので、この質問に答えるためだけにアカウントを作成しました)。

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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.