Skip to content

Commit c59492b

Browse files
committed
first draft of split hmc
1 parent 119a1dc commit c59492b

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

examples/normal.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from mcex import *
2+
import numpy as np
3+
import theano
4+
5+
#import pydevd
6+
#pydevd.set_pm_excepthook()
7+
np.seterr(invalid = 'raise')
8+
9+
data = np.random.normal(size = (3, 20))
10+
11+
12+
model = Model()
13+
14+
n = 1
15+
x = AddVar(model, 'x', Normal(mu = 0, tau = 1.), (n))
16+
17+
#make a chain with some starting point
18+
chain = {'x' : np.zeros(n)}
19+
20+
21+
22+
#move the chain to the MAP which should be a good starting point
23+
chain = find_MAP(model, chain)
24+
hmc_cov = approx_cov(model, chain) #find a good orientation using the hessian at the MAP
25+
26+
step_method = split_hmc_step(model, model.vars, hmc_cov, chain, hmc_cov)
27+
#step_method = hmc_step(model, model.vars, hmc_cov)
28+
29+
ndraw = 3e3
30+
history = NpHistory(model.vars, ndraw) # an object that keeps track
31+
state, t = sample(ndraw, step_method, chain, history)
32+
33+
print "took :", t

mcex/step_methods/split_hmc.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
'''
2+
Created on Mar 7, 2011
3+
4+
@author: johnsalvatier
5+
'''
6+
from numpy import floor, concatenate, exp, zeros, diag, real
7+
from numpy.linalg import inv, cholesky, eig
8+
9+
10+
from utils import *
11+
from ..core import *
12+
13+
def split_hmc_step(model, vars, C, approx_loc, approx_C, step_size_scaling = .25, trajectory_length = 2. ):
14+
15+
mapp = DASpaceMap( vars)
16+
approx_loc = mapp.project(approx_loc)
17+
18+
n = C.shape[0]
19+
20+
logp_d_dict = model_logp_dlogp(model, vars)
21+
22+
step_size = step_size_scaling * n**(1/4.)
23+
24+
invC = inv(C)
25+
cholInvC = cholesky(invC)
26+
27+
A = zeros((2*n,2*n))
28+
A[:n,n:] = C
29+
A[n:,:n] = -approx_C
30+
31+
D, gamma = eig(A)
32+
33+
e = step_size
34+
R = real(gamma.dot(diag(exp(D* e))).dot(gamma.T))
35+
def step(logp_d, state, q0):
36+
37+
if state is None:
38+
state = SamplerHist()
39+
40+
nstep = int(floor(trajectory_length / step_size))
41+
42+
q = q0
43+
logp0, dlogp = logp_d(q)
44+
dlogp = dlogp + dot(approx_C, q - approx_loc)
45+
logp = logp0
46+
47+
# momentum scale proportional to inverse of parameter scale (basically sqrt(covariance))
48+
p = p0 = cholesky_normal( q.shape, cholInvC)
49+
50+
#use the leapfrog method
51+
52+
for i in range(nstep):
53+
#alternate full variable and momentum updates
54+
p = p - (e/2) * -dlogp # half momentum update
55+
56+
x = concatenate((q - approx_loc, p))
57+
x = dot(R, x)
58+
q = x[:n] + approx_loc
59+
60+
logp, dlogp = logp_d(q)
61+
dlogp = dlogp + dot(approx_C, q - approx_loc)
62+
63+
p = p - (e/2) * -dlogp # do a half step momentum update to finish off
64+
65+
66+
p = -p
67+
68+
mr = logp - logp0 + K(C, p0) - K(C, p)
69+
state.metrops.append(mr)
70+
71+
return state, metrop_select(mr, q, q0)
72+
73+
return array_step(step, logp_d_dict, vars)
74+
75+
76+
def K (cov, x):
77+
return .5 * dot(x,dot(cov, x))
78+
79+

0 commit comments

Comments
 (0)