web-dev-qa-db-ja.com

最高事後密度領域と中央信頼性領域

いくつかのパラメータΘに対する事後p(Θ| D)が与えられると、次のことができます 定義

最高事後密度領域:

最高事後密度領域は、合計で事後質量の100(1-α)%を構成するΘの最も可能性の高い値のセットです。

言い換えると、与えられたαに対して、以下を満たすp*を探します。

enter image description here

次に、最高事後密度領域をセットとして取得します。

enter image description here

中央信頼できる地域:

上記と同じ表記法を使用して、信頼できる領域(または間隔)は次のように定義されます。

enter image description here

分布によっては、そのような間隔が多数存在する可能性があります。 中央の信頼区間は、(1-α)/ 2質量が各テールである信頼区間として定義されます。

計算:

  • 一般的な分布の場合、分布からのサンプルが与えられた場合、上記の2つの量を取得するための組み込みがありますPythonまたはPyMC

  • 一般的なパラメトリック分布(ベータ、ガウスなど)の場合、 SciPy または statsmodels を使用してこれを計算するための組み込みまたはライブラリはありますか?

27

HPDを計算するには、pymc3を活用できます。例を次に示します。

import pymc3
from scipy.stats import norm
a = norm.rvs(size=10000)
pymc3.stats.hpd(a)
7
sushmit

私の理解では、「中央の信頼できる領域」は信頼区間の計算方法と何ら変わりはありません。必要なのは、alpha/21-alpha/2cdf関数の逆関数です。 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つのニースガウス分布を取得します。

enter image description here


[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*です。

enter image description here

14
behzad.nouri

別のオプション(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で使用されているものとまったく同じである必要があります。

8
aloctavodia

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%の中央信頼区間が得られると思います。

8
nstjhp

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)

上記の方法は、私が持っているデータに基づいて論理的な答えを与えてくれます!

6
user72564

中央の信頼区間は、次の2つの方法で取得できます。グラフィカルに、モデル内の変数でsummary_plotを呼び出すと、デフォルトでbpdに設定されているTrueフラグがあります。これをFalseに変更すると、中央の間隔が描画されます。 2番目に取得できるのは、モデルまたはノードでsummaryメソッドを呼び出すときです。事後分位数が得られ、外側の分位数はデフォルトで95%の中央区間になります(これはalpha引数で変更できます)。

2