いくつかのパラメータΘに対する事後p(Θ| D)が与えられると、次のことができます 定義 :
最高事後密度領域は、合計で事後質量の100(1-α)%を構成するΘの最も可能性の高い値のセットです。
言い換えると、与えられたαに対して、以下を満たすp*を探します。
次に、最高事後密度領域をセットとして取得します。
上記と同じ表記法を使用して、信頼できる領域(または間隔)は次のように定義されます。
分布によっては、そのような間隔が多数存在する可能性があります。 中央の信頼区間は、(1-α)/ 2質量が各テールである信頼区間として定義されます。
一般的な分布の場合、分布からのサンプルが与えられた場合、上記の2つの量を取得するための組み込みがありますPythonまたはPyMC ?
一般的なパラメトリック分布(ベータ、ガウスなど)の場合、 SciPy または statsmodels を使用してこれを計算するための組み込みまたはライブラリはありますか?
HPDを計算するには、pymc3を活用できます。例を次に示します。
import pymc3
from scipy.stats import norm
a = norm.rvs(size=10000)
pymc3.stats.hpd(a)
私の理解では、「中央の信頼できる領域」は信頼区間の計算方法と何ら変わりはありません。必要なのは、alpha/2
と1-alpha/2
のcdf
関数の逆関数です。 scipy
では、これはppf
(パーセンテージポイント関数)と呼ばれます。ガウス事後分布について:
>>> from scipy.stats import norm
>>> alpha = .05
>>> l, u = norm.ppf(alpha / 2), norm.ppf(1 - alpha / 2)
[l, u]
が事後密度の(1-alpha)
をカバーしていることを確認するには:
>>> norm.cdf(u) - norm.cdf(l)
0.94999999999999996
同様に、a=1
およびb=3
と言うベータ事後確率の場合:
>>> from scipy.stats import beta
>>> l, u = beta.ppf(alpha / 2, a=1, b=3), beta.ppf(1 - alpha / 2, a=1, b=3)
そしてまた:
>>> beta.cdf(u, a=1, b=3) - beta.cdf(l, a=1, b=3)
0.94999999999999996
ここ scipyに含まれているパラメトリック分布を見ることができます。そして、それらすべてにppf
関数があると思います。
pdf
関数は必ずしも可逆ではないため、最高事後密度領域に関しては、より注意が必要です。そして一般的に、そのような地域は接続さえされていないかもしれません。たとえば、a = b = .5
のベータ版の場合(ご覧のとおり ここ );
しかし、ガウス分布の場合、「最高事後密度領域」が「中央信頼性領域」と一致していることが簡単にわかります。これは、すべての対称ユニモーダル分布に当てはまると思います(つまり、pdf関数が分布モードの周りで対称である場合)
一般的なケースで考えられる数値アプローチは、pdf
の- 数値積分 を使用してp*
の値を二分探索することです。積分がp*
の単調関数であるという事実を利用します。
混合ガウスの例を次に示します。
[1]最初に必要なのは分析pdf関数です。簡単な混合ガウス分布の場合:
def mix_norm_pdf(x, loc, scale, weight):
from scipy.stats import norm
return np.dot(weight, norm.pdf(x, loc, scale))
たとえば、場所、スケール、重量の値については、
loc = np.array([-1, 3]) # mean values
scale = np.array([.5, .8]) # standard deviations
weight = np.array([.4, .6]) # mixture probabilities
手をつないでいる2つのニースガウス分布を取得します。
[2]ここで、p*
のテスト値を指定してp*
の上にpdf関数を統合して返すエラー関数が必要です。目的の値からの二乗誤差1 - alpha
:
def errfn( p, alpha, *args):
from scipy import integrate
def fn( x ):
pdf = mix_norm_pdf(x, *args)
return pdf if pdf > p else 0
# ideally integration limits should not
# be hard coded but inferred
lb, ub = -3, 6
prob = integrate.quad(fn, lb, ub)[0]
return (prob + alpha - 1.0)**2
[3]ここで、alpha
の特定の値に対して、エラー関数を最小化してp*
を取得できます。
alpha = .05
from scipy.optimize import fmin
p = fmin(errfn, x0=0, args=(alpha, loc, scale, weight))[0]
その結果、p* = 0.0450
になり、HPDは次のようになります。赤い領域は分布の1 - alpha
を表し、水平の破線はp*
です。
別のオプション(RからPythonに適合)で、John K. Kruschkeによる「ベイジアンデータ分析の実行」という本から引用したものは次のとおりです。
from scipy.optimize import fmin
from scipy.stats import *
def HDIofICDF(dist_name, credMass=0.95, **args):
# freeze distribution with given arguments
distri = dist_name(**args)
# initial guess for HDIlowTailPr
incredMass = 1.0 - credMass
def intervalWidth(lowTailPr):
return distri.ppf(credMass + lowTailPr) - distri.ppf(lowTailPr)
# find lowTailPr that minimizes intervalWidth
HDIlowTailPr = fmin(intervalWidth, incredMass, ftol=1e-8, disp=False)[0]
# return interval as array([low, high])
return distri.ppf([HDIlowTailPr, credMass + HDIlowTailPr])
アイデアは、lowTailPrで始まり、credMassの質量を持つ間隔の幅を返す関数intervalWidthを作成することです。 intervalWidth関数の最小値は、scipyの fmin 最小値を使用して設定されます。
たとえば、次の結果です。
print HDIofICDF(norm, credMass=0.95, loc=0, scale=1)
です
[-1.95996398 1.95996398]
HDIofICDFに渡される配布パラメーターの名前は、scipyで使用されているものとまったく同じである必要があります。
PyMCには、hpdを計算するための組み込み関数があります。 v2.3では、utilsにあります。ソースを参照してください ここ 。線形モデルとそのHPDの例として
import pymc as pc
import numpy as np
import matplotlib.pyplot as plt
## data
np.random.seed(1)
x = np.array(range(0,50))
y = np.random.uniform(low=0.0, high=40.0, size=50)
y = 2*x+y
## plt.scatter(x,y)
## priors
emm = pc.Uniform('m', -100.0, 100.0, value=0)
cee = pc.Uniform('c', -100.0, 100.0, value=0)
#linear-model
@pc.deterministic(plot=False)
def lin_mod(x=x, cee=cee, emm=emm):
return emm*x + cee
#likelihood
llhy = pc.Normal('y', mu=lin_mod, tau=1.0/(10.0**2), value=y, observed=True)
linearModel = pc.Model( [llhy, lin_mod, emm, cee] )
MCMClinear = pc.MCMC( linearModel)
MCMClinear.sample(10000,burn=5000,thin=5)
linear_output=MCMClinear.stats()
## pc.Matplot.plot(MCMClinear)
## print HPD using the trace of each parameter
print(pc.utils.hpd(MCMClinear.trace('m')[:] , 1.- 0.95))
print(pc.utils.hpd(MCMClinear.trace('c')[:] , 1.- 0.95))
分位数の計算を検討することもできます
print(linear_output['m']['quantiles'])
print(linear_output['c']['quantiles'])
ここで、2.5%から97.5%の値を取るだけで、95%の中央信頼区間が得られると思います。
MCMCサンプルからHDIを推定する方法を見つけようとしてこの投稿に出くわしましたが、どの答えもうまくいきませんでした。 aloctavodiaのように、私は本Doing Bayesian DataAnalysisのRの例をPythonに適合させました。 MCMCサンプルから95%のHDIを計算する必要がありました。これが私の解決策です:
import numpy as np
def HDI_from_MCMC(posterior_samples, credible_mass):
# Computes highest density interval from a sample of representative values,
# estimated as the shortest credible interval
# Takes Arguments posterior_samples (samples from posterior) and credible mass (normally .95)
sorted_points = sorted(posterior_samples)
ciIdxInc = np.ceil(credible_mass * len(sorted_points)).astype('int')
nCIs = len(sorted_points) - ciIdxInc
ciWidth = [0]*nCIs
for i in range(0, nCIs):
ciWidth[i] = sorted_points[i + ciIdxInc] - sorted_points[i]
HDImin = sorted_points[ciWidth.index(min(ciWidth))]
HDImax = sorted_points[ciWidth.index(min(ciWidth))+ciIdxInc]
return(HDImin, HDImax)
上記の方法は、私が持っているデータに基づいて論理的な答えを与えてくれます!
中央の信頼区間は、次の2つの方法で取得できます。グラフィカルに、モデル内の変数でsummary_plot
を呼び出すと、デフォルトでbpd
に設定されているTrue
フラグがあります。これをFalse
に変更すると、中央の間隔が描画されます。 2番目に取得できるのは、モデルまたはノードでsummary
メソッドを呼び出すときです。事後分位数が得られ、外側の分位数はデフォルトで95%の中央区間になります(これはalpha
引数で変更できます)。