ベイジアン事後確率のキャリブレーションをチェックするシミュレーションアルゴリズムの設定


8

何かをシミュレートする方法を理解することは、多くの場合、基本的な原理を理解するための最良の方法です。以下を正確にシミュレートする方法について、私は少し途方に暮れています。

仮定するとそのである事前分布有し。観測値サンプルに基づいて、単にと省略し、事後確率であることを非ベイジアンに示しは適切に調整されています。たとえば、Probここで、は事後確率です。関連ディスカッションはこちらμ N γ τ 2nはY 1... Y N Y μ > 0 | Y μ > 0 | P = P PYN(μ,σ2)μN(γ,τ2)nY1,,YnYμ>0|Y(μ>0|P)=PP

私が本当に示したいのは、事後確率が0.95などのレベルを超えたときに連続テストを行ってサンプリングを停止した場合、確率がはないということです。< 0.95μ>0<0.95

私は、タイプ1のエラーについての議論に踏み込むことなく、ベイジアン確率が意味があることを常連論者に説得しようとしています。帰無仮説を楽しませる常連客と話をするときに哲学上の問題があると思います。事前分布が(上記のように)連続である場合、ある確率はゼロであり、シミュレーションは不要です。問題全体をどのように考え、デモンストレーションシミュレーションを設計する方法についていくつかの提案をいただければ幸いです。私は、が1つの定数に設定されているだけで、なシミュレーションを行うことに慣れています。ベイジアンは条件付けません。μ μμ=0μμ

