久保先生の"緑本"こと
「データ解析のための統計モデリング入門」
をベースに回帰分析の概要を紹介。
線形モデル LM (単純な直線あてはめ)
↓ いろんな確率分布を扱いたい
一般化線形モデル GLM
↓ 個体差などの変量効果を扱いたい
一般化線形混合モデル GLMM
↓ もっと自由なモデリングを!
階層ベイズモデル HBM
植物100個体から8個ずつ種子を取って植えたら全体で半分ちょい発芽。
親1個体あたりの生存数はn=8の二項分布になるはずだけど、
極端な値(全部死亡、全部生存)が多かった。個体差?
各個体の生存率$p_i$が能力値$z_i$のシグモイド関数で決まると仮定。
その能力値は全個体共通の正規分布に従うと仮定:
$z_i \sim \mathcal{N}(\hat z, \sigma)$
パラメータ2つで済む: 平均 $\hat z$, ばらつき $\sigma$ 。
普通の二項分布は個体差無し $\sigma = 0$ を仮定してるのと同じ。
事前分布のパラメータに、さらに事前分布を設定するので階層ベイズ
10
とか 3
とか、エイヤっと決めてるやつが超パラメータ。
data {
int<lower=0> N;
array[N] int<lower=0> y;
}
parameters {
real z_hat; // mean ability
real<lower=0> sigma; // sd of r
vector[N] r; // individual difference
}
transformed parameters {
vector[N] z = z_hat + r;
vector[N] p = inv_logit(z);
}
model {
y ~ binomial(8, p);
z_hat ~ normal(0, 10);
r ~ normal(0, sigma);
sigma ~ student_t(3, 0, 1);
}
generated quantities {
array[N] int yrep = binomial_rng(8, p);
}
seeds_data = list(y = df_seeds_od$y, N = samplesize)
model = cmdstanr::cmdstan_model("stan/glmm.stan")
fit = model$sample(data = seeds_data, seed = 19937L, step_size = 0.1, refresh = 0)
draws = fit$draws(c("z_hat", "sigma", "r[1]", "r[2]"))
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
lp__ -455.85 -455.48 9.21 9.27 -471.57 -441.72 1.00 834 1563
z_hat 0.25 0.25 0.31 0.29 -0.25 0.74 1.00 729 1431
sigma 2.77 2.74 0.34 0.34 2.26 3.35 1.00 1182 2360
r[1] -0.24 -0.24 0.77 0.78 -1.47 1.02 1.00 2869 2766
r[2] 1.76 1.66 1.07 1.06 0.16 3.67 1.00 4692 2672
r[3] 1.77 1.69 1.09 1.03 0.17 3.75 1.00 4713 2417
r[4] -3.74 -3.55 1.57 1.53 -6.53 -1.45 1.00 4865 3015
r[5] -2.21 -2.11 1.07 1.03 -4.14 -0.65 1.00 4223 2252
r[6] -2.19 -2.11 1.03 0.99 -4.00 -0.60 1.00 4408 2463
r[7] 0.93 0.88 0.89 0.88 -0.43 2.48 1.00 4135 3151
# showing 10 of 403 rows (change via 'max_rows' argument or 'cmdstanr_max_rows' option)
データ生成の真のパラメータ値は $\hat z = 0.5,~\sigma = 3.0$ だった。
8-hbm.ipynb
をJupyterで開き、スライド説明に沿って実行していこう。
100個体の植物から8つずつ種を取り、発芽した数を観察。
samplesize = 300L
lambda = 3
overdisp = 4
.n = lambda / (overdisp - 1)
.p = 1 / overdisp
df_beer_od = tibble::tibble(
X = rnbinom(samplesize, size = .n, prob = .p)
)
より柔軟にモデルを記述できるようになった。計算方法も変化。