Stan 実行結果

Stan(rstan) の実行結果は stanfit クラスのオブジェクトとして保存される。このオブジェクトの中には、MCMC サンプリングを行った時の条件や推定されたパラメーターの分布などが記録されている。このページでは、この stanfit クラスのオブジェクトかた必要なデータを取り出して、保存したり、図示したりする方法を示す。

Stan によるモデルパラメーター推定

ここで、テスト用に、R を使って平均 10 分散 4 となる正規分布に従う乱数を 100 個発生させて、次に Stan で乱数の生成元となる正規分布のパラメーターを推測して stanfit クラスのオブジェクトを作成する。

data {
    int n;
    real x[n];
}
parameters {
    real mu;
    real sigma;
}
model {
    x ~ normal(mu, sigma);
}
x <- rnorm(n = 100, mean = 10, sd = 2)
d <- list(x = x, n = length(x))
fit <- stan(file = 'normdisp.stan', data = d)
fit
## Inference for Stan model: tmp.
## 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      10.25    0.00 0.19    9.88   10.13   10.25   10.38   10.63  3048    1
## sigma    1.90    0.00 0.13    1.66    1.80    1.89    1.98    2.17  2963    1
## lp__  -113.29    0.02 1.01 -116.08 -113.67 -112.98 -112.60 -112.32  1781    1

Stan 結果の取得

stan 関数によりモデル推定を行った結果が fit オブジェクトに保存されるため、パラメーターの推定結果を取得したい時、この fit オブジェクトの中から抽出する。

サンプリング条件

stanfit クラスのオブジェクトをそのまま表示させるか、または summary(fit) で表示させることによって、パラメーター推定結果の概要を見ることができる。例えば、次の場合、iter、warmup、および tihn にはそれぞれサンプリング回数、ウォームアップ回数、および間引き間隔を表す。

ウォームアップ回数は、サンプリング回数のうち、パラメーターに使われない最初の方のサンプリング回数を表す。サンプリング初期において、初期値から最適解付近に遷移するまでにステップ数がかかるために、ウォームアップを設けることで、その遷移過程を無視することになり、初期値の影響を軽減することができる。また、間引き間隔は、ウォームアップ後のサンプリング結果のうち、どのぐらいの間隔のものをパラメーター推定に使うのかを示している。例えば thin=2 とした場合は、パラメーター推定に使われるサンプリング結果は 1 回目、3 回目、5 回目、・・・の結果となる。

fit <- stan(file = 'normdisp.stan', data = d)
fit
## Inference for Stan model: tmp.
## 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      10.25    0.00 0.19    9.88   10.13   10.25   10.38   10.63  3048    1
## sigma    1.90    0.00 0.13    1.66    1.80    1.89    1.98    2.17  2963    1
## lp__  -113.29    0.02 1.01 -116.08 -113.67 -112.98 -112.60 -112.32  1781    1

fit オブジェクトから、Stan コードで記述されたモデルを取得することができる。この際に、get_stanmodel 関数を利用する。

ms <- rstan::extract(fit)

get_stanmodel(fit)
## S4 class stanmodel 'lm' coded as follows:
## data {
##     int n;
##     real x[n];
## }
## parameters {
##     real mu;
##     real sigma;
## }
## model {
##     x ~ normal(mu, sigma);
## }

初期化パラメーターおよびサンプリング時に使用したシードはそれぞれ get_initsget_seeds 関数で取得できる。

ms <- rstan::extract(fit)

get_inits(fit)
## [[1]]
## [[1]]$mu
## [1] -1.676589
## [[1]]$sigma
## [1] 0.37793
## 
## [[2]]
## [[2]]$mu
## [1] -1.289332
## [[2]]$sigma
## [1] 1.433932
## 
## [[3]]
## [[3]]$mu
## [1] 1.719083
## [[3]]$sigma
## [1] 1.188696
## 
## [[4]]
## [[4]]$mu
## [1] -1.233047
## [[4]]$sigma
## [1] 0.2119928

get_seeds(fit)
## [1] 1469703516 1469703516 1469703516 1469703516

Rhat

各 Rhat について、chain 数が 3 以上のとき、すべてのパラメーターで Rhat < 1.1 ならば、MCMC サンプリングによるパラメーター推定が収束したとみなすことができる。

パラメーターの分布