順次の状況では、可能な最大サンプルサイズを設定します(例:。n=1000

私がいつも考えるのに苦労している問題には微妙な問題があります。プロセスが実際にまったく効果がない()場合、本当の懐疑論者は、有効性の誤った主張()を心配することがあります。微妙なのは、懐疑論者が特別な値としてゼロを「単一化」していることであり、おそらくイベント(?)にゼロ以外の確率を与えています。事後者が調整されていることを示す方法では、懐疑者は実際に条件付けを行いたいと考えているため、ベイジアンとしては何がわかっているかでのみ条件付けを行うため、このような懐疑者を満足させることはできません。おそらくこれは、統計家が使用している事前分布が、懐疑論者が使用している不連続な事前分布と矛盾する場合でしょうか?μ = 0 μ = 0 μ = 0μ>0μ=0μ=0μ=0

回答:


6

シミュレーション結果は、シミュレーションでのパラメーターのサンプリング方法によって異なります。以前の確率がそうである場合、事後確率が(周波数の意味で)調整されるかどうかについては異論はないと思います。そのため、シミュレーションが新しいものをだれにも納得させないのではないかと思います。

とにかく、質問(3番目の段落)で言及されている順次サンプリングの場合、前の状態からを描画し、この与えられたサンプルをまで描画することで、「そのまま」シミュレーションできまたは他の終了基準が発生します(実行事後確率が超えないという正の確率があるため、別の終了基準が必要です)。次に、すべてのクレームについて、基になるサンプリングされたパラメータが正かどうかを確認し、真陽性と偽陽性の数を数えます。したがって、:μ P μ > 0 | サンプル> 0.95 0.95 P μ > 0 | サンプル> 0.95 μ iの= 1 2 ...μμp(μ>0samples)>0.950.95p(μ>0samples)>0.95μi=1,2,

  • サンプルμiN(γ,τ2)
  • j=1,
    • サンプルyi,jN(μi,σ2)
    • 計算するpi,j:=P(μi>0yi,1:j)
    • もしpi,j>0.95
      • 場合、真の正のカウンターをインクリメントしますμi>0
      • 場合、誤カウンタをインクリメントしますμi0
      • 内部のforループから抜け出す
    • などの他のいくつかの破損状態jjmax

すべての陽性に対する真陽性の比率は、少なくとも。これは、クレームのキャリブレーションを示しています。P μ > 0 D > 0.950.95P(μ>0D)>0.95

汚いPythonの実装(非常に可能性のあるバグ+予想されるキャリブレーションプロパティが保持されるのを確認するまでデバッグを行うと、潜在的な停止バイアスが発生します)。

# (C) Juho Kokkala 2016
# MIT License 

import numpy as np

np.random.seed(1)

N = 10000
max_samples = 50

gamma = 0.1
tau = 2
sigma = 1

truehits = 0
falsehits = 0

p_positivemus = []

while truehits + falsehits < N:
    # Sample the parameter from prior
    mu = np.random.normal(gamma, tau)

    # For sequential updating of posterior
    gamma_post = gamma
    tau2_post = tau**2

    for j in range(max_samples):
        # Sample data
        y_j = np.random.normal(mu, sigma)

        gamma_post = ( (gamma_post/(tau2_post) + y_j/(sigma**2)) /
                       (1/tau2_post + 1/sigma**2) )
        tau2_post = 1 / (1/tau2_post + 1/sigma**2)

        p_positivemu = 1 - stats.norm.cdf(0, loc=gamma_post,
                                          scale=np.sqrt(tau2_post))

        if p_positivemu > 0.95:
            p_positivemus.append(p_positivemu)
            if mu>0:
                truehits += 1
            else:
                falsehits +=1
            if (truehits+falsehits)%1000 == 0:
                print(truehits / (truehits+falsehits))
                print(truehits+falsehits)
            break

print(truehits / (truehits+falsehits))
print(np.mean(p_positivemus))

すべての申し立てに対する真の陽性の割合はでした。事後確率が正確にヒットしないため、これはを超えています。このため、このコードは「要求された」事後確率の平均も追跡します。この確率はです。0.95 0.95 0.98040.98070.950.950.9804

また、すべてのについて以前のパラメータを変更して、「すべての推論にわたって」調整を実証することもできます(事前計算が調整されている場合)。一方、「グラウンドトゥルースパラメーターの描画に使用されるものとは異なる」「間違った」以前のハイパーパラメーターから開始して事後更新を実行することもできます。その場合、キャリブレーションが保持されない可能性があります。Iγ,τi


これは非常に明確で非常に役立ちます。質問に別の段落を追加し、残りの問題を1つ残しています。カウント方法に加えて、私は真(サンプリング)に対する虚偽の主張の確率プロットに興味がありますおそらく黄土検量線を表示する-smoothedを。μ
Frank Harrell、2016年

以前の2つのパラメーターを変更する代わりに、順次評価でサンプルサイズを拡大して最大事後確率に対して描画されたをプロットすることは意味があり、解釈できるのではないかと思います。これは偽陽性と真陽性ではありませんが、おそらく別の形の校正ですか?μ
フランクハレル2016年

4

@ juho-kokkalaによる優れた回答を拡張し、ここでRを使用すると、結果が得られます。母集団の平均muの事前分布では、平均がゼロである2つの正規分布の等しい混合を使用しました。そのうちの1つは、大きな平均について非常に懐疑的です。

## Posterior density for a normal data distribution and for
## a mixture of two normal priors with mixing proportions wt and 1-wt
## and means mu1 mu2 and variances v1 an
## Adapted for LearnBayes package normal.normal.mix function

## Produces a list of 3 functions.  The posterior density and cum. prob.
## function can be called with a vector of posterior means and variances
## if the first argument x is a scalar

mixpost <- function(stat, vstat, mu1=0, mu2=0, v1, v2, wt) {
  if(length(stat) + length(vstat) != 2) stop('improper arguments')
  probs      <- c(wt, 1. - wt)
  prior.mean <- c(mu1, mu2)
  prior.var  <- c(v1,  v2)

  post.precision <- 1. / prior.var + 1. / vstat
  post.var       <- 1. / post.precision
  post.mean <- (stat / vstat + prior.mean / prior.var) / post.precision
  pwt       <- dnorm(stat, prior.mean, sqrt(vstat + prior.var))
  pwt       <- probs * pwt / sum(probs * pwt)

  dMix <- function(x, pwt, post.mean, post.var)
    pwt[1] * dnorm(x, mean=post.mean[1], sd=sqrt(post.var[1])) +
    pwt[2] * dnorm(x, mean=post.mean[2], sd=sqrt(post.var[2]))
  formals(dMix) <- z <-
    list(x=NULL, pwt=pwt, post.mean=post.mean, post.var=post.var)

  pMix <- function(x, pwt, post.mean, post.var)
    pwt[1] * pnorm(x, mean=post.mean[1], sd=sqrt(post.var[1])) +
    pwt[2] * pnorm(x, mean=post.mean[2], sd=sqrt(post.var[2]))
  formals(pMix) <- z

  priorMix <- function(x, mu1, mu2, v1, v2, wt)
    wt * dnorm(x, mean=mu1, sd=sqrt(v1)) +
    (1. - wt) * dnorm(x, mean=mu2, sd=sqrt(v2))
  formals(priorMix) <- list(x=NULL, mu1=mu1, mu2=mu2, v1=v1, v2=v2, wt=wt)
  list(priorMix=priorMix, dMix=dMix, pMix=pMix)
}

## mixposts handles the case where the posterior distribution function
## is to be evaluated at a scalar x for a vector of point estimates and
## variances of the statistic of interest
## If generates a single function

mixposts <- function(stat, vstat, mu1=0, mu2=0, v1, v2, wt) {
  post.precision1 <- 1. / v1 + 1. / vstat
  post.var1       <- 1. / post.precision1
  post.mean1      <- (stat / vstat + mu1 / v1) / post.precision1

  post.precision2 <- 1. / v2 + 1. / vstat
  post.var2       <- 1. / post.precision2
  post.mean2      <- (stat / vstat + mu2 / v2) / post.precision2

  pwt1 <- dnorm(stat, mean=mu1, sd=sqrt(vstat + v1))
  pwt2 <- dnorm(stat, mean=mu2, sd=sqrt(vstat + v2))
  pwt <- wt * pwt1 / (wt * pwt1 + (1. - wt) * pwt2)

  pMix <- function(x, post.mean1, post.mean2, post.var1, post.var2, pwt)
    pwt        * pnorm(x, mean=post.mean1, sd=sqrt(post.var1)) +
    (1. - pwt) * pnorm(x, mean=post.mean2, sd=sqrt(post.var2))
  formals(pMix) <-
    list(x=NULL, post.mean1=post.mean1, post.mean2=post.mean2,
         post.var1=post.var1, post.var2=post.var2, pwt=pwt)
 pMix
}

## Compute proportion mu > 0 in trials for
## which posterior prob(mu > 0) > 0.95, and also use a loess smoother
## to estimate prob(mu > 0) as a function of the final post prob
## In sequential analyses of observations 1, 2, ..., N, the final
## posterior prob is the post prob at the final sample size if the
## prob never exceeds 0.95, otherwise it is the post prob the first
## time it exceeds 0.95

sim <- function(N, prior.mu=0, prior.sd, wt, mucut=0, postcut=0.95,
                nsim=1000, plprior=TRUE) {
  prior.mu <- rep(prior.mu, length=2)
  prior.sd <- rep(prior.sd, length=2)
  sd1 <- prior.sd[1]; sd2 <- prior.sd[2]
  v1 <- sd1 ^ 2
  v2 <- sd2 ^ 2
  if(plprior) {
    pdensity <- mixpost(1, 1, mu1=prior.mu[1], mu2=prior.mu[2],
                        v1=v1, v2=v2, wt=wt)$priorMix
    x <- seq(-3, 3, length=200)
    plot(x, pdensity(x), type='l', xlab=expression(mu), ylab='Prior Density')
    title(paste(wt, 1 - wt, 'Mixture of Zero Mean Normals\nWith SD=',
                round(sd1, 3), 'and', round(sd2, 3)))
  }
  j <- 1 : N
  Mu <- Post <- numeric(nsim)
  stopped <- integer(nsim)

  for(i in 1 : nsim) {
    # See http://stats.stackexchange.com/questions/70855
    component <- sample(1 : 2, size=1, prob=c(wt, 1. - wt))
    mu <- prior.mu[component] + rnorm(1) * prior.sd[component]
    # mu <- rnorm(1, mean=prior.mu, sd=prior.sd) if only 1 component

    Mu[i] <- mu
    y  <- rnorm(N, mean=mu, sd=1)
    ybar <- cumsum(y) / j
    pcdf <- mixposts(ybar, 1. / j, mu1=prior.mu[1], mu2=prior.mu[2],
                     v1=v1, v2=v2, wt=wt)
    if(i==1) print(body(pcdf))
    post    <- 1. - pcdf(mucut)
    Post[i] <- if(max(post) < postcut) post[N]
               else post[min(which(post >= postcut))]
    stopped[i] <- if(max(post) < postcut) N else min(which(post >= postcut))
  }
  list(mu=Mu, post=Post, stopped=stopped)
}

# Take prior on mu to be a mixture of two normal densities both with mean zero
# One has SD so that Prob(mu > 1) = 0.1
# The second has SD so that Prob(mu > 0.25) = 0.05
prior.sd <- c(1 / qnorm(1 - 0.1), 0.25 / qnorm(1 - 0.05))
prior.sd
set.seed(2)
z <- sim(500, prior.mu=0, prior.sd=prior.sd, wt=0.5, postcut=0.95, nsim=10000)

事前:2つの正規分布の等しい混合

mu   <- z$mu
post <- z$post
st   <- z$stopped
plot(mu, post)
abline(v=0, col=gray(.8)); abline(h=0.95, col=gray(.8))
hist(mu[post >= 0.95], nclass=25)
k <- post >= 0.95
mean(k)   # 0.44 of trials stopped with post >= 0.95
mean(st)  # 313 average sample size
mean(mu[k] > 0)  # 0.963 of trials with post >= 0.95 actually had mu > 0
mean(post[k])    # 0.961 mean posterior prob. when stopped early
w <- lowess(post, mu > 0, iter=0)
# perfect calibration of post probs 
plot(w, type='n',         # even if stopped early
     xlab=expression(paste('Posterior Probability ', mu > 0, ' Upon Stopping')),
     ylab=expression(paste('Proportion of Trials with ',  mu > 0)))
abline(a=0, b=1, lwd=6, col=gray(.85))
lines(w)

mu> 0の比率と停止時の事後確率

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.