Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

55
Julia Tokyo #2 Julia Hamiltonian Monte Carlo (NUTS ) (Kenta Sato) @bicycle1885 1 / 55

description

サンプルコード: https://github.com/bicycle1885/JuliaTokyo2HMC

Transcript of Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Page 1: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Julia Tokyo #2

Juliaで学ぶHamiltonian Monte Carlo

(NUTS入り)

佐藤 建太 (Kenta Sato)

@bicycle1885

1 / 55

Page 2: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

コンテンツ

自己紹介

マルコフ連鎖モンテカルロ法 (MCMC)

Metropolis-HastingsHamiltonian Monte Carlo (HMC)No-U-Turn Sampler (NUTS)

Juliaで使えるMCMCパッケージ

2 / 55

Page 3: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

こんなヒトのための発表です

MCMCによるサンプリングをブラックボックスにしたくない

Stanなどのサンプラーの原理を垣間見たい

Juliaで使えるサンプラーを知りたい

3 / 55

Page 4: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

注意

時間の都合上、MCMC自体は簡単に触れる程度です

数学的に厳密な話は期待しないで下さい

内容には細心の注意を払っていますが、専門外ゆえ間違いがある

かもしれません

その時はその場で指摘していただけると助かります

4 / 55

Page 5: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

自己紹介 / パッケージ紹介

5 / 55

Page 6: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

自己紹介

佐藤 建太

Twitter/GitHub: @bicycle1885

所属: 東大大学院農学部

専門: Bioinformatics

Julia歴: 今年の初め頃~現在

好きな言語: Julia / Haskell

よく使う言語: Python / R

6 / 55

Page 7: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Haskellもよろしくお願いします

『Haskellによる並列・並行プログラミング』の翻訳レビューをしまし

た。

7 / 55

Page 8: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

パッケージ紹介

DocOpt.jl - https://github.com/docopt/DocOpt.jl

ヘルプメッセージをパースし、コマンドライン引数のパースをする

RandomForests.jl -https://github.com/bicycle1885/RandomForests.jl

機械学習アルゴリズムRandom ForestのJulia実装

GeneOntology.jl - https://github.com/bicycle1885/GeneOntology.jl

生物学のGene Ontologyのツールキットを目指してる

8 / 55

Page 9: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

マルコフ連鎖モンテカルロ法

(MCMC)

9 / 55

Page 10: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

MCMC法とは

言わずと知れた、確率分布 からのサンプルをマルコフ連鎖を用いて得るサンプリング手法のひとつ。

得られたサンプル自体は分布の期待値や分散など色々な値を計算する

のに使われる。

マルコフ連鎖とは、現在の状態のみで次の状態の確率分布が決まる確

率過程のことをいう。

このとき、状態 から へ遷移する確率を と書き、遷移確

率と呼ぶ。

P(x)

P( = x < = , … , = ) = P( = x < = )Xt+1 X1 x1 Xt xt Xt+1 Xt xt

x x′ T( ; x)x′

10 / 55

Page 11: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

マルコフ連鎖の図

遷移確率 T( ; x) = P( = < = x)x′ Xt+1 x′ Xt11 / 55

Page 12: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

正しいMCMC

目的の確率分布 からサンプリングするには、遷移確率が満たさ

なければならない性質がある。

分布の不変性:

エルゴード性:

各サンプラーがこれらを満たすということの説明などは今日はしない

(できない)。

π(x)

π(x) = D T(x; )π( )dx′ x′ x′

(x) → π(x) as t → 7, for any (x)P(t) P(0)

12 / 55

Page 13: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

高次元空間でのサンプリングは難しい

確率密度関数 やその非正規化密度関数 があるとする。

高次元空間でのサンプリングの難しさ

"濃い"領域は、空間上のごく一部に集中している

しかしそれがどこかはサンプリング前には分からない

2つの戦略

1. その場から濃い方へ濃い方へと進み

2. 濃いところを見つけたらそこから薄いところへはあまり行かない

➠ MCMCはまさにそのような戦略をとる

p(x) (x)p ̃

p(x)

13 / 55

Page 14: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Metropolis­HastingsNight View with Tokyo Tower Special Lightup (Shibakouen, Tokyo, Japan) by t-mizo is licensed under CC BY 2.0

14 / 55

Page 15: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Metropolis­Hastings

MCMCサンプリングのひとつで、提案分布というサンプリングしたい

分布とは別の分布から候補点を取り出し、"良い値"ならその点を受理し、そうでなければその場にとどまる。

