7.4 階層モデル

階層モデル $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個もあるので,かなり安定な計算ができます(ASOR にすると対数オッズ比になります)。

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);
}