この勉強会に参加させていただきました: https://github.com/7shi/study/wiki/bayes_hmc
読んでいる本(出典): 基礎からのベイズ統計学: ハミルトニアンモンテカルロ法による実践的入門 | 豊田 秀樹 | 本 | Amazon.co.jp
前回: 基礎からのベイズ統計学 Skype読書会(13): 参加メモ - クッキーの日記
読んだ範囲: 126~132ページ
126ページのカタログ刷新問題をやる。
正規分布の場合の事後分布、ポテンシャルエネルギー、その母数での偏微分は以下のようになるはず。
特に の方収束しているのかが大いにあやしいけど目をつぶる。本当は付録2を読んで適切な を決めないといけない。128ページには として までを破棄してと書いてあるけど と の値がない。 でも多少 と を試したが以下の図よりもっと悲惨だったのでとりあえずサンプリング数を増やした。 と の具体的な数値を教えてくれていないのは理論を理解して自分で決定するようにという教育的配慮なんだろうか。
それで求まった10万点のサンプルからEAP推定値を出すと128ページの表と近い。ただ事後標準偏差が小さい。
事後標準偏差が小さいなりに95%信頼区間もちょっと狭くなっている。
「カタログBの平均購入金額が従来のものより高い確率」も事後標準偏差が小さいなりに教科書よりちょっと高い。
「カタログBの平均購入金額が3000円より高い確率」も事後標準偏差が小さいなりに教科書よりちょっと低い。
「効果量が0.8より大きい確率」も事後標準偏差が小さいなりに教科書よりちょっと低い。
でもまあ雰囲気的には近いからいいや。
> mean(mu.trace) [1] 2925.961 > sd(mu.trace) [1] 158.6847 > quantile(mu.trace, probs=c(0.025, 0.975)) 2.5% 97.5% 2611.585 3238.228 > length(mu.trace[mu.trace > 2500])/length(mu.trace) [1] 0.99646 > length(mu.trace[mu.trace > 3000])/length(mu.trace) [1] 0.32493 > length(mu.trace[(mu.trace - 2500)/sqrt(sigma2.trace) > 0.8])/length(mu.trace) [1] 0.13042
スクリプトは以下。収束がいまいちなのは と の調整の問題だと思いたい。
ちなみに受容率は 100% だった。
# カタログBを使用した顧客20人の購入金額データ x <- c(3060, 2840, 1780, 3280, 3550, 2450, 2200, 3070, 2100, 4100, 3630, 3060, 3280, 1870, 2980, 3120, 2150, 3830, 4300, 1880) p_1 <- rnorm(1) p_2 <- rnorm(1) mu <- 2926.5 # mu の初期値: 標本平均にしておく。 sigma2 <- 572855.5 # sigma2 の初期値: 不偏分散にしておく。 p_1.trace <- c(p_1) p_2.trace <- c(p_2) mu.trace <- c(mu) sigma2.trace <- c(sigma2) epsilon <- 0.1 L <- 100 # ポテンシャルエネルギーの mu 偏微分 p_h_p_mu <- function(mu, sigma2) { return(-sum(x - mu) / sigma2) } # ポテンシャルエネルギーの sigma2 偏微分 p_h_p_sigma2 <- function(mu, sigma2) { return(10.0 / sigma2 - 0.5 * sum((x - mu) * (x - mu))/(sigma2 * sigma2)) } # ハミルトニアン H <- function(p_1, p_2, mu, sigma2) { return(10.0 * log(sigma2) + 0.5 * sum((x - mu) * (x - mu))/sigma2 + 0.5 * (p_1 * p_1 + p_2 * p_2)) } # 10万点サンプリング for (i in 2:200000) { # 一応棄却されることを考えて多めにループ p_1_save <- p_1 p_2_save <- p_2 mu_save <- mu sigma2_save <- sigma2 for (j in 1:L) { # リープフロッグ法で次の候補点を得る p_1 <- p_1 - 0.5 * epsilon * p_h_p_mu(mu, sigma2) p_2 <- p_2 - 0.5 * epsilon * p_h_p_sigma2(mu, sigma2) mu <- mu + epsilon * p_1 sigma2 <- sigma2 + epsilon * p_2 p_1 <- p_1 - 0.5 * epsilon * p_h_p_mu(mu, sigma2) p_2 <- p_2 - 0.5 * epsilon * p_h_p_sigma2(mu, sigma2) } # 需要・棄却の判定 r <- exp( H(p_1, p_2, mu, sigma2) - H(p_1_save, p_2_save, mu_save, sigma2_save) ) if (r < runif(1)) { # 棄却 p_1 <- p_1_save p_2 <- p_2_save mu <- mu_save sigma2 <- sigma2_save next } # 受容 p_1.trace <- c(p_1.trace, p_1) p_2.trace <- c(p_2.trace, p_2) mu.trace <- c(mu.trace, mu) sigma2.trace <- c(sigma2.trace, sigma2) if (length(p_1.trace) >= 100000) { # 10万点たまったら抜ける print(i) # ここでループのインデックスも 100000 なら1回も棄却なし break } # 次の探索の準備 -- 正規乱数をセットしておく p_1 <- rnorm(1) p_2 <- rnorm(1) }