SSブログ

ZIPモデルのWAICを計算してみた [統計]

ゼロ過剰ポアソン(Zero-Infrated Poisson; ZIP)モデルでWAICを計算させてみました。ついでに、ポアソン分布と、負の二項分布とも比較してみました。

[2017-12-07 コードが間違っていたのを修正。]

ZIPのStanファイル: zip_waic.stan

data {
  int<lower=0> N;
  int<lower=0> Y[N];
}

parameters {
  real<lower=0, upper=1> omega;
  real<lower=0> lambda;
}

model {
  for (i in 1:N)
    if (Y[i] > 0) {
      1 ~ bernoulli(omega);
      Y[i] ~ poisson(lambda);
    } else {
      target += log_sum_exp(bernoulli_lpmf(0 | omega),
                            bernoulli_lpmf(1 | omega)
                            + poisson_lpmf(0 | lambda));
    }
}

generated quantities {
  real log_lik[N];
  
  for (i in 1:N)
    log_lik[i] = (Y[i] > 0) ?
                 bernoulli_lpmf(1 | omega) + poisson_lpmf(Y[i] | lambda) :
                 log_sum_exp(bernoulli_lpmf(0 | omega),
                             bernoulli_lpmf(1 | omega)
                             + poisson_lpmf(0 | lambda));
}

ポアソン分布のStanファイル: poisson_waic.stan

data {
  int<lower=0> N;
  int<lower=0> Y[N];
}

parameters {
  real<lower=0> lambda;
}

model {
  Y ~ poisson(lambda);
}

generated quantities {
  real log_lik[N];
  
  for (i in 1:N)
    log_lik[i] = poisson_lpmf(Y[i] | lambda);
}

負の二項分布のStanファイル: negbin_waic.stan

data {
  int<lower=0> N;
  int<lower=0> Y[N];
}

parameters {
  real<lower=0> mu;
  real<lower=0> phi;
}

model {
  mu ~ cauchy(0, 5);
  phi ~ cauchy(0, 5);
  Y ~ neg_binomial_2(mu, phi);
}

generated quantities {
  real log_lik[N];
  
  for (i in 1:N)
    log_lik[i] = neg_binomial_2_lpmf(Y[i] | mu, phi);
}

phiに弱情報事前分布をつけないと、MCMC計算が収束しませんでした。

Rスクリプト

##
## Zero-inflated Poisson
##

set.seed(123)

n <- 40
omega <- 0.4
lambda <- 3

y <- rbinom(n, 1, omega) * rpois(n, lambda)

##
library(loo)
library(rstan)
rstan_options(auto_write = TRUE)
options(mc.cores = parallel::detectCores())

stan_data = list(N = n, Y = y)
fit1 <- stan("zip_waic.stan", data = stan_data,
             iter = 2000, warmup = 1000, thin = 1)
waic1 <- waic(extract_log_lik(fit1))

fit2 <- stan("poisson_waic.stan", data = stan_data,
             iter = 2000, warmup = 1000, thin = 1)
waic2 <- waic(extract_log_lik(fit2))

fit3 <- stan("negbin_waic.stan", data = stan_data,
             iter = 2000, warmup = 1000, thin = 1)
waic3 <- waic(extract_log_lik(fit3))

結果(追記: というとWAICは予測最適化なので語弊があります)ですが、当然ながら、データを生成したモデルであるZIPでWAICがもっとも小さくなりました。

> print(fit1, pars = c("omega", "lambda", "lp__"))
Inference for Stan model: zip_waic.
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
omega    0.47    0.00 0.08   0.31   0.42   0.47   0.53   0.64  3205    1
lambda   2.47    0.01 0.42   1.71   2.17   2.45   2.74   3.32  2692    1
lp__   -28.56    0.02 1.00 -31.32 -28.93 -28.26 -27.86 -27.59  1814    1

Samples were drawn using NUTS(diag_e) at Thu Dec  7 21:13:35 2017.
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).
> print(fit2, pars = c("lambda", "lp__"))
Inference for Stan model: poisson_waic.
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
lambda   1.15    0.00 0.17   0.84   1.03   1.14   1.25   1.51  2979    1
lp__   -40.09    0.02 0.74 -42.18 -40.25 -39.80 -39.62 -39.57  2120    1

Samples were drawn using NUTS(diag_e) at Sat Oct  8 07:55:33 2016.
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).
> print(fit3, pars = c("mu", "phi", "lp__"))
Inference for Stan model: negbin_waic.
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
mu     1.23    0.01 0.31   0.77   1.02   1.18   1.37   1.95  1664    1
phi    1.05    0.04 1.42   0.29   0.54   0.77   1.13   3.35  1221    1
lp__ -33.49    0.02 1.03 -36.31 -33.88 -33.16 -32.77 -32.52  1693    1

Samples were drawn using NUTS(diag_e) at Sat Oct  8 07:55:37 2016.
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).
> 
> print(waic1)
Computed from 4000 by 40 log-likelihood matrix

          Estimate   SE
elpd_waic    -52.9  6.6
p_waic         1.7  0.2
waic         105.8 13.3
> print(waic2)
Computed from 4000 by 40 log-likelihood matrix

          Estimate   SE
elpd_waic    -67.3  6.0
p_waic         2.0  0.3
waic         134.7 11.9
> print(waic3)
Computed from 4000 by 40 log-likelihood matrix

          Estimate   SE
elpd_waic    -60.3  6.3
p_waic         1.6  0.1
waic         120.6 12.5


タグ:STAn WAIC
nice!(2)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

nice! 2

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

Facebook コメント

トラックバック 0