候補点を生成する提案分布 は相関のない正規分布など、サン

プリングしやすい分布に設定する。

候補点 は以下の確率 で受理される:

ここで、 はサンプリングしたい分布 の非正規化密度関数

q( < θ)θ̃

θ̃ A( < )θ̃ θ(m)

A( < ) = min (1, ))θ̃ θ(m) ( )q( < )p ̃ θ̃ θ(m) θ̃

( )q( < )p ̃ θ(m) θ̃ θ(m)

(θ)p ̃ p(θ)

15 / 55

Page 16: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Metropolis­Hastingsのアルゴリズム

非正規化確率分布関数 からサンプリングする

1. 初期状態 を決め、 に設定する

2. 提案分布 から新たな点 をとる

3. 確率 で をサンプルとして受理し、そうでなければ

棄却する

4. 受理された場合は と設定し、棄却された場合は と設定する

5. として、2~4を 個のサンプルが得られるまで繰り返す

(θ)p ̃

θ(0) m ← 0

q( < )θ̃ θ(m) θ̃

A( < )θ̃ θ(m) θ̃

←θ(m+1) θ̃ ←θ(m+1) θ(m)

m ← m + 1 M

16 / 55

Page 17: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

提案分布は正規分布(randn)

# p: (unnormalized) probability density function# θ₀: initial state# M: number of samples# ϵ: step sizefunction metropolis(p::Function, θ₀::Vector{Float64}, M::Int, ϵ::Float64) d = length(θ₀) # allocate samples' holder samples = Array(typeof(θ₀), M) # set the current state to the initial state θ = θ₀ for m in 1:M # generate a candidate sample from # the proposal distribution (normal distribution) θ ̃= randn(d) * ϵ + θ if rand() < min(1.0, p(θ)̃ / p(θ)) # accept the proposal θ = θ̃ end samples[m] = θ print_sample(θ) end samplesend

metropolis.jl

17 / 55

Page 18: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

呼び出し側

2変数の変数間に相関のある正規分布

# meanμ = [0.0, 0.0]# covariance matrixΣ = [1.0 0.8; 0.8 1.0]# precision matrixΛ = inv(Σ)# unnormalized multivariate normal distributionnormal = x -> exp(-0.5 * ((x - μ)' * Λ * (x - μ))[1])

初期値x₀ 、サンプル数M、ステップ幅 ϵを指定してサンプリング

samples = metropolis(normal, x₀, M, ϵ)

18 / 55

Page 19: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

結果 ­ created with Gadfly.jl

x-4 -2 0 2 4

500

200

400

300

1

100

Iteration

-4

-2

0

2

4

y

Metropolis (ϵ = 1.0)

19 / 55

Page 20: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

x-3 -2 -1 0 1

500

200

400

300

1

100

Iteration

-2.0

-1.5

-1.0

-0.5

0.0

0.5

y

Metropolis (ϵ = 0.1)

x-3 -2 -1 0 1 2

500

200

400

300

1

100

Iteration

-3

-2

-1

0

1

2

3

y

Metropolis (ϵ = 0.5)

x-4 -2 0 2 4

500

200

400

300

1

100

Iteration

-4

-2

0

2

4

y

Metropolis (ϵ = 1.0)

x-3 -2 -1 0 1 2 3

500

200

400

300

1

100

Iteration

-3

-2

-1

0

1

2

3

y

Metropolis (ϵ = 2.0)

結果 ­ created with Gadfly.jl

20 / 55

Page 21: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Metropolis­Hastingsの問題点

1. 棄却率のトレードオフ

ステップサイズ の値で、棄却率と性能のトレードオフがある

2. ランダムウォーク

サンプルの列がランダムウォークをする

ϵ

21 / 55

Page 22: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

問題1: 棄却率のトレードオフ

確率分布の値が集中してるのはごく一部だけ。

ステップサイズ 大 ➠ 大きく動けるが、棄却率が上がる

ステップサイズ 小 ➠ 棄却率は抑えられるが、あまり動けない

MCMCからなるべく独立なサンプルを得るにはステップサイズを大きくしたいが、棄却率が上がるためサンプリングの効率が悪くなるトレ

ードオフがある。

次元(サンプリングする変数)によってパラメータ の良い値が異なり、調節が難しい。

ϵ

ϵ

ϵ

22 / 55

Page 23: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

問題2: ランダムウォーク

Metropolis-Hastingsから得られたサンプル列は、ランダムウォークを

している

