『ゼロからできるMCMC』 Chapter 4をJuliaで
最終更新:2020/11/9
『ゼロからできるMCMC』 Chapter 4のコードを, 練習を兼ねてJuliaで書いてみました. 詳細なことを書くと著作権的にだめな気もするので, 解説などはありません.
Julia Version 1.5.0
Metropolis法を用いた\( S(x) = x^2/2 \)からのサンプル ( p.52 )
モンテカルロ法で円周率を求める.
Julia
using Random: seed! function main(niter) seed!(12345) step_size = 0.5 # initial values x = 0.0 naccept = 0 xs = zeros(Float64, niter) # main for i = 1:niter backup_x = x action_init = 0.5*x*x x += (rand()-0.5)*step_size*2.0 action_fin = 0.5*x*x # Metropolis test metropolis = rand() exp(action_init - action_fin) > metropolis ? naccept+= 1 : x=backup_x xs[i] = x end return xs naccept/niter end
xs
にサンプルを格納しました.
結果をヒストグラムで可視化
niter = 10^3
niter = 10^5
niter = 10^7
niter = 10^7では, 気を利かして普通のプロットのような図にしてくれたようです.
コード(click)
Juliausing Plots xs = main(10^3); pyplot(fmt=:svg, size=(400, 250)) histogram(xs) PyPlot.savefig("ch4_1_1.png", dpi=300)
\( \langle x^2 \rangle \)のジャックナイフ誤差 ( p.60 )
p.60にあるジャックナイフ誤差を求める函数です. \( w \)の値の範囲変えられます.
Julia
function mcmcJackknife(xs, nw) # xs: sample, nw:wの最大値 xs = xs.^2 # x^2の期待値なので f̄ = mean(xs) # total mean L = length(xs) Δw = zeros(1, nw) for w = 1:nw thisL = L - L%w n = thisL / w thisXs = xs[1:thisL] thisXs = reshape(thisXs, w, :) l = mean(thisXs, dims=1) Δw[w] = sqrt(sum((l .- f̄).^2)/(n*(n-1))) end return Δw' end
Metropolis法のサンプル数nの値を変えてプロットしてみました.
コード(click)
Juliaxs = main(10^5); d1 = mcmcJackknife(xs, 200) xs = main(10^6); d2 = mcmcJackknife(xs, 200) xs = main(10^7); d3 = mcmcJackknife(xs, 200) pyplot(fmt=:svg, size=(400, 250)) plot([d1 d2 d3], labels=["n=10⁵" "n=10⁶" "n=10⁷"]) xlabel!("w") ylabel!("Δw") title!("jackknife error for <x²>") PyPlot.savefig("ch4_1_4jack.png", dpi=300)