-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMCMC.py
More file actions
99 lines (82 loc) · 2.31 KB
/
Copy pathMCMC.py
File metadata and controls
99 lines (82 loc) · 2.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import numpy as np
import numpy.linalg as npla
def gaussian(x, sigma, sampled=None):
"""
"""
if sampled is None:
L = npla.cholesky(sigma)
z = np.random.randn(x.shape[0], 1)
return np.dot(L, z+x)
else:
return np.exp(-0.5*np.dot( (x-sampled).T, np.dot(npla.inv(sigma), (x-sampled))))[0,0]
def gaussian_1d(x, sigma, sampled=None):
"""
1d Gaussian
"""
if sampled is None:
return sigma*np.random.randn(1)[0]
else:
return np.exp(-0.5( (x-sampled)**2)/sigma**2)
def chi_sq(x, sampled = None, n = 0):
"""
chi squared function. Adapted for
usage in metropolis-hastings.
"""
if sampled is None:
return np.random.chisquare(n)
else:
return np.power(sampled,0.5*n - 1)*np.exp(-0.5*sampled)
def inv_chi_sq(theta, n, a):
"""
scaled inverse chi squared function.
"""
return np.power(theta, -0.5*n)*np.exp(-a/(2*theta))
def metropolis(f, proposal, old):
"""
basic metropolis algorithm, according to the original,
(1953 paper), needs symmetric proposal distribution.
"""
new = proposal(old)
alpha = np.min([f(new)/f(old), 1])
u = np.random.uniform()
# _cnt_ indicates if new sample is used or not.
cnt = 0
if (u < alpha):
old = new
cnt = 1
return old, cnt
def met_hast(f, proposal, old):
"""
metropolis_hastings algorithm.
"""
new = proposal(old)
alpha = np.min([(f(new)*proposal(new, sampled = old))/(f(old) * proposal(old, sampled = new)), 1])
u = np.random.uniform()
cnt = 0
if (u < alpha):
old = new
cnt = 1
return old, cnt
def run_chain(chainer, f, proposal, start, n, take=1):
"""
_chainer_ is one of Metropolis, MH, Gibbs ...
_f_ is the unnormalized density function to sample
_proposal_ is the proposal distirbution
_start_ is the initial start of the Markov Chain
_n_ length of the chain
_take_ thinning
"""
count = 0
samples = [start]
for i in range(n):
start, c = chainer(f, proposal, start)
count = count + c
if i%take is 0:
samples.append(start)
return samples, count
def uni_prop(x, frm, to, sampled=None):
"""
a uniform proposal generator --
is symmetric!
"""
return np.random.uniform(frm, to)