提案分布が提示する候補点 は、現在の値 からみて等方的

が移動した先からすぐに戻ってきてしまうことがある

ランダムウォークでは(おおまかに言って)反復回数の平方根に比例した距離しか進めない

空間を端から端まで渡るのにかなり反復回数が必要になる

θ̃ θ(m)

θ(m)

23 / 55

Page 24: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Hamiltonian Mote Carlo (HMC)Hamiltonian circuit on a small rhombicosidodecahedron by fdecomite is licensed under CC BY 2.0

24 / 55

Page 25: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Hamiltonian Monte Carlo

Hamiltonian Monte Carlo法(HMC)は、ハミルトン力学(Hamiltoniandynamics)を元に考案されたMCMC法のひとつ。

確率密度関数の勾配を利用する (離散的な確率分布はできない)

空間での粒子の運動を追ってサンプルを得る

他のMCMCのアルゴリズムと比較して、相関の少ない良いサンプ

ルが得られる

この手法を発展させたNo-U-Turn Sampler (NUTS)はStanというベイズ推定のためのプログラミング言語に実装されている

25 / 55

Page 26: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Boltzmann分布

状態 のエネルギー と確率分布 は次のように関連付けられる。

ここで、 は確率分布の正規化定数である。

これを逆に使えば、確率分布のエネルギーが計算できる。

x E(x) P(x)

P(x) = exp (+E(x))1Z

Z

E(x) = + log P(x) + log Z

26 / 55

Page 27: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

ハミルトン力学

粒子の運動を考える。 を粒子の位置ベクトル、 を運動量ベクトルとした時の粒子の運動を決めるハミルトン方程式:

ここで、ハミルトニアン はポテンシャルエネルギー と運動エネルギー の和として定義される。

θ r

dθi

dtdri

dt

=�H�ri

= +�H�θi

H(θ, r) U(θ)K(r)

H(θ, r) = U(θ) + K(r)

27 / 55

Page 28: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

サンプリングへの応用

変数

位置ベクトル : サンプリングしたい確率変数

運動量ベクトル : 運動の補助的な変数

エネルギー

ポテンシャルエネルギー : Boltzmann分布を基に設定

運動エネルギー : 適当な運動エネルギーに設定

位置ベクトルと運動量ベクトルの同時分布 は より以下のように分解できる。

θ

r

U(θ)

K(r)

p(θ, r)H(θ, r) = U(θ) + K(r)

p(θ, r) = exp (+H(θ, r)) = exp (+U(θ)) exp (+K(r))1Z

1Z

28 / 55

Page 29: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

HMCの受容確率

提示された候補点に関する受容確率は以下のようになる。

理論的には、 の値は不変なので ゆえ必ず受理される ( ) はずだが、コンピュータで数値的にハミルトン方

程式を離散化して解くと必ず誤差が発生するため現実的には棄却率は

ゼロでない。

A( < θ) = min (1, exp {H(θ, r) + H( , )})θ̃ θ̃ r ̃

H H(θ, r) + H( , ) = 0θ̃ r ̃ A = 1

29 / 55

Page 30: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Leapfrog離散化

ハミルトン方程式は解析的に解くのは難しいので、数値積分を行う。

そこでは、Leapfrog離散化という以下の更新式をつかう。

(t + ϵ/2)ri

(t + ϵ)θi

(t + ϵ)ri

= (t) +riϵ2�U(θ(t))�θi

= (t) + ϵ (t + ϵ/2)θi ri

= (t + ϵ/2) +riϵ2�U(θ(t + ϵ))

�θi

30 / 55

Page 31: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

なぜLeapfrog離散化なのか

同時分布 を不変にするためには、 の体積を不変にしなければならない

しかし、Euler法などでは(精度の悪さを無視しても)体積が変化してしまうので、 が不変にならない

Leapfrog離散化では、3つの更新式はそれぞれ剪断写像(shearmapping)なので、それぞれ適用しても体積が変化しない

"VerticalShear m=1.25" by RobHar - Own work using Inkscape. Licensed under Public domain via Wikimedia Commons -

http://commons.wikimedia.org/wiki/File:VerticalShear_m%3D1.25.svg#mediaviewer/File:VerticalShear_m%3D1.25.svg

p(θ, r) H(θ, r)

p(θ, r)

31 / 55

Page 32: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

HMCによるサンプリングアルゴリズム

1. 初期状態 を決め、 に設定する

2. 運動量を正規分布などからサンプリングする