各パラメーターに対する MCMC サンプリングの結果は extract 関数で取得できる。extract 関数で取得したサンプリング結果はリストの形で返される。リストの名前が、パラメーターの名前であり、リストの各要素がサンプリングの結果となる。上の例では、4 chains で、それぞれの chain では 1000 回サンプリングが行われたので、リストの各要素の長さが 4000 となっている。

ms <- rstan::extract(fit)

sapply(ms, length)
##    mu sigma  lp__
##  4000  4000  4000

sapply(ms, summary)
##                mu    sigma      lp__
## Min.     9.476039 1.517786 -120.6438
## 1st Qu. 10.125193 1.802569 -113.6709
## Median  10.248190 1.891605 -112.9778
## Mean    10.251277 1.897141 -113.2948
## 3rd Qu. 10.378800 1.980579 -112.5989
## Max.    10.917563 2.426028 -112.2946

extract 関数にはいくつかのオプションが用意されている。例えば、parsinclude を組み合わせることで、特定のパラメーターだけを取り出せたり、あるいは特定のパラメーターだけを無視したりすることができる。

ms <- rstan::extract(fit, pars = c('mu', 'sigma'), include = TRUE)
names(ms)
## [1] "mu"    "sigma"

ms <- rstan::extract(fit, pars = c('mu', 'sigma'), include = FALSE)
names(ms)
## [1] "lp__"

また、ウォームアップの結果も含めたい場合は、inc_warmup オプションを利用する。ただし、この際に permuted=FALSE を指定する必要があり、このとき抽出されたデータは 3 次元配列として返される。

ms <- rstan::extract(fit, permuted = FALSE, inc_warmup = TRUE)
str(ms)
##  num [1:2000, 1:4, 1:3] -1.66 -1.66 -1.66 -1.66 -1.66 ...
##  - attr(*, "dimnames")=List of 3
##   ..$ iterations: NULL
##   ..$ chains    : chr [1:4] "chain:1" "chain:2" "chain:3" "chain:4"
##   ..$ parameters: chr [1:3] "mu" "sigma" "lp__"

対数事後確率の分布

ベイズ推定において、MCMC サンプリングにより、対数事後確率

\[ \log p(\theta | x) \propto \log p(x|\theta) + \log p(\theta) + C \]

の高いところでパラメーター探索を行われる。このときの対数事後確率は、lp__ の名前でパラメーターとして stanfit クラスのオブジェクトに保存される。そのため、他のモデルパラメーターと同様に、extract 関数で取得することができる。

ms <- rstan::extract(fit)
names(ms)
## [1]    mu sigma  lp__

sapply(ms, summary)
##                mu    sigma      lp__
## Min.     9.476039 1.517786 -120.6438
## 1st Qu. 10.125193 1.802569 -113.6709
## Median  10.248190 1.891605 -112.9778
## Mean    10.251277 1.897141 -113.2948
## 3rd Qu. 10.378800 1.980579 -112.5989
## Max.    10.917563 2.426028 -112.2946

ベイズ信頼区間

MCMC サンプリング結果がから各パラメーターのベイズ信頼区間を求めることができる。例えば、mu と singma の 95% 信頼区間は次のように求めることができる。

ms <- rstan::extract(fit)
quantile(ms$mu, probs = c(0.025, 0.975))
##      2.5%     97.5%
##  9.882575 10.632519

quantile(ms$sigma, probs = c(0.025, 0.975))
##     2.5%    97.5%
## 1.663189 2.174985

Stan 結果の図示

Stan の結果の図示は、extract 関数で取得できるため、取得した値を使用してヒストグラムなどを描くことができる。このほかに、rstan パッケージで用意された関数を使ってグラフを描くこともできる。各回の MCMC サンプリングによってパラメーターの値がどのように遷移したのかを確認したい場合は、stan_trace 関数を使うことで図示できる。

stan_trace(fit)
stan による正規分布のパラメーター推定結果(サンプリング軌跡)

また、推定されたパラメーターの分布(ヒストグラム)は stan_hist 関数を使用する。

stan_hist(fit)
stan による正規分布のパラメーター推定結果(事後確率の分布)

これらのプロット関数には、extract 関数と同様なオプションが用意され、特定のパラメーターのみについて図示したり、ウォームアップ区間を含まなないようにしたりすることができる。