井出草平の研究ノート

重回帰分析[ベイズ]

CPS1985データを使い、wageを従属変数、genderとageと独立変数とした重回帰分析を行う。 RStudioでの実行。R.4.3.3+Stools4.3を使用。

data {
  int<lower=0> N;                 // サンプルサイズ
  int<lower=0, upper=1> X_1[N];   // 独立変数(性別、0: 男性、1: 女性)
  vector[N] X_2;                  // 独立変数: 年齢
  vector[N] Y;                    // 従属変数(賃金)
}

parameters {
  real alpha;                     // 切片
  real beta_gender;               // 性別の影響
  real beta_age;                  // 年齢の影響
  real<lower=0> sigma;            // 誤差項の標準偏差
}

model {
  vector[N] gender_effect = to_vector(X_1); // 性別が1の場合は1、それ以外(つまり0)は0

  Y ~ normal(alpha + beta_gender * gender_effect + beta_age * X_2, sigma);
}
library(rstan)
library(AER)

# データの準備
N <- nrow(CPS1985)
Y <- CPS1985$wage
X_1 <- ifelse(CPS1985$gender == "male", 0, 1)
X_2 <- CPS1985$age

# データをリストにまとめる
stan_data <- list(N = N, Y = Y, X_1 = X_1, X_2 = X_2)

# Stanモデルのフィット
fit <- sampling(stan_model, data = stan_data, iter = 2000, chains = 4, seed=1234)

# 結果の出力
print(fit)
Inference for Stan model: anon_model.
4 chains, each with iter=2000; warmup=1000; thin=1; 
post-warmup draws per chain=1000, total post-warmup draws=4000.

                mean se_mean   sd     2.5%      25%      50%      75%    97.5% n_eff Rhat
alpha           6.92    0.02 0.71     5.50     6.44     6.92     7.38     8.33  2068    1
beta_gender    -2.29    0.01 0.44    -3.16    -2.59    -2.30    -1.99    -1.41  2818    1
beta_age        0.09    0.00 0.02     0.05     0.07     0.09     0.10     0.12  2050    1
sigma           4.95    0.00 0.16     4.66     4.84     4.95     5.06     5.27  3265    1
lp__        -1118.87    0.04 1.48 -1122.47 -1119.61 -1118.52 -1117.76 -1117.06  1524    1

Samples were drawn using NUTS(diag_e) at Thu Apr 18 02:40:46 2024.
For each parameter, n_eff is a crude measure of effective sample size,
and Rhat is the potential scale reduction factor on split chains (at 
convergence, Rhat=1)
bayesplot::mcmc_trace(as.array(fit), pars = c("alpha", "beta_gender", "beta_age", "sigma"))

bayesplot::mcmc_pairs(
  as.array(fit),
  pars = c("alpha", "beta_gender", "beta_age", "sigma"),
  off_diag_args = list(size = 0.5)  # オフダイアゴナルのプロットの点の大きさ
  )

事後予測チェック

library(bayesplot)
posterior_samples <- extract(fit)

# 予測値の生成
num_draws <- length(posterior_samples$alpha)  # 事後サンプルの数
predicted_Y <- matrix(NA, nrow = num_draws, ncol = N)  # 初期化

for (i in 1:num_draws) {
  predicted_Y[i, ] <- rnorm(N,
      mean = posterior_samples$alpha[i] + 
      posterior_samples$beta_gender[i] * X_1 + 
      posterior_samples$beta_age[i] * X_2, 
      sd = posterior_samples$sigma[i])
}

# 事後予測チェック
ppc_check <- bayesplot::pp_check(object = Y, yrep = predicted_Y, fun="dens_overlay")
print(ppc_check)

実効サンプルサイズ

fit_summary <- monitor(fit)
print(fit_summary)
                     mean      se_mean         sd          2.5%           25%           50%           75%         97.5% n_eff     Rhat valid
alpha        6.921184e+00 0.0155193212 0.70682223  5.502206e+00  6.440878e+00  6.924570e+00  7.381204e+00     8.3312505  2070 1.000772     1
beta_gender -2.291384e+00 0.0083537210 0.44279597 -3.161696e+00 -2.592320e+00 -2.298043e+00 -1.992746e+00    -1.4104326  2798 1.001946     1
beta_age     8.559054e-02 0.0003989017 0.01808944  4.954774e-02  7.318514e-02  8.540466e-02  9.828155e-02     0.1209101  2051 1.000292     1
sigma        4.951900e+00 0.0027256369 0.15593607  4.658480e+00  4.843548e+00  4.946649e+00  5.058095e+00     5.2701769  3265 1.000555     1
lp__        -1.118869e+03 0.0376995835 1.47783101 -1.122466e+03 -1.119609e+03 -1.118521e+03 -1.117764e+03 -1117.0557380  1526 1.000905     1
                       Q5           Q50          Q95    MCSE_Q2.5     MCSE_Q25     MCSE_Q50     MCSE_Q75  MCSE_Q97.5      MCSE_SD Bulk_ESS Tail_ESS
alpha        5.755831e+00  6.924570e+00     8.051954 0.0341940210 0.0179667943 0.0179815608 0.0174125228 0.041111513 0.0109835488     2076     1973
beta_gender -3.012165e+00 -2.298043e+00    -1.551494 0.0235019727 0.0141219316 0.0087052647 0.0147062847 0.027382883 0.0060181400     2834     2237
beta_age     5.623037e-02  8.540466e-02     0.114979 0.0009738498 0.0005416239 0.0005417372 0.0005132177 0.001034017 0.0002830609     2062     2106
sigma        4.704350e+00  4.946649e+00     5.220389 0.0075309437 0.0034408536 0.0036507362 0.0048615927 0.008442741 0.0019301027     3288     2363
lp__        -1.121690e+03 -1.118521e+03 -1117.174445 0.1265368331 0.0521949723 0.0342846729 0.0308008386 0.013573997 0.0266666435     1620     2162

感度分析

data {
  int<lower=0> N;
  int<lower=0, upper=1> X_1[N];
  vector[N] X_2;
  vector[N] Y;
}

parameters {
  real alpha;
  real beta_gender;
  real beta_age;
  real<lower=0> sigma;
}

model {
  // 変更した事前分布
  alpha ~ normal(7, 1);  // 事後分布の95%確信区間から取りうる値を指定
  beta_gender ~ normal(-2.3, 0.45);
  beta_age ~ normal(0.085, 0.018);
  sigma ~ inv_gamma(2, 1/(4.97^2));   // 逆ガンマ分布

  // データに基づくモデル
  vector[N] gender_effect = to_vector(X_1); 

  // 観測データの尤度
  Y ~ normal(alpha + beta_gender * gender_effect + beta_age * X_2, sigma);
}
fit_sensitivity  <- sampling(sensitivity_analysis, data = stan_data, iter = 2000, chains = 4, seed=1234)
print(fit_sensitivity )
                mean se_mean   sd     2.5%      25%      50%      75%    97.5% n_eff Rhat
alpha           6.95    0.01 0.46     6.06     6.64     6.94     7.26     7.87  2365    1
beta_gender    -2.28    0.01 0.31    -2.88    -2.50    -2.29    -2.07    -1.68  3136    1
beta_age        0.08    0.00 0.01     0.06     0.08     0.08     0.09     0.11  2249    1
sigma           4.93    0.00 0.15     4.64     4.83     4.93     5.04     5.24  2997    1
lp__        -1123.62    0.03 1.35 -1126.96 -1124.32 -1123.35 -1122.60 -1121.85  1770    1