More Related Content Similar to みどりぼん9章前半 (20) More from Akifumi Eguchi (18) みどりぼん9章前半2. 自己紹介
Twitter ID: @siero5335
仕事: 某大学で
化学物質曝露影響の解析
測定法の開発してます
専門: 環境化学、分析化学
測定結果の解析に統計を使用
3. 目次
9.0:
例題データ紹介
9.1:
種子数のポアソン回帰
9.2:
GLMのベイズモデル化
9.3:
無情報事前分布
9.4:
ベイズ統計モデルの事後分布の推定
9.4.1:
ベイズ統計モデルのコーディング
(Stan)
9.4.2:
事後分布推定の準備
9.4.3:
どれだけ長くMCMCサンプリングすればいいのか
4. 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)
5. 9.1:
種子数のポアソン回帰
3 4 5 6 7
4 6 8 10 12
Call:
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
図9.1
p195より引用
今回はこのGLMをベイズ統計モデルに移植し、
事後分布の推定に取り組む
6. 9.2:
GLMのベイズモデル化
1. 個体iの種子数yiのばらつきを平均λiのポアソン分布
p(yi|λi)
に従うとする。
2. GLMの時と同様に、線形予測子と対数リンク関数で平均を
λi = exp(β1 + β2xi)
と指定する。個体差は考慮しないのでランダム効果の項はなし。
3.このモデルの尤度関数: L(β1, β2)は
β!, β! = !
!
!! λ! =! !
!
(!! |β!, β!, !!)!
となる。ここまではGLMといっしょ。
7. 9.2:
GLMのベイズモデル化
5. 今回はベイズモデル化して事後分布を推定したい
ベイズモデルの事後分布は
(尤度) × (事前分布)
に比例するので、今回の例題では以下の関係が成り立つ。
事後分布 切片β1, 傾きβ2の
事前分布
β1,β2がある値の時
Yが得られる確率
この切片β1, 傾きβ2を適切に指定できれば
ベイズモデル化したGLMが得られる
8. 9.3:
無情報事前分布
どうやって切片β1, 傾きβ2の事前分布を推定するのか
架空植物の平均種子数を増減させる
切片、傾きの確率分布なんて分かるわけない。
[-∞, ∞]の範囲で好きな値をとっていいことにする。
→ 無情報事前分布と呼ぶ。
9. 9.3:
無情報事前分布
どうやって切片β1, 傾きβ2の事前分布を推定するのか
架空植物の平均種子数を増減させる
切片、傾きの確率分布なんて分かるわけない。
[-∞, ∞]の範囲で好きな値をとっていいことにする。
→ 無情報事前分布と呼ぶ。
どんな確率分布?
範囲を取る一様分布
ひらべったい正規分泌
標準正規分布
-10 -5 0 5 10
0.0 0.1 0.2 0.3 0.4
平均0, 標準偏差100の
正規分布
図9.2
p197より引用
10. 9.3:
無情報事前分布
どうやって切片β1, 傾きβ2の事前分布を推定するのか
架空植物の平均種子数を増減させる
切片、傾きの確率分布なんて分かるわけない。
[-∞, ∞]の範囲で好きな値をとっていいことにする。
→ 無情報事前分布と呼ぶ。
どんな確率分布?
範囲を取る一様分布
ひらべったい正規分泌
11. 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)
}
12. 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についてる変数の添字
13. 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 演算高速化のために標本平均を引いて中央化
14. 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
=
分散の逆数
標準偏差
=
パラメータβ1
,β2の事前分布を指定
tau
=
1.0E-‐4なので
パラメータβ1
,β2の事前分布は
平均0,
分散100の無情報事前分布
標準偏差は100だが、リンク関数が対数なので無情報と言って良い
15. 9.4.1:
ベイズ統計モデルのコーディング
(BUGS)
無情報事前分布 切片β1
無情報事前分布 傾きβ2
ポアソン分布
データ(各個体のサイズX[i]) 平均λ[i] データ
(各個体の種子数Y[i])
確率論的関係
左辺は右辺の確率分布に従う: コード上表記 “~”
決定論的関係
左辺の内容は右辺である: コード上表記 “->”
16. 9.4.2:
事後分布推定の準備
手順
(1)
データの読み込み
(2)
推定したいパラメータの初期値を指定
(3)
RからWinBUGS読み出してデータ・初期値・サンプリング回数、
コードファイル名を伝達
(4)
WinBUGSが働く
(5)
MCMCサンプリングが終わったら結果をRに渡す
(6)
MCMCサンプリングの結果をR内で調べる
R2WinBUGSを使って普通は連携するが、使いやすくないので、
本書では久保先生お手製のR2WBwapper.Rを使って操作を簡易化
17. 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)
#次スライドに続く
18. 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個とばしで記録する
→間引きのため(サンプリング回数検討の負担減らし)
19. 9.4.3:
どれだけ長くMCMCサンプリングすればいいのか
サンプリング数が足りないと
事後分布を正確に推定できない。 多いと時間がかかる…
収束診断で確認
サンプリングを繰り返してサンブル列間の乖離を確認
chain関数を指定(デフォルトは3) -> Rhat < 1.1(経験的な指標: 収束した、しない)
Rhat! =! !"#!/!
!"#! =!
! − 1
!
! +!
1
!
!
図8.8
p179より引用
W: サンプル列内の分散
B: サンプル列間の分散 var+: 周辺事後分布の分散
20. 9.4.3:
Rhat
>
1.1の時どうする?
n.iterを増やす
→サンプリング回数増やす
n.burninを増やす
→定常分布になるまでの
待ち時間を増やす
それでも改善しない時は?
不適切な統計モデリング
コード・データの間違い
パラメータの初期値が不適切
図9.4
p205より引用
22. おまけ:
glmer2stanでもうちょっとお手軽に
library(rstan)
#
rstan読み出し
library(glmer2stan)
#
glmer2stan読み出し
res
<-‐
glmer2stan(y
~
x,
family
=
“poisson”,
data
=
d,
chain
=3)
#lme4のformula形式で記述
(res)
#結果の表示
res@stanmodel
#stanでどう表すか表示
>(res)
3 chains, each with iter=10000; warmup=5000; thin=1;
post-warmup draws per chain=5000, total post-warmup draws=15000.
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
iter,
warmup
(burn-‐in),
chain,
thin回数については
XX
(内容)
=
X
(回数)
で指定可能
デフォルトは iter
=
10000,
warmup
=
5000,
chain
=
1,
thin
=
1
23. おまけ:
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事始めに向いているかも?