《自由エネルギー》は統計モデルを使ったデータで,モデル評価の指標として使われる推定量の一つです.実用上はStanなどを使って,MCMCサンプルからこれらの指標を計算することが多いと思います.
その際,解析的に計算した厳密値とPCで計算した値が一致するかどうか気になったことはないでしょうか?
そこで本ノートでは,《解析的に計算した(手計算で求めた)自由エネルギー》と《PCを使って計算した近似値》が一致するのかどうかを単純な例を使って調べます ^1 .以下,数式の例は渡辺(2012)を,計算コードの例は浜田・石田・清水(2019)を参照しました.
まずは定義を確認します.
確率モデルを
ここで,周辺尤度の対数の符号を逆転させたものを,自由エネルギー(free energy)と定義し、記号
周辺尤度
一般的に確率モデルは
ここで
事前分布を
共役事前分布を使って,確率モデルが指数分布族である場合の分配関数を一般的に計算します.
ここで共役事前分布の仮定より
これを使えば分配関数は
です.ただし
自由エネルギー
この計算から,《指数分布族に対しては共役事前分布を定義でき,事後分布は共役事前分布と同じ関数となること》が分かります.ただし事前分布のハイパーパラメータは
正規分布のパラメータ
指数分布族の共役事前分布は
ガウス積分を使って計算すると
なので,
具体的な確率モデルと事前分布を使って,自由エネルギーを計算してみましょう.以下の例は渡辺(2012)の例をさらに簡略化したものです.
計算のための具体例.
さきほどの計算結果から,この事前分布は共役事前分布であることが分かります.
確率モデルが指数分布族で,事前分布が共役事前分布であるとき,自由エネルギーは
ゆえに仮定のもとで,自由エネルギーは
かなりシンプルな仮定から出発したおかげで,自由エネルギーを陽表的な関数として示すことができました.ここから,モデルが複雑になると,解析的な計算が困難であることは容易に想像できるでしょう.そのため実用上はMCMCサンプルを用いた近似計算がよく使われます.
真の分布が確率モデルに対して正則であり,事後分布が正規分布に近似できる場合,積分のラプラス近似の手法を用いて,自由エネルギーを近似的に求められます.それが,BIC(Bayesian Information Criterion)であり,最尤推定から得られる最大対数尤度を用いた単純な式として,
正則でないモデルにおいても,自由エネルギーの近似値を導出できるのがWBIC(Widely Applicable Bayesian Information Criterion)です.
これは,経験対数損失
そのほか,MCMCサンプルから自由エネルギーを推定する手法としてブリッジ・サンプリング(bridge sampling)があります.
うえで計算した自由エネルギーの厳密値と,WBICやブリッジサンプリングからの計算が一致するかどうかを確認してみましょう.
以下のようなデータを使い,データを生成する未知の分布を確率モデルで推測します.「未知」と言いつつ,ここでは《正解》が分かっているデータをRで作成します.
n = 500
y <- rnorm(n)
data1 <- list(y=y,n=n)
確率モデルと事前分布は
です.パラメータの事後分布をMCMCで計算するためのStanコード(fe.stan)は,以下の通りです.
data{
int n;// no. of respondents real y[n];//
}
parameters {
real mu;
}
model {
target += normal_lpdf(mu|0,1);
target += normal_lpdf(y|mu,1);
}
後でブリッジサンプリングを使うために,target記法で書いている点に注意してください.つぎにWBICをMCMCサンプルから計算するためのコード(wbic.stan)です.
data{
int n;// no. of respondents real y[n];//
}
parameters {
real mu;
}
model {
target += normal_lpdf(mu|0,1);
target += (1/log(n))*normal_lpdf(y|mu,1);
}
generated quantities{
vector[n] log_lik;
for(i in 1:n){
log_lik[i] = normal_lpdf(y[i]|mu,1);
}
}
WBICは逆温度
以上のStanコードを次のようなRコードで実行します.
library(rstan)
library(bridgesampling)
# define WBIC function
WBIC.mcmc<-function(x){-mean(rowSums(x))}
############################################################
# compile and sampling
############################################################
model <- stan_model(file='model/fe.stan')
fit <- sampling(model,data=data1,iter = 10500, warmup =500, seed=1234,chains = 5)
bs<-bridge_sampler(fit,method="warp3")
-logml(bs)
model.wbic <- stan_model(file='model/wbic.stan')
fit.wbic <- sampling(model.wbic,data=data1,iter = 5500, warmup =500, seed=1234,chains = 3)
WBIC.mcmc(rstan::extract(fit.wbic)$log_lik)
計算した結果です.
# ブリッジサンプリングから計算した自由エネルギー
# [1] 706.8302, n=500 MCMCsample=40000
# [1] 706.8301, n=500 MCMCsample=50000
# MCMCサンプルから計算したWBIC
# 706.7799, n=500
そして最後に解析的に解いた自由エネルギーにデータをあてはめて計算します(ここが今回のノートのハイライトです).
a1 <- -sum(log(1/sqrt(2*pi)*exp(-y^2/2)))
nume <- sqrt((2*pi)/(n+1))*exp((sum(y^2))/(2*(n+1)))
a2 <- -log(nume/sqrt(2*pi))
a1+a2
# [1] 707.0134 自由エネルギーの厳密値
ほぼ一致しました.ちょびっとズレていますが誤差の範囲でしょう.これで安心してブリッジサンプリングやWBICが使えますね.