View
947
Download
0
Category
Preview:
DESCRIPTION
Citation preview
@siero5335
#みどりぼん 2014/09/09
データ解析のための統計モデリング入門 9章: GLMのベイズモデル化と事後分布の推定
前半
自己紹介 Twitter ID: @siero5335
仕事: 某大学で 化学物質曝露影響の解析 測定法の開発してます 専門: 環境化学、分析化学
測定結果の解析に統計を使用
目次
9.0: 例題データ紹介
9.1: 種子数のポアソン回帰
9.2: GLMのベイズモデル化
9.3: 無情報事前分布
9.4: ベイズ統計モデルの事後分布の推定
9.4.1: ベイズ統計モデルのコーディング (Stan)
9.4.2: 事後分布推定の準備
9.4.3: どれだけ長くMCMCサンプリングすればいいのか
9.0: 例題データ紹介
今回はどんなデータ? 架空植物: n = 20
x: 体サイズ y: 種子数 仮説 体サイズxiに依存して種子数yiの平均が増減する 実際は
のポアソン分布から生成したデータ
x y 3 5
3.210526 3 3.421053 6 3.631579 7 3.842105 7 4.052632 5 4.263158 9 4.473684 9 4.684211 7 4.894737 10 5.105263 12 5.315789 8 5.526316 7 5.736842 4 5.947368 4 6.157895 11 6.368421 9 6.578947 9 6.789474 8
7 6
λ = exp(1.5 + 0.1x)
9.1: 種子数のポアソン回帰
3 4 5 6 7
46
810
12Call: glm(formula = y ~ x, family = poisson, data = d) Coefficients: (Intercept) x 1.56606 0.08334 Degrees of Freedom: 19 Total (i.e. Null); 18 Residual Null Deviance: 15.66 Residual Deviance: 14.17 AIC: 94.04
今回はこのGLMをベイズ統計モデルに移植し、 事後分布の推定に取り組む
図9.1 p195より引用
9.2: GLMのベイズモデル化
1. 個体iの種子数yiのばらつきを平均λiのポアソン分布 に従うとする。 2. GLMの時と同様に、線形予測子と対数リンク関数で平均を と指定する。個体差は考慮しないのでランダム効果の項はなし。 3.このモデルの尤度関数: L(β1, β2)は となる。ここまではGLMといっしょ。
λi = exp(β1 + β2xi)
p(yi|λi)
β! , β! = !!
!! λ! = ! !!
(!!|β! , β! , !!)!
9.2: GLMのベイズモデル化
5. 今回はベイズモデル化して事後分布を推定したい ベイズモデルの事後分布は
に比例するので、今回の例題では以下の関係が成り立つ。
この切片β1, 傾きβ2を適切に指定できれば ベイズモデル化したGLMが得られる
(尤度) × (事前分布)
事後分布 切片β1, 傾きβ2の事前分布
β1,β2がある値の時Yが得られる確率
9.3: 無情報事前分布
どうやって切片β1, 傾きβ2の事前分布を推定するのか 架空植物の平均種子数を増減させる 切片、傾きの確率分布なんて分かるわけない。 [-∞, ∞]の範囲で好きな値をとっていいことにする。 → 無情報事前分布と呼ぶ。
9.3: 無情報事前分布
どうやって切片β1, 傾きβ2の事前分布を推定するのか 架空植物の平均種子数を増減させる 切片、傾きの確率分布なんて分かるわけない。 [-∞, ∞]の範囲で好きな値をとっていいことにする。 → 無情報事前分布と呼ぶ。 どんな確率分布? 範囲を取る一様分布 ひらべったい正規分泌
-10 -5 0 5 10
0.0
0.1
0.2
0.3
0.4
平均0, 標準偏差100の 正規分布
標準正規分布
図9.2 p197より引用
9.3: 無情報事前分布
どうやって切片β1, 傾きβ2の事前分布を推定するのか 架空植物の平均種子数を増減させる 切片、傾きの確率分布なんて分かるわけない。 [-∞, ∞]の範囲で好きな値をとっていいことにする。 → 無情報事前分布と呼ぶ。 どんな確率分布? 範囲を取る一様分布 ひらべったい正規分泌
9.4.1: ベイズ統計モデルのコーディング (BUGS) Model { for (i in 1:N) { Y[i] ~ dpois ( lambda [i] ) log ( lambda [i] ) <-‐ beta1 + beta2 * (X [i] –Mean.X ) } beta1 ~ dnorm (0, 1.0E-‐4) beta1 ~ dnorm (0, 1.0E-‐4) }
9.4.1: ベイズ統計モデルのコーディング (BUGS) Model { for (i in 1:N) { Y[i] ~ dpois ( lambda [i] ) log ( lambda [i] ) <-‐ beta1 + beta2 * (X [i] –Mean.X ) } beta1 ~ dnorm (0, 1.0E-‐4) beta1 ~ dnorm (0, 1.0E-‐4) }
Y[1] ~ dpois ( lambda [1] ) log ( lambda [1] ) <-‐ beta1 + beta2 * (X [1] –Mean.X ) Y[2] ~ dpois ( lambda [2] ) log ( lambda [2] ) <-‐ beta1 + beta2 * (X [2] –Mean.X ) ・・・ Y[20] ~ dpois ( lambda [20] ) log ( lambda [20] ) <-‐ beta1 + beta2 * (X [20] –Mean.X )
ブロック 統計モデルの記述
ブロックは以下のように展開されてWinBUGSに解釈される
iはYやlambdaについてる変数の添字
9.4.1: ベイズ統計モデルのコーディング (BUGS)
Y[i] ~ dpois ( lambda [i] )
個体i の種子数Y[i]が平均 lambda [i] のポアソン分布 dpois ( lambda [i] )に従うという意味
log ( lambda [i] ) <-‐ beta1 + beta2 * (X [i] –Mean.X )
左辺: 個体iの平均種子数lambda [i] は対数リンク関数に従う
beta1 = 切片β1 beta2 = 傾きβ2 X [i] = 説明変数(個体iのサイズxi)
Mean.X 演算高速化のために標本平均を引いて中央化
9.4.1: ベイズ統計モデルのコーディング (BUGS) Model { for (i in 1:N) { Y[i] ~ dpois ( lambda [i] ) log ( lambda [i] ) <-‐ beta1 + beta2 * (X [i] –Mean.X ) } beta1 ~ dnorm (0, 1.0E-‐4) beta2 ~ dnorm (0, 1.0E-‐4) } dnorm (mean, tau) mean = 平均 tau = 分散の逆数
標準偏差 = 標準偏差は100だが、リンク関数が対数なので無情報と言って良い
パラメータβ1 ,β2の事前分布を指定
tau = 1.0E-‐4なので パラメータβ1 ,β2の事前分布は 平均0, 分散100の無情報事前分布
9.4.1: ベイズ統計モデルのコーディング (BUGS)
無情報事前分布 切片β1
無情報事前分布 傾きβ2
ポアソン分布 平均λ[i] データ(各個体のサイズX[i]) データ
(各個体の種子数Y[i])
確率論的関係 左辺は右辺の確率分布に従う: コード上表記 “~”
決定論的関係 左辺の内容は右辺である: コード上表記 “->”
9.4.2: 事後分布推定の準備
手順
(1) データの読み込み
(2) 推定したいパラメータの初期値を指定
(3) RからWinBUGS読み出してデータ・初期値・サンプリング回数、コードファイル名を伝達
(4) WinBUGSが働く
(5) MCMCサンプリングが終わったら結果をRに渡す
(6) MCMCサンプリングの結果をR内で調べる
R2WinBUGSを使って普通は連携するが、使いやすくないので、 本書では久保先生お手製のR2WBwapper.Rを使って操作を簡易化
9.4.2: 事後分布推定の準備
source (“R2WBwrapper.R”) #ラッパー読み込み load(“d.RData”) # (1) 必要なデータの準備 clear.data.param() # データ・初期値読み込みの準備 #データの設定, set.data関数を使ってデータの中身を指定 set,data(“N”, nrow(d)) #サンプルサイズ set.data(“Y”, d$y) #応答変数:種子数Y[i] set.data(“X”, d$x) #説明変数: 体サイズX[i] set.data (“Mean.X, mean(d$x)) #X[i]の標本平均 #パラメータの初期値設置(2), set.param関数で初期値設定set.param(“beta1”, 0) set.param(“beta2”, 0) #次スライドに続く
9.4.2: 事後分布推定の準備
#サンプリング回数等の決定(3) #MCMCサンプリングが終わったら結果をRに渡す(5)
post.bugs <-‐ call.bugs( file = “model.bugs.txt”, n.iter = 1600, n.burnin = 100, n.thin =3 }
file = “model.bugs.txt”: BUGSコードを書いたファイル名の指定 n.iter = 1600: MCMCサンプリング1600回 n.burnin = 100: バーンイン, 最初100回分のデータは使わない
n.thin =3: 101-‐1600までの1500ステップを2個とばしで記録する →間引きのため(サンプリング回数検討の負担減らし)
9.4.3: どれだけ長くMCMCサンプリングすればいいのか
サンプリング数が足りないと 事後分布を正確に推定できない。
多いと時間がかかる… 収束診断で確認 サンプリングを繰り返してサンブル列間の乖離を確認 chain関数を指定(デフォルトは3)
-> Rhat < 1.1(経験的な指標: 収束した、しない)
Rhat! = ! !"#!/!
!"#! = !! − 1! ! + !1!!
W: サンプル列内の分散 B: サンプル列間の分散
var+: 周辺事後分布の分散
図8.8 p179より引用
9.4.3: Rhat > 1.1の時どうする?
n.iterを増やす →サンプリング回数増やす
n.burninを増やす →定常分布になるまでの 待ち時間を増やす
それでも改善しない時は?
不適切な統計モデリング コード・データの間違い パラメータの初期値が不適切
図9.4 p205より引用
まとめ
まずGLMをベイズモデル化することで感覚をつかむ
未知の値には無情報事前分布を事前分布に使ってみる
WinBUGSなどにコードを渡してMCMCサンプリング!
サンプル列間の乖離を調べて収束したか確かめる→ Rhat < 1.1
収束しない時は… サンプリング回数、Burn-‐in期間を確認 それでもダメならモデルの中身をチェック 事後分布の推定については後半に!
おまけ: glmer2stanでもうちょっとお手軽に
library(rstan) # rstan読み出し library(glmer2stan) # glmer2stan読み出し res <-‐ glmer2stan(y ~ x, family = “poisson”, data = d, chain =3) #lme4のformula形式で記述 (res) #結果の表示 res@stanmodel #stanでどう表すか表示 >(res)
mean se_mean sd 2.50% 25% 50% 75% 97.50% n_eff Rhat Intercept 1.55 0.01 0.36 0.81 1.31 1.56 1.8 2.23 1996 1 beta_x 0.09 0 0.07 -‐0.04 0.04 0.08 0.13 0.22 1987 1 dev 92.02 0.04 2.04 90.08 90.6 91.39 92.75 97.51 2553 1 lp__ 143.98 0.02 1.02 141.24 143.62 144.3 144.69 144.95 2553 1
3 chains, each with iter=10000; warmup=5000; thin=1;
post-warmup draws per chain=5000, total post-warmup draws=15000.
iter, warmup (burn-‐in), chain, thin回数については XX (内容) = X (回数) で指定可能 デフォルトは iter = 10000, warmup = 5000, chain = 1, thin = 1
おまけ: glmer2stanでもうちょっとお手軽に res@stanmodel #stanでどう表すか表示 > res@stanmodel S4 class stanmodel 'y ~ x [poisson]' coded as follows: data{ int N; int y[N]; real x[N]; } parameters{ real Intercept; real beta_x; } #右へ続く
model{ real vary[N]; real glm[N]; // Priors Intercept ~ normal( 0 , 100 ); beta_x ~ normal( 0 , 100 ); // Fixed effects for ( i in 1:N ) { glm[i] <-‐ Intercept + beta_x * x[i]; glm[i] <-‐ exp( glm[i] ); } y ~ poisson( glm ); } generated quanwwes{ real dev; real vary[N]; real glm[N]; dev <-‐ 0; for ( i in 1:N ) { glm[i] <-‐ Intercept + beta_x * x[i]; dev <-‐ dev + (-‐2) * poisson_log( y[i] , exp(glm[i]) ); } }
今まで使っていたモデルをstanで書き換えるとどうやって書くのかわかるので、stan事始めに向いているかも?
Recommended