3. からステップサイズ でLeapfrog離散化による更新を 回繰り返し、 を得る

4. 確率 で受理し、そうでなけ

れば棄却する

5. 受理された場合は と設定し、棄却された場合は と設定する

6. として、2~5を 個のサンプルが得られるまで繰り返す

θ(0) m ← 0

θ(m) ϵ Lθ̃

min (1, exp {H(θ, r) + H( , )})θ̃ r ̃

←θ(m+1) θ̃ ←θ(m+1) θ(m)

m ← m + 1 M

32 / 55

Page 33: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

# U : potential energy function# ∇U : gradient of the potential energy function# θ₀ : initial state# M : number of samples# ϵ : step size# L : number of stepsfunction hmc(U::Function, ∇U::Function, θ₀::Vector{Float64}, M::Int, ϵ::Float64, L::Int) d = length(θ₀) # allocate sampels' holder samples = Array(typeof(θ₀), M) # set the current sate to the initail state θ = θ₀ for m in 1:M # sample momentum variable p = randn(d) H = U(θ) + p ⋅ p / 2 θ ̃= θ for l in 1:L p -= ϵ / 2 * ∇U(θ)̃ # half step in momentum variable θ ̃+= ϵ * p # full step in location variable p -= ϵ / 2 * ∇U(θ)̃ # half step in momentum variable again end H̃ = U(θ)̃ + p ⋅ p / 2 if randn() < min(1.0, exp(H - H̃)) # accept the proposal θ = θ̃ end samples[m] = θ print_sample(θ) end samplesend

hmc.jl

33 / 55

Page 34: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

結果 ­ created with Gadfly.jl

x-4 -2 0 2 4

100

200

300

1

500

400

Iteration

-4

-2

0

2

4

y

HMC (ϵ = 0.1, L = 10)

L = 10 34 / 55

Page 35: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

x-2 -1 0 1

100

200

300

1

500

400

Iteration

-2

-1

0

1

y

HMC (ϵ = 0.01, L = 10)

x-4 -2 0 2 4

100

200

300

1

500

400

Iteration

-3

-2

-1

0

1

2

3

y

HMC (ϵ = 0.05, L = 10)

x-4 -2 0 2 4

100

200

300

1

500

400

Iteration

-4

-2

0

2

4

y

HMC (ϵ = 0.1, L = 10)

x-4 -2 0 2 4

100

200

300

1

500

400

Iteration

-4

-2

0

2

4

y

HMC (ϵ = 0.5, L = 10)

結果 ­ created with Gadfly.jl

L = 1035 / 55

Page 36: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

x-0.3 -0.2 -0.1 0.0 0.1

100

200

300

1

500

400

Iteration

-0.3

-0.2

-0.1

0.0

0.1

y

HMC (ϵ = 0.01, L = 1)

x-1.0 -0.5 0.0 0.5

100

200

300

1

500

400

Iteration

-1.5

-1.0

-0.5

0.0

0.5

y

HMC (ϵ = 0.05, L = 1)

x-2 -1 0 1

100

200

300

1

500

400

Iteration

-2

-1

0

1

y

HMC (ϵ = 0.1, L = 1)

x-4 -2 0 2 4

100

200

300

1

500

400

Iteration

-3

-2

-1

0

1

2

3

y

HMC (ϵ = 0.5, L = 1)

結果 ­ created with Gadfly.jl

L = 136 / 55

Page 37: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

x-4 -2 0 2 4

100

200

300

1

500

400

Iteration

-3

-2

-1

0

1

2

3

y

HMC (ϵ = 0.01, L = 50)

x-3 -2 -1 0 1 2 3

100

200

300

1

500

400

Iteration

-4

-2

0

2

4

y

HMC (ϵ = 0.05, L = 50)

x-4 -2 0 2 4

100

200

300

1

500

400

Iteration

-4

-2

0

2

4

y

HMC (ϵ = 0.1, L = 50)

x-2 -1 0 1 2 3

100

200

300

1

500

400

Iteration

-2

-1

0

1

2

3

y

HMC (ϵ = 0.5, L = 50)

結果 ­ created with Gadfly.jl

L = 5037 / 55

Page 38: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

HMCが解決したこと

エネルギーの勾配情報を使うことで、可能になったこと:

ステップサイズ を十分小さくとればLeapfrogの積分誤差が小さくなり、棄却率を低く抑えられる

粒子が ステップ連続して滑らかに移動するため、ランダムウォ

ークと比べて遠くまで動ける

