階層モデル $y_i \sim \mathcal{N}(\theta_i, \sigma_i^2)$,$\theta_i \sim \mathcal{N}(\mu, \tau^2)$ を解く問題です。本書のRコードのこの問題に固有な部分は次のようになっています:
ydata = c(11, 13, 16) # データ(例)
s2data = c(1, 1, 4) # それぞれのデータの誤差分散(例)
n = length(ydata) # データの個数
s2bar = 1 / mean(1/s2data) # 平均の誤差分散
logpost = function(m, u) { # 事後分布の対数
t2 = exp(u) - s2bar
if (t2 < 0) return(-Inf)
(log(sum(1/(t2+s2data)^2)) - sum((ydata-m)^2/(t2+s2data)) - sum(log(t2+s2data))) / 2 + u
}
この後に通常のメトロポリスのアルゴリズムが来ます。
これをそのままStanにすると,次のようになります:
// ex74a.stan
data {
int n;
real ydata[n];
real s2data[n];
real s2bar;
}
parameters {
real m;
real<lower=log(s2bar)> u;
}
model {
real t2 = exp(u) - s2bar;
real z1 = 0;
real z2 = 0;
for (i in 1:n) z1 += 1/square(t2+s2data[i]);
for (i in 1:n) z2 += square(ydata[i]-m)/(t2+s2data[i]) + log(t2+s2data[i]);
target += (log(z1) - z2) / 2 + u;
}
Rコードは次の通りです:
ydata = c(11, 13, 16)
s2data = c(1, 1, 4)
n = length(ydata) # データの個数
s2bar = 1 / mean(1/s2data) # 平均の誤差分散
data = list(n=n, ydata=ydata, s2data=s2data, s2bar=s2bar)
fit = stan("ex74a.stan", data=data)
e = extract(fit)
hist(e$m, freq=FALSE, col="gray")
しかし,Stanではむしろ次のように書くのが自然です:
// ex74b.stan
data {
int n;
real y[n];
real sigma[n];
}
parameters {
real theta[n];
real mu;
real<lower=0> tau;
}
model {
real p = 0;
for (i in 1:n) p += 1 / square(square(tau) + square(sigma[i]));
target += 0.5 * log(p) + log(tau); // Jeffreys prior
y ~ normal(theta, sigma);
theta ~ normal(mu, tau);
}
こちらの場合,Rでは次のように打ち込みます。
data = list(n=3, y=c(11,13,16), sigma=c(1,1,2))
fit = stan("ex74b.stan", data=data)
実行すると There were XXX divergent transitions after warmup. Increasing adapt_delta above 0.8 may help. See http://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup という警告が出ます。オプション control=list(adapt_delta=0.99) を付けてみましょう。
fit = stan("ex74b.stan", data=data, control=list(adapt_delta=0.99))
それでも警告は出ますが,divergent transitions の数は減ります。
本書pp.140--141のbayesmetaパッケージの結果と比較するために,繰返し数を100万回にしてやってみましょう:
data = list(n=3, y=c(11,13,16), sigma=c(1,1,2))
fit = stan("ex74b.stan", data=data, iter=251000, warmup=1000, control=list(adapt_delta=0.99))
結果はこんな具合です:
fit
Inference for Stan model: ex74b.
4 chains, each with iter=251000; warmup=1000; thin=1;
post-warmup draws per chain=250000, total post-warmup draws=1e+06.
mean se_mean sd 2.5% 25% 50% 75% 97.5% n_eff Rhat
theta[1] 11.41 0.00 0.99 9.43 10.75 11.43 12.10 13.30 382182 1
theta[2] 12.94 0.00 0.94 11.13 12.31 12.93 13.56 14.80 361743 1
theta[3] 14.59 0.00 1.89 11.36 13.20 14.44 15.84 18.59 214759 1
mu 13.01 0.03 4.70 7.53 11.84 12.85 14.01 19.04 35265 1
tau 3.68 0.03 7.20 0.40 1.38 2.36 4.04 14.64 48606 1
lp__ -5.44 0.01 2.11 -10.57 -6.55 -5.07 -3.93 -2.43 111021 1
model { ... } の中の5行のうち頭3行を消せば $\tau$ について一様な事前分布になります。いろいろお試しください。
最後に,本書でも取り上げた現実的な問題(BCGワクチンのメタアナリシス)を試してみましょう。データが13個もあるので,かなり安定な計算ができます(AS を OR にすると対数オッズ比になります)。
library(metafor)
es = escalc(measure="AS", ai=tpos, bi=tneg, ci=cpos, di=cneg, data=dat.bcg)
data = list(n=dim(es)[1], y=es$yi, sigma=sqrt(es$vi))
fit = stan("ex74b.stan", data=data, iter=26000, warmup=1000)
結果は次のようになりました:
Inference for Stan model: ex74b.
4 chains, each with iter=26000; warmup=1000; thin=1;
post-warmup draws per chain=25000, total post-warmup draws=1e+05.
mean se_mean sd 2.5% 25% 50% 75% 97.5% n_eff Rhat
theta[1] -0.08 0.00 0.05 -0.17 -0.11 -0.08 -0.05 0.01 100000 1
theta[2] -0.14 0.00 0.04 -0.21 -0.16 -0.14 -0.11 -0.07 100000 1
theta[3] -0.09 0.00 0.04 -0.17 -0.12 -0.09 -0.07 -0.02 100000 1
theta[4] -0.07 0.00 0.01 -0.08 -0.08 -0.07 -0.07 -0.06 100000 1
theta[5] -0.01 0.00 0.01 -0.03 -0.02 -0.01 0.00 0.01 100000 1
theta[6] -0.17 0.00 0.02 -0.21 -0.18 -0.17 -0.16 -0.14 100000 1
theta[7] -0.07 0.00 0.02 -0.11 -0.08 -0.07 -0.05 -0.03 100000 1
theta[8] 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.01 100000 1
theta[9] -0.02 0.00 0.01 -0.03 -0.02 -0.02 -0.01 0.00 100000 1
theta[10] -0.10 0.00 0.02 -0.13 -0.11 -0.10 -0.08 -0.06 100000 1
theta[11] -0.01 0.00 0.00 -0.02 -0.01 -0.01 -0.01 0.00 100000 1
theta[12] 0.01 0.00 0.01 -0.02 0.00 0.01 0.01 0.03 100000 1
theta[13] 0.00 0.00 0.01 -0.01 0.00 0.00 0.00 0.01 100000 1
mu -0.06 0.00 0.02 -0.10 -0.07 -0.06 -0.05 -0.02 100000 1
tau 0.07 0.00 0.02 0.04 0.05 0.06 0.07 0.11 100000 1
lp__ 23.87 0.01 2.82 17.44 22.20 24.20 25.90 28.37 38953 1
なお,Bayesian Data Analysis, 3rd edition によれば,次のように $\theta_i = \mu + \tau \eta_i$ と分解するほうがStanでは効率が良いとのことです:
data {
int n;
real y[n];
real sigma[n];
}
parameters {
real mu;
real<lower=0> tau;
vector[n] eta;
}
transformed parameters {
vector[n] theta = mu + tau * eta;
}
model {
eta ~ normal(0, 1);
y ~ normal(theta, sigma);
}