_PyMC3
_とREAL DATAを使用して、ベイジアン線形回帰モデルを実装しようとしています。 (つまり、線形関数+ガウスノイズからではありません)_sklearn.datasets
_のデータセットから。形状が_(442, 10)
_である属性の数が最も少ない回帰データセット(つまり、load_diabetes()
)を選択しました。つまり、_442 samples
_および_10 attributes
_です。
私はモデルが機能していると信じています。事後確率は、このようなものがどのように機能するかを理解するために試して予測するのに十分まともなように見えますが...これらのベイジアンモデルで予測する方法がわからないことに気付きました! glm
およびpatsy
表記を使用するときに実際に何が起こっているのかを理解するのが難しいため、この表記の使用を避けようとしています。
私は次のことを試みました: pymc3の推定パラメーターから予測を生成する そして http://pymc-devs.github.io/pymc3/posterior_predictive/ しかし、私のモデルは非常にひどいです予測するか、私はそれを間違っています。
私が実際に予測を正しく行っている場合(おそらくそうではありません)、誰かが私のモデルを最適化するのを手伝ってくれますか?少なくとも_mean squared error
_、_absolute error
_、またはそのようなものがベイジアンフレームワークで機能するかどうかはわかりません。理想的には、number_of_rows = _X_te
_属性/データテストセットの行数、および事後分布からのサンプルとなる列の数の配列を取得したいと思います。
_import pymc3 as pm
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
from scipy import stats, optimize
from sklearn.datasets import load_diabetes
from sklearn.cross_validation import train_test_split
from theano import shared
np.random.seed(9)
%matplotlib inline
#Load the Data
diabetes_data = load_diabetes()
X, y_ = diabetes_data.data, diabetes_data.target
#Split Data
X_tr, X_te, y_tr, y_te = train_test_split(X,y_,test_size=0.25, random_state=0)
#Shapes
X.shape, y_.shape, X_tr.shape, X_te.shape
#((442, 10), (442,), (331, 10), (111, 10))
#Preprocess data for Modeling
shA_X = shared(X_tr)
#Generate Model
linear_model = pm.Model()
with linear_model:
# Priors for unknown model parameters
alpha = pm.Normal("alpha", mu=0,sd=10)
betas = pm.Normal("betas", mu=0,#X_tr.mean(),
sd=10,
shape=X.shape[1])
sigma = pm.HalfNormal("sigma", sd=1)
# Expected value of outcome
mu = alpha + np.array([betas[j]*shA_X[:,j] for j in range(X.shape[1])]).sum()
# Likelihood (sampling distribution of observations)
likelihood = pm.Normal("likelihood", mu=mu, sd=sigma, observed=y_tr)
# Obtain starting values via Maximum A Posteriori Estimate
map_estimate = pm.find_MAP(model=linear_model, fmin=optimize.fmin_powell)
# Instantiate Sampler
step = pm.NUTS(scaling=map_estimate)
# MCMC
trace = pm.sample(1000, step, start=map_estimate, progressbar=True, njobs=1)
#Traceplot
pm.traceplot(trace)
_
_# Prediction
shA_X.set_value(X_te)
ppc = pm.sample_ppc(trace, model=linear_model, samples=1000)
#What's the shape of this?
list(ppc.items())[0][1].shape #(1000, 111) it looks like 1000 posterior samples for the 111 test samples (X_te) I gave it
#Looks like I need to transpose it to get `X_te` samples on rows and posterior distribution samples on cols
for idx in [0,1,2,3,4,5]:
predicted_yi = list(ppc.items())[0][1].T[idx].mean()
actual_yi = y_te[idx]
print(predicted_yi, actual_yi)
# 158.646772735 321.0
# 160.054730647 215.0
# 149.457889418 127.0
# 139.875149489 64.0
# 146.75090354 175.0
# 156.124314452 275.0
_
モデルの問題の1つは、データのスケールが大きく異なることだと思います。「X」の範囲は最大0.3、「Y」の範囲は最大300です。したがって、事前確率で指定されているより大きな勾配(およびシグマ)を期待する必要があります。論理的なオプションの1つは、次の例のように事前確率を調整することです。
_#Generate Model
linear_model = pm.Model()
with linear_model:
# Priors for unknown model parameters
alpha = pm.Normal("alpha", mu=y_tr.mean(),sd=10)
betas = pm.Normal("betas", mu=0, sd=1000, shape=X.shape[1])
sigma = pm.HalfNormal("sigma", sd=100) # you could also try with a HalfCauchy that has longer/fatter tails
mu = alpha + pm.dot(betas, X_tr.T)
likelihood = pm.Normal("likelihood", mu=mu, sd=sigma, observed=y_tr)
step = pm.NUTS()
trace = pm.sample(1000, step)
chain = trace[100:]
pm.traceplot(chain);
_
事後予測チェックは、多かれ少なかれ合理的なモデルがあることを示します。
_sns.kdeplot(y_tr, alpha=0.5, lw=4, c='b')
for i in range(100):
sns.kdeplot(ppc['likelihood'][i], alpha=0.1, c='g')
_
もう1つのオプションは、データを標準化して同じスケールに配置することです。そうすることで、勾配が+ -1前後になり、一般に、任意のデータに同じ拡散事前分布を使用できます(情報がない限り便利です)。使用できる事前確率)。実際、多くの人が一般化線形モデルにこの方法を推奨しています。これについては、本で詳しく読むことができます ベイジアンデータ分析を行う または 統計的再考
値を予測したい場合は、いくつかのオプションがあります。1つは、次のような推定パラメーターの平均を使用することです。
_alpha_pred = chain['alpha'].mean()
betas_pred = chain['betas'].mean(axis=0)
y_pred = alpha_pred + np.dot(betas_pred, X_tr.T)
_
もう1つのオプションは、_pm.sample_ppc
_を使用して、推定の不確実性を考慮した予測値のサンプルを取得することです。
PPCを実行する主なアイデアは、予測値をデータと比較して、両方が一致する場所と一致しない場所を確認することです。この情報は、たとえばモデルを改善するために使用できます。
pm.sample_ppc(trace, model=linear_model, samples=100)
それぞれが331個の予測観測値を持つ100個のサンプルを提供します(この例では、_y_tr
_の長さは331であるため)。したがって、予測された各データポイントを、後方から取得したサイズ100のサンプルと比較できます。事後分布自体が可能なパラメーターの分布であるため、予測値の分布が得られます(分布は不確実性を反映しています)。 _sample_ppc
_の引数に関して:samples
は、後方から取得するポイントの数を指定します。各ポイントはパラメーターのベクトルです。 size
は、パラメーターのベクトルを使用して予測値をサンプリングする回数を指定します(デフォルトでは_size=1
_)。
この中で_sample_ppc
_を使用する他の例があります チュートリアル
(X --u)/σを標準化すると、ベータの分散はすべての変数で均一ですが、スケールが異なるため、独立変数もうまく機能する可能性があります。
もう1つのポイントは、pm.math.dot
を使用する場合、f(x) =切片+Xβ+εであるとすると、行列ベクトル積を計算する方が効率的かもしれません。