16
16
17
17
import numpy as np
18
18
from scipy .special import logsumexp
19
- from fastprogress .fastprogress import progress_bar
20
- import multiprocessing as mp
21
19
import warnings
22
20
from theano import function as theano_function
21
+ from arviz import psislw
23
22
24
23
from ..model import modelcontext , Point
25
24
from ..parallel_sampling import _cpu_count
26
- from ..theanof import inputvars , make_shared_replacements
27
- from ..vartypes import discrete_types
25
+ from ..theanof import floatX , inputvars , make_shared_replacements , join_nonshared_inputs
28
26
from ..sampling import sample_prior_predictive
29
- from ..theanof import floatX , join_nonshared_inputs
30
- from ..step_methods .arraystep import metrop_select
31
- from ..step_methods .metropolis import MultivariateNormalProposal
32
27
from ..backends .ndarray import NDArray
33
28
from ..backends .base import MultiTrace
34
29
41
36
class SMC :
42
37
def __init__ (
43
38
self ,
44
- draws = 1000 ,
39
+ draws = 2000 ,
45
40
kernel = "metropolis" ,
46
41
n_steps = 25 ,
47
- parallel = False ,
48
42
start = None ,
49
- cores = None ,
50
43
tune_steps = True ,
51
44
p_acc_rate = 0.99 ,
52
45
threshold = 0.5 ,
53
46
epsilon = 1.0 ,
54
47
dist_func = "absolute_error" ,
55
48
sum_stat = "Identity" ,
56
- progressbar = False ,
57
49
model = None ,
58
50
random_seed = - 1 ,
59
51
):
60
52
61
53
self .draws = draws
62
54
self .kernel = kernel
63
55
self .n_steps = n_steps
64
- self .parallel = parallel
65
56
self .start = start
66
- self .cores = cores
67
57
self .tune_steps = tune_steps
68
58
self .p_acc_rate = p_acc_rate
69
59
self .threshold = threshold
70
60
self .epsilon = epsilon
71
61
self .dist_func = dist_func
72
62
self .sum_stat = sum_stat
73
- self .progressbar = progressbar
74
63
self .model = model
75
64
self .random_seed = random_seed
76
65
@@ -79,23 +68,16 @@ def __init__(
79
68
if self .random_seed != - 1 :
80
69
np .random .seed (self .random_seed )
81
70
82
- if self .cores is None :
83
- self .cores = _cpu_count ()
84
-
85
71
self .beta = 0
86
72
self .max_steps = n_steps
87
73
self .proposed = draws * n_steps
88
74
self .acc_rate = 1
89
75
self .acc_per_chain = np .ones (self .draws )
90
- self .model .marginal_log_likelihood = 0
76
+ self .model .log_marginal_likelihood = 0
91
77
self .variables = inputvars (self .model .vars )
92
78
self .dimension = sum (v .dsize for v in self .variables )
93
- self .scalings = np .ones (self .draws ) * min (1 , 2.38 ** 2 / self .dimension )
94
- self .discrete = np .concatenate (
95
- [[v .dtype in discrete_types ] * (v .dsize or 1 ) for v in self .variables ]
96
- )
97
- self .any_discrete = self .discrete .any ()
98
- self .all_discrete = self .discrete .all ()
79
+ self .scalings = np .ones (self .draws ) * 2.38 / (self .dimension ) ** 0.5
80
+ self .weights = np .ones (self .draws ) / self .draws
99
81
100
82
def initialize_population (self ):
101
83
"""
@@ -153,17 +135,8 @@ def initialize_logp(self):
153
135
"""
154
136
initialize the prior and likelihood log probabilities
155
137
"""
156
- if self .parallel and self .cores > 1 :
157
- self .pool = mp .Pool (processes = self .cores )
158
- priors = self .pool .starmap (
159
- self .prior_logp_func , [(sample ,) for sample in self .posterior ]
160
- )
161
- likelihoods = self .pool .starmap (
162
- self .likelihood_logp_func , [(sample ,) for sample in self .posterior ]
163
- )
164
- else :
165
- priors = [self .prior_logp_func (sample ) for sample in self .posterior ]
166
- likelihoods = [self .likelihood_logp_func (sample ) for sample in self .posterior ]
138
+ priors = [self .prior_logp_func (sample ) for sample in self .posterior ]
139
+ likelihoods = [self .likelihood_logp_func (sample ) for sample in self .posterior ]
167
140
168
141
self .prior_logp = np .array (priors ).squeeze ()
169
142
self .likelihood_logp = np .array (likelihoods ).squeeze ()
@@ -192,11 +165,9 @@ def update_weights_beta(self):
192
165
new_beta = 1
193
166
log_weights_un = (new_beta - old_beta ) * self .likelihood_logp
194
167
log_weights = log_weights_un - logsumexp (log_weights_un )
168
+ self .ess = np .exp (- logsumexp (log_weights * 2 ))
195
169
196
- ll_max = np .max (log_weights_un )
197
- self .model .marginal_log_likelihood += ll_max + np .log (
198
- np .exp (log_weights_un - ll_max ).mean ()
199
- )
170
+ self .model .log_marginal_likelihood += logsumexp (log_weights_un ) - np .log (self .draws )
200
171
self .beta = new_beta
201
172
self .weights = np .exp (log_weights )
202
173
@@ -218,13 +189,12 @@ def update_proposal(self):
218
189
"""
219
190
Update proposal based on the covariance matrix from tempered posterior
220
191
"""
221
- cov = np .cov (self .posterior , bias = False , rowvar = 0 )
192
+ cov = np .cov (self .posterior , ddof = 0 , aweights = self . weights , rowvar = 0 )
222
193
cov = np .atleast_2d (cov )
223
194
cov += 1e-6 * np .eye (cov .shape [0 ])
224
195
if np .isnan (cov ).any () or np .isinf (cov ).any ():
225
196
raise ValueError ('Sample covariances not valid! Likely "draws" is too small!' )
226
197
self .cov = cov
227
- self .proposal = MultivariateNormalProposal (cov )
228
198
229
199
def tune (self ):
230
200
"""
@@ -244,8 +214,8 @@ def tune(self):
244
214
self .proposed = self .draws * self .n_steps
245
215
246
216
def mutate (self ):
247
-
248
217
ac_ = np .empty ((self .n_steps , self .draws ))
218
+
249
219
proposals = (
250
220
np .random .multivariate_normal (
251
221
np .zeros (self .dimension ), self .cov , size = (self .n_steps , self .draws )
0 commit comments