Path: blob/master/site/ja/probability/examples/Modeling_with_JointDistribution.ipynb
25118 views
Copyright 2019 The TensorFlow Authors.
Licensed under the Apache License, Version 2.0 (the "License");
同時分布を使用してベイズモデルを構築する
JointDistributionSequential
は、新しく導入された分布のようなクラスであり、ベイズモデルのプロトタイプを迅速に作成できるようにします。複数の分布を連鎖し、ラムダ関数を使用して依存関係を導入できます。これは、GLM、混合効果モデル、混合モデルなどの多くの一般的に使用されるモデルを含む、中小規模のベイズモデルを構築するように設計されています。これにより、事前予測サンプリングなどベイジアンワークフローに必要なすべての機能を利用できます。また、別の大規模なベイジアングラフィカルモデルまたはニューラルネットワークにプラグインできます。このコラボでは、JointDistributionSequential
を使用して日常的なベイズワークフローを実行する方法の例をいくつか示します。
依存関係と前提条件
迅速に作成
はじめる前に、このデモに GPU を使用していることを確認します。
[ランタイム] -> [ランタイムタイプの変更] -> [ハードウェアアクセラレータ] -> [GPU] を選択します。
次のスニペットは、GPU にアクセスできることを確認します。
注意: 何らかの理由で GPU にアクセスできない場合でも、このコラボは機能します (トレーニングには時間がかかります)。
JointDistribution
注意: この分布クラスは、モデルが単純である場合に役立ちます。「単純」とは、連鎖のようなグラフを意味しますが、このアプローチは、単一ノードで最大 255 の次数(Python 関数の最大引数のため)を持つすべての PGM で技術的に機能します。
基本的な考え方は、PGM の頂点ごとに 1 つの tfp.Distribution
インスタンスを生成する callable
のリストをユーザーに指定させることです。callable
には、最大リスト内のインデックスと同じ数の引数があります。(便宜のために、引数は作成の逆の順序で渡されます。) 内部的には、以前のすべての RV の値をそれぞれの呼び出し可能オブジェクトに渡すだけで、「グラフをウォーク」し、[確率の連鎖律]を実装します。(https://en.wikipedia.org/wiki/Chain_rule_(probability)#More_than_two_random_variables): 。
Python コードですが、非常に単純です。要点は次のとおりです。
JointDistributionSequential
の docstring から詳細情報を見つけることができます。要点はクラスを初期化するために分布のリストを渡すことです。リスト内の一部の分布が別の上流の分布/変数からの出力に依存している場合、ラムダ関数でラップするだけです。実際にどのように機能するか見てみましょう。
(ロバスト)線形回帰
出典: PyMC3 doc GLM: Robust Regression with Outlier Detection
従来の OLS モデル
それでは、線形モデル、単純な切片および勾配回帰問題を設定しましょう。
次に、モデルのグラフをチェックして、依存関係を確認します。x
は最後のノードの名前として予約されており、JointDistributionSequential モデルのラムダ引数として使用できないことに注意してください。
モデルからのサンプリングは非常に簡単です。
...これは tf.Tensor のリストを提供します。すぐに log_prob 関数にプラグインして、モデルの log_prob を計算できます。
何かおかしいですね。log_prob はスカラーを取得するはずです。.log_prob_parts
を呼び出すことで、グラフィカルモデルの各ノードの log_prob
が得られ、問題を確認できます。
...最後のノードが i.i.d 次元/軸に沿って reduce_sum されていないことが分かりました。合計すると、最初の 2 つの変数が誤ってブロードキャストされます。
ここでの秘訣は、tfd.Independent
を使用してバッチ形状を再解釈することです (軸の残りの部分が正しく縮小されます)。
ここで、モデルの最後のノード/分布を確認してみましょう。イベントの形状が正しく解釈されていることがわかります。reinterpreted_batch_ndims
を正しく取得するには、少し試行錯誤が必要な場合がありますが、分布またはサンプリングされたテンソルをいつでも簡単に出力して、形状を再確認できます。
他の JointDistribution*
API
MLE
これで推論できるようになりました。オプティマイザを使用すると最尤推定を見つけることができます。
バッチバージョンモデルと MCMC
ベイズ推定では、通常、MCMC サンプルを使用します。サンプルが事後分布からのものである場合、それらを any 関数にプラグインして、期待値を計算できるためです。ただし、MCMC API では、バッチフレンドリーなモデルを作成する必要があります。sample([...])
を呼び出すことで、私たちのモデルが実際に「バッチ処理可能」でないことを確認できます。
この場合、モデル内には線形関数しかないため、比較的簡単です。形状を拡張するだけです。
log_prob_parts を再度サンプリングして評価し、確認します。
注意:
モデルのバッチバージョンを使用するとマルチチェーン MCMC で最も迅速に作業できます。モデルをバッチバージョンとして書き直すことができない場合 (ODE モデルなど)、
tf.map_fn
を使用して log_prob 関数をマップし、同じ効果を得ることができます。事前スケーラーがあるため
scaler_tensor[:, None]
を実行できないので、mdl_ols_batch.sample()
は機能しない可能性があります。ここでの解決策は、tfd.Sample(..., sample_shape=1)
をラップして、スケーラーテンソルをランク 1 に拡張することです。モデルを関数として記述して、ハイパーパラメータなどの設定を簡単に変更できるようにすることをお勧めします。
No-U-Turn サンプラーを使用した MCMC
Student-T メソッド
以下では常にモデルのバッチバージョンを使用するので注意してください
事前予測サンプリング
MLE
MCMC
階層的な部分プーリング
出典: PyMC3 baseball data for 18 players from Efron and Morris (1975)
事前予測サンプリング
繰り返しますが、Independent を使用しないと、batch_shape が間違った log_prob になってしまうことに注意してください。
MLE
tfp.optimizer
の優れた機能は、開始点の k バッチに対して並列に最適化し、stopping_condition
kwarg を指定できることです。これを tfp.optimizer.converged_all
に設定して、すべてが同じ最小値を見つけるかどうかを確認するか、tfp.optimizer.converged_any
に設定してローカルソリューションをすばやく見つけることができます。
LBFGS は収束しませんでした。
MCMC
混合効果モデル (ラドン)
PyMC3 doc: A Primer on Bayesian Methods for Multilevel Modeling の最後のモデル
事前のいくつかの変更 (小規模化など)
複雑な変換を伴うモデルの場合、機能的なスタイルで実装すると、書き込みとテストがはるかに簡単になります。また、入力データの (ミニバッチ) を条件とする log_prob 関数をプログラムで生成するのが大幅に簡単になります。
変分推論
JointDistribution*
の非常に強力な機能の 1 つは、VI の近似を簡単に生成できることです。たとえば、平均場 ADVI を実行するには、グラフを調べて、観測されていないすべての分布を正規分布に置き換えるだけです。
平均場 ADVI
tensorflow_probability/python/experimental/vi の実験的機能を使用して、変分近似を構築することもできます。これは基本的に以下で使用されるロジックと同じですが (つまり、JointDistribution を使用して近似を作成)、近似出力は無制限の空間ではなく元の空間を使用します。
FullRank ADVI
FullRank ADVI では、多変量ガウス分布で事後分布を近似します。
ベータベルヌーイ混合モデル
複数のレビューアが未知の (真の) 潜在ラベルを使用していくつかのアイテムにラベルを付ける混合モデル。