22

誰かが助けてくれるかどうか疑問に思っている一般的な問題に遭遇しました。私はよく pymc3 を 2 つのモードで使用したいと思います: トレーニング (つまり、実際にパラメーターの推論を実行する) と評価 (つまり、推論されたパラメーターを使用して予測を生成する) です。

一般に、ポイントごとの推定だけでなく、予測よりも事後が必要です(それはベイジアンフレームワークの利点の一部ですよね?)。トレーニング データが固定されている場合、これは通常、類似した形式のシミュレートされた変数を観測された変数に追加することによって達成されます。例えば、

from pymc3 import *

with basic_model:

    # Priors for unknown model parameters
    alpha = Normal('alpha', mu=0, sd=10)
    beta = Normal('beta', mu=0, sd=10, shape=2)
    sigma = HalfNormal('sigma', sd=1)

    # Expected value of outcome
    mu = alpha + beta[0]*X1 + beta[1]*X2

    # Likelihood (sampling distribution) of observations
    Y_obs = Normal('Y_obs', mu=mu, sd=sigma, observed=Y)
    Y_sim = Normal('Y_sim', mu=mu, sd=sigma, shape=len(X1))

    start = find_MAP()
    step = NUTS(scaling=start)
    trace = sample(2000, step, start=start)

しかし、データが変更された場合はどうなりますか? 新しいデータに基づいて予測を生成したいとしますが、推論を最初から実行する必要はありません。理想的には、theano 計算グラフを介して新しいデータを単純に実行する、predict_posterior(X1_new, X2_new, 'Y_sim', trace=trace)またはのような関数が必要です。predict_point(X1_new, X2_new, 'Y_sim', vals=trace[-1])

私の質問の一部は、pymc3 が theano 計算グラフを実装する方法に関連していると思います。関数model.Y_sim.evalは私が望むものと似ているように見えますがY_sim、入力として必要であり、与えられたものを返すだけのようです。

このプロセスは非常に一般的だと思いますが、それを行う方法が見つからないようです。どんな助けでも大歓迎です。(また、pymc2 でこれを行うためのハックがあることにも注意してください。pymc3 では、theano のためにより困難です。)

4

2 に答える 2

13

注: この機能は現在、pymc.sample_ppcメソッドとしてコア コードに組み込まれています。詳細については、ドキュメントをご覧ください。

twiecki から送信されたこのリンク(2017 年 7 月時点で無効) に基づいて、私の問題を解決するためのいくつかのトリックがあります。1 つ目は、トレーニング データを共有 theano 変数に入れることです。これにより、theano 計算グラフを台無しにすることなく、後でデータを変更できます。

X1_shared = theano.shared(X1)
X2_shared = theano.shared(X2)

次に、モデルを構築し、通常どおり推論を実行しますが、共有変数を使用します。

with basic_model:

    # Priors for unknown model parameters
    alpha = Normal('alpha', mu=0, sd=10)
    beta = Normal('beta', mu=0, sd=10, shape=2)
    sigma = HalfNormal('sigma', sd=1)

    # Expected value of outcome
    mu = alpha + beta[0]*X1_shared + beta[1]*X2_shared

    # Likelihood (sampling distribution) of observations
    Y_obs = Normal('Y_obs', mu=mu, sd=sigma, observed=Y)

    start = find_MAP()
    step = NUTS(scaling=start)
    trace = sample(2000, step, start=start)

最後に、新しいデータの事後予測を可能にする開発中の関数があります (最終的には pymc3 に追加される可能性があります)。

from collections import defaultdict

def run_ppc(trace, samples=100, model=None):
    """Generate Posterior Predictive samples from a model given a trace.
    """
    if model is None:
         model = pm.modelcontext(model)

    ppc = defaultdict(list)
    for idx in np.random.randint(0, len(trace), samples):
        param = trace[idx]
        for obs in model.observed_RVs:
            ppc[obs.name].append(obs.distribution.random(point=param))

    return ppc

次に、予測を実行する新しいデータを渡します。

X1_shared.set_value(X1_new)
X2_shared.set_value(X2_new)

最後に、新しいデータの事後予測サンプルを生成できます。

ppc = run_ppc(trace, model=model, samples=200)

変数ppcは、モデル内の観測された各変数のキーを持つディクショナリです。したがって、この場合ppc['Y_obs']、配列のリストが含まれます。各配列は、トレースからのパラメーターの単一セットを使用して生成されます。

トレースから抽出されたパラメーターを変更することもできることに注意してください。たとえば、GaussianRandomWalk変数を使用するモデルがあり、将来の予測を生成したいと考えていました。pymc3 が未来にサンプリングできるようにする (つまり、ランダム ウォーク変数が発散できるようにする) こともできますが、最後の推定値に対応する係数の固定値を使用したかっただけです。このロジックは、run_ppc関数に実装できます。

run_ppc関数が非常に遅いことにも言及する価値があります。実際の推論を実行するのと同じくらいの時間がかかります。これは、theano の使用方法に関連する非効率性に関係していると思われます。

編集: 最初に含まれていたリンクは無効になっているようです。

于 2015-10-22T21:16:10.063 に答える