-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathlangevin_cached_model.py
146 lines (112 loc) · 4.67 KB
/
langevin_cached_model.py
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import pymc3 as pm
import theano.tensor as tt
from theano import shared
import numpy as np
import scipy as sp
# theano.config.gcc.cxxflags = "-fbracket-depth=16000" # default is 256
class Ornstein_Uhlenbeck(pm.Continuous):
"""
Ornstein-Uhlenbeck Process
Parameters
----------
B : tensor
B > 0, B = exp(-(D/A)*delta_t)
A : tensor
A > 0, amplitude of fluctuation <x**2>=A
delta_t: scalar
delta_t > 0, time step
"""
def __init__(self, A=None, B=None,
*args, **kwargs):
super(Ornstein_Uhlenbeck, self).__init__(*args, **kwargs)
self.A = A
self.B = B
self.mean = 0.
def logp(self, x):
A = self.A
B = self.B
x_im1 = x[:-1]
x_i = x[1:]
ou_like = pm.Normal.dist(mu=x_im1*B, tau=1.0/A/(1-B**2)).logp(x_i)
return pm.Normal.dist(mu=0.0,tau=1.0/A).logp(x[0]) + tt.sum(ou_like)
class BayesianModel(object):
samples = 10000
target_accept = 0.8
def __init__(self, cache_model=True):
self.cached_model = None
self.cached_start = None
self.cached_sampler = None
self.shared_vars = {}
def cache_model(self, **inputs):
self.shared_vars = self._create_shared_vars(**inputs)
self.cached_model = self.create_model(**self.shared_vars)
def create_model(self, **inputs):
raise NotImplementedError('This method has to be overwritten.')
def _create_shared_vars(self, **inputs):
shared_vars = {}
for name, data in inputs.items():
shared_vars[name] = shared(np.asarray(data), name=name)
return shared_vars
def run(self, reinit=True, **inputs):
if self.cached_model is None:
self.cache_model(**inputs)
for name, data in inputs.items():
self.shared_vars[name].set_value(data)
trace = self._inference(reinit=reinit)
return trace
def _inference(self, reinit=True):
with self.cached_model:
trace = pm.sample(samples=self.samples,target_accept=self.target_accept)
return trace
class OU_DA(BayesianModel):
"""Bayesian model for a Ornstein-Uhlenback process.
The model has inputs x, and prior parameters for
uniform distributions for D and A
"""
def create_model(self, x=None, d_bound=None, a_bound=None, delta_t=None, N=None):
with pm.Model() as model:
D = pm.Uniform('D', lower=0, upper=d_bound)
A = pm.Uniform('A', lower=0, upper=a_bound)
B = pm.Deterministic('B', pm.math.exp(-delta_t * D / A))
path = Ornstein_Uhlenbeck('path',A=A, B=B, observed=x)
return model
class OU_BA(BayesianModel):
"""Bayesian model for a Ornstein-Uhlenback process.
The model has inputs x, and prior parameters for
uniform distributions for B and A
"""
def create_model(self, x=None, b_bound=None, a_bound=None, delta_t=None, N=None):
with pm.Model() as model:
B = pm.Uniform('B', lower=0, upper=b_bound)
A = pm.Uniform('A', lower=0, upper=a_bound)
path = Ornstein_Uhlenbeck('path',B=B, A=A, observed=x)
return model
class LangevinPlusNoiseIG(BayesianModel):
"""Bayesian model for a Ornstein-Uhlenback process + noise.
The model has inputs x, and prior parameters for
gamma distributions for D and A
"""
def create_model(self, x=None, aD=None, bD=None, aA=None, bA=None, aN=None, bN=None, delta_t=None, N=None):
with pm.Model() as model:
D = pm.InverseGamma('D', alpha=aD, beta=bD)
A = pm.Gamma('A', alpha=aA, beta=bA)
sN = pm.InverseGamma('sN', alpha=aN, beta=bN)
B = pm.Deterministic('B', pm.math.exp(-delta_t * D / A))
path = Ornstein_Uhlenbeck('path',A=A, B=B, shape=(N,))
X_obs = pm.Normal('X_obs', mu=path, sd=sN, observed=x)
return model
class LangevinIG2(BayesianModel):
"""Bayesian model for a Ornstein-Uhlenback process.
The model has inputs x, and prior parameters for
gamma distributions for D and A
"""
def create_model(self, x1=None, x2=None, aD=None, bD=None, aA1=None, bA1=None, aA2=None, bA2=None, delta_t=None, N=None):
with pm.Model() as model:
D = pm.InverseGamma('D', alpha=aD, beta=bD)
A1 = pm.Gamma('A1', alpha=aA1, beta=bA1)
A2 = pm.Gamma('A2', alpha=aA2, beta=bA2)
B1 = pm.Deterministic('B1', pm.math.exp(-delta_t * D / A1))
B2 = pm.Deterministic('B2', pm.exp.math(-delta_t * D / A2))
path1 = Ornstein_Uhlenbeck('path1',A=A1, B=B1, observed=x1)
path2 = Ornstein_Uhlenbeck('path2', A=A2, B=B2, observed=x2)
return model