0

ステップごとにサンプリングするときにサンプラーが非常に遅い理由を知りたいです。たとえば、次のように実行すると:

mcmc = MCMC(model)
mcmc.sample(1000)

サンプリングは高速です。ただし、実行すると:

mcmc = MCMC(model)
for i in arange(1000):
    mcmc.sample(1)

サンプリングは遅くなります (サンプリングが多いほど遅くなります)。

なぜ私がこれを尋ねているのか疑問に思っているなら..まあ、サンプラーの各ステップの後に変数の値に対していくつかの操作を実行したいので、段階的なサンプリングが必要です。

それをスピードアップする方法はありますか?

前もって感謝します!

- - - - - - - - - 編集 - - - - - - - - - - - - - - - - ------------------------------

ここで、特定の問題をより詳細に提示します。

競合する 2 つのモデルがあり、それらは 2 つの間の「スイッチ」として機能するカテゴリ変数を持つより大きなモデルの一部です。

このおもちゃの例では、観測されたベクトル 'Y' があり、これはポアソン分布または幾何分布で説明できます。カテゴリ変数 'switch_model' は、= 0 の場合は幾何モデルを選択し、=1 の場合はポアソン モデルを選択します。

各サンプルの後、switch_model が幾何学的モデルを選択した場合、ポアソン モデルの変数は更新されないようにします。これは、可能性に影響を与えていないため、単に漂流しているだけだからです。switch_model がポアソン モデルを選択する場合は、その逆です。

基本的に、各ステップで行うことは、選択されていないモデルの値を手動で 1 ステップ戻すことによって「変更」することです。

私の説明とコメント付きのコードが十分に明確になることを願っています。詳細が必要な場合はお知らせください。

import numpy as np
import pymc as pm
import pandas as pd
import matplotlib.pyplot as plt

# OBSERVED VALUES
Y = np.array([0, 1, 2, 3, 8])

# PRIOR ON THE MODELS
pi = (0.5, 0.5)

switch_model = pm.Categorical("switch_model", p = pi) 
# switch_model = 0 for Geometric, switch_model = 1 for Poisson

p = pm.Uniform('p', lower = 0, upper = 1) # Prior of the parameter of the geometric distribution
mu = pm.Uniform('mu', lower = 0, upper = 10) # Prior of the parameter of the Poisson distribution


# LIKELIHOOD
@pm.observed
def Ylike(value = Y, mu = mu, p = p, M = switch_model):
    if M == 0:
        out = pm.geometric_like(value+1, p)
    elif M == 1:
        out = pm.poisson_like(value, mu)
    return out

model = pm.Model([Ylike, p, mu, switch_model])

mcmc = pm.MCMC(model)

n_samples = 5000

traces = {}
for var in mcmc.stochastics:
    traces[str(var)] = np.zeros(n_samples)


bar = pm.progressbar.progress_bar(n_samples)
bar.update(0)

mcmc.sample(1, progress_bar=False)
for var in mcmc.stochastics:
    traces[str(var)][0] = mcmc.trace(var)[-1]


for i in np.arange(1,n_samples):
    mcmc.sample(1, progress_bar=False)
    bar.update(i)
    for var in mcmc.stochastics:
        traces[str(var)][i] = mcmc.trace(var)[-1]
    if mcmc.trace('switch_model')[-1] == 0: # Gemetric wins
        traces['mu'][i] = traces['mu'][i-1] # One step back for the sampler of the Poisson parameter
        mu.value = traces['mu'][i-1]

    elif mcmc.trace('switch_model')[-1] == 1: # Poisson wins
        traces['p'][i] = traces['p'][i-1] # One step back for the sampler of the Geometric parameter
        p.value = traces['p'][i-1]

print '\n\n'

traces=pd.DataFrame(traces)

traces['mu'][traces['switch_model'] == 0] = np.nan
traces['p'][traces['switch_model'] == 1] = np.nan

print traces.describe()

traces.plot()
plt.show()
4

2 に答える 2

0

実際、私は「クレイジーな」解決策を見つけました。なぜそれが機能するのかを容疑者に知ってもらいました。私はまだ私のトリックについて専門家の意見を得たいと思っています.

基本的に、for ループを次のように変更し、1000 ループごとに「mcmc のリセット」を追加すると、サンプリングが再び開始されます。

for i in np.arange(1,n_samples):
    mcmc.sample(1, progress_bar=False)
    bar.update(i)
    for var in mcmc.stochastics:
        traces[str(var)][i] = mcmc.trace(var)[-1]
    if mcmc.trace('switch_model')[-1] == 0: # Gemetric wins
        traces['mu'][i] = traces['mu'][i-1] # One step back for the sampler of the Poisson parameter
        mu.value = traces['mu'][i-1]

    elif mcmc.trace('switch_model')[-1] == 1: # Poisson wins
        traces['p'][i] = traces['p'][i-1] # One step back for the sampler of the Geometric parameter
        p.value = traces['p'][i-1]

    if i%1000 == 0:
        mcmc = pm.MCMC(model)

実際には、このトリックは 1000 ステップごとにサンプラーのトレースとデータベースを消去します。理由はよくわかりませんが、サンプラーは長いデータベースを好まないようです。(もちろん、1000 ステップは任意です。短すぎるとオーバーヘッドが大きくなり、長すぎるとトレースとデータベースが長くなりすぎます)。

このハックは少しクレイジーで、間違いなくエレガントではないと思います..専門家または開発者のいずれかがそれについてコメントしていますか? ありがとうございました!

于 2014-03-23T02:10:59.230 に答える