棄却率を抑えつつ前の位置より遠くまで動くことができるようにな

り、得られるサンプルがより独立なサンプルに近づいた。

ϵ

L

38 / 55

Page 39: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

HMCの難しさ

HMCの利点は、運動を調節する2つのパラメータ

ステップサイズ

ステップ数

の値がちょうど良い値に設定されているということに依存している。

分布の形状によってちょうど良い値が変わるため、これらの値をどん

な分布にもうまくいくよう予め設定するのは不可能。

ϵ

L

39 / 55

Page 40: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

 と   の調整を間違えるとどうなるか

ステップサイズ :

が小さすぎる ➠ 粒子があまり動かない

が大きすぎる ➠ leapfrog離散化が荒すぎて棄却率が上がる

を小さくすると を大きくしないといけないため、計算コストもか

かる。

ステップ数 :

が小さすぎる ➠ ランダムウォークをしてしまう

が大きすぎる ➠ 粒子が引き返す (Uターン)

➠ 自動的にパラメータを調節したい

ϵ L

ϵ

ϵ

ϵ

ϵ L

L

L

L

40 / 55

Page 41: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

No­U­Turn Sampler (NUTS)No Turning Back by Pak Gwei is licensed under CC BY-NC-SA 2.0

41 / 55

Page 42: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

No­U­Turn Sampler

HMCはステップサイズ とステップ数 の2つのパラメータに敏感だ

ったが、 No-U-Turn Sampler (NUTS)ではこれらのパラメータ(特に )をうまいこと調節してくれる。

の調節 ➠ サンプリング前のdual averagingにより最適化

の調節 ➠ サンプリング中の粒子の怪しい運動を検出して止まる

ヒトが手でパラメータのチューニングすることなく最適なHMCサンプラーと同じくら質の良いサンプルが得られるようになっている。

ϵ L

L

ϵ

L

42 / 55

Page 43: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

突然ですがNUTSのアルゴリズムです

(Hoffman & Gelman, 2014) 43 / 55

Page 44: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

NUTSの要点

さすがに全部を紹介するのは厳しいので要点を紹介すると、

サンプル間の軌跡は、妥当な範囲で長い方がいい

なので予め を設定せず、軌跡をどんどん伸ばしていく

伸ばしすぎて運動がUターンを始めたら、軌跡を伸ばすのを止める

その軌跡にあるデータ点から、新しいサンプルを得る

軌跡からのサンプリングは、詳細釣り合いを崩さないようにする

L

詳細釣り合い(detailed balance)とは、分布が不変になるための十分条件❏

44 / 55

Page 45: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

No! U­Turn!!

軌跡の長さの時間変化は、始点 から現在の点 までのベクトルと運動量ベクトル の積に比例する:

この値が 以下になったら、軌跡がUターンをし始めたことになる。

θ θ̃ r ̃

= ( + θ ( + θ) = ( + θddt

( + θ ( + θ)θ̃ )T θ̃ 2

θ̃ )T ddt

θ̃ θ̃ )Tr ̃

0

45 / 55

Page 46: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

長いので気になる方はサンプルコードのnuts.jlを参照して下さい。

# L: logarithm of the joint density θ# ∇L: gradient of L# θ₀: initial state# M: number of samples# ϵ: step sizefunction nuts(L::Function, ∇L::Function, θ₀::Vector{Float64}, M::Int, ϵ::Float64) d = length(θ₀) samples = Array(typeof(θ₀), M) θ = θ₀ for m in 1:M r₀ = randn(d) u = rand() * exp(L(θ) - r₀ ⋅ r₀ / 2) θ⁻ = θ⁺ = θ r⁻ = r⁺ = r₀ C = Set([(θ, r₀)]) j = 0 s = 1 while s == 1 v = randbool() ? -1 : 1 if v == -1 θ⁻, r⁻, _, _, C′, s′ = build_tree(L, ∇L, θ⁻, r⁻, u, v, j, ϵ) else _, _, θ⁺, r⁺, C′, s′ = build_tree(L, ∇L, θ⁺, r⁺, u, v, j, ϵ) end if s′ == 1 C = C ∪ C′ end s = s′ * ((θ⁺ - θ⁻) ⋅ r⁻ ≥ 0) * ((θ⁺ - θ⁻) ⋅ r⁺ ≥ 0) j += 1 end θ, _ = rand(C) samples[m] = θ print_sample(θ) end samplesend

nuts.jl

46 / 55

Page 47: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

結果 ­ created with Gadfly.jl

x-3 -2 -1 0 1 2 3

100

400

200

1

300

500

Iteration

-3

-2

-1

0

1

2

3

y

NUTS (ϵ = 0.1)

47 / 55

Page 48: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

x-3 -2 -1 0 1 2 3

100

400

200

1

300

500

Iteration

-4

-2

0

2

4

y

NUTS (ϵ = 0.01)

x-3 -2 -1 0 1 2 3

100

400

200

1

300

500

Iteration

-3

-2

-1

0

1

2

3

y

NUTS (ϵ = 0.05)

x-3 -2 -1 0 1 2 3

100

400

200

1

300

500

Iteration

-3

-2

-1

0

1

2

3

y

NUTS (ϵ = 0.1)

x-3 -2 -1 0 1 2 3

100

400

200

1

300

500

Iteration

-3

-2

-1

0

1

2

3

y

NUTS (ϵ = 0.5)

結果 ­ created with Gadfly.jl

48 / 55

Page 49: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Juliaで使えるMCMCパッケージ

49 / 55

Page 50: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Juliaで使えるMCMCパッケージ

MCMC.jl - https://github.com/JuliaStats/MCMC.jl

サンプラーのデパート (12種類!)

ドキュメントがない

Stan.jl - https://github.com/goedman/Stan.jl

Stanバインディング (via CmdStan)

そのうちMCMC.jlに取り込まれるっぽい?

Mamba.jl - https://github.com/brian-j-smith/Mamba.jl

かなり本気っぽいJulia製の実用的なMCMCフレームワーク

充実のドキュメント

50 / 55

Page 51: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

まとめ

HMCは粒子の運動を追跡してサンプリングすることにより、棄却

率を下げられる

NUTSはHMCの難しいパラメータ調節を、自動化してくれる

Mamba.jlがJuliaの実用的なサンプラーの注目株か

51 / 55

Page 52: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

参考

Bishop, C. M. (2006). Pattern recognition and machine learning.New York: springer. (元田浩 (2012) サンプリング法 パターン認識

と機械学習 下, pp.237-273. 丸善出版)

Hoffman, M. D., & Gelman, A. (2014). The No-U-Turn Sampler :Adaptively Setting Path Lengths in Hamiltonian Monte Carlo.Journal of Machine Learning Research, 15, 1351–1381.MacKay, D. J. C. (2003). Information Theory, Inference, andLearning Algorithms. Cambridge University Press.Neal, R. M. (2011). MCMC Using Hamiltonian Dynamics. InHandbook of Markov Chain Monte Carlo, pp.113-162. Chapman &Hall/CRC.

豊田秀樹 (2008). マルコフ連鎖モンテカルロ法 朝倉書店

52 / 55

Page 53: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

おまけ

53 / 55

Page 54: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

Juliaのソースコードと擬似コードの異常な類似

function build_tree(L::Function, ∇L::Function, θ::Vector{Float64}, r::Vector{Float64}, u::Float64, v::Int if j == 0 θ′, r′ = leapfrog(∇L, θ, r, v * ϵ) C′ = u ≤ exp(L(θ′) - r′ ⋅ r′ / 2) ? Set([(θ′, r′)]) : Set([]) s′ = int(L(θ′) - r′ ⋅ r′ / 2 > log(u) - Δmax) return θ′, r′, θ′, r′, C′, s′ else θ⁻, r⁻, θ⁺, r⁺, C′, s′ = build_tree(L, ∇L, θ, r, u, v, j - 1, ϵ) if v == -1 θ⁻, r⁻, _, _, C″, s″ = build_tree(L, ∇L, θ⁻, r⁻, u, v, j - 1, ϵ) else _, _, θ⁺, r⁺, C″, s″ = build_tree(L, ∇L, θ⁺, r⁺, u, v, j - 1, ϵ) end s′ = s′ * s″ * ((θ⁺ - θ⁻) ⋅ r⁻ ≥ 0) * ((θ⁺ - θ⁻) ⋅ r⁺ ≥ 0) C′ = C′ ∪ C″ return θ⁻, r⁻, θ⁺, r⁺, C′, s′ endend nuts.jl

54 / 55

Page 55: Juliaで学ぶ Hamiltonian Monte Carlo (NUTS 入り)

ハミルトニアンの不変性の証明

dHdt

= { + }∑i

�H�xi

dxi

dt�H�pi

dpi

dt

= { + } = 0∑i

�H�pi

�H�xi

�H�pi

�H�xi

55 / 55