Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 096d6fa

Browse files
aloctavodiajunpenglao
authored andcommittedAug 18, 2018
Refactor SMC and properly compute marginal likelihood (#3124)
* [WIP] refactor SMC and properly compute marginal likelihood * generalize to variables with shape > 1 * fix tests * use sample_prior_predictive to generate initial population * fix tests, for real * make test more robust, just in case * add experimental warning message add change to release note
1 parent cf0614e commit 096d6fa

File tree

6 files changed

+352
-1286
lines changed

6 files changed

+352
-1286
lines changed
 

‎RELEASE-NOTES.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Release Notes
22

33

4-
## PyMC3 3.6
4+
## PyMC3 3.6 (unreleased)
55

66
- Renamed `sample_ppc()` and `sample_ppc_w()` to `sample_posterior_predictive()` and `sample_posterior_predictive_w()`, respectively.
7+
- Refactor SMC and properly compute marginal likelihood (#3124)
8+
79

810
## PyMC 3.5 (July 21 2018)
911

@@ -440,3 +442,4 @@ Thus, Thomas, Chris and I are pleased to announce that PyMC3 is now in Beta.
440442
* maahnman <github@mm.maahn.de>
441443
* paul sorenson <paul@metrak.com>
442444
* zenourn <daniel@zeno.co.nz>
445+

‎pymc3/backends/smc_text.py

Lines changed: 0 additions & 482 deletions
This file was deleted.

‎pymc3/sampling.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -323,23 +323,12 @@ def sample(draws=500, step=None, init='auto', n_init=200000, start=None, trace=N
323323
if isinstance(step, pm.step_methods.smc.SMC):
324324
if step_kwargs is None:
325325
step_kwargs = {}
326-
if chains is None:
327-
chains = 100
328-
if cores is None:
329-
cores = 1
330326
test_folder = mkdtemp(prefix='SMC_TEST')
331-
trace = smc.sample_smc(samples=draws,
332-
chains=chains,
327+
trace = smc.sample_smc(draws=draws,
333328
step=step,
334-
start=start,
335-
homepath=step_kwargs.get('homepath', test_folder),
336-
stage=step_kwargs.get('stage', 0),
337-
cores=cores,
338329
progressbar=progressbar,
339330
model=model,
340-
random_seed=random_seed,
341-
rm_flag=step_kwargs.get('rm_flag', True),
342-
**kwargs)
331+
random_seed=random_seed)
343332
else:
344333
if cores is None:
345334
cores = min(4, _cpu_count())

‎pymc3/step_methods/smc.py

Lines changed: 192 additions & 614 deletions
Large diffs are not rendered by default.

‎pymc3/tests/test_smc.py

Lines changed: 19 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,15 @@
11
import pymc3 as pm
22
import numpy as np
3-
from pymc3.backends.smc_text import TextStage
4-
import pytest
5-
from tempfile import mkdtemp
6-
import shutil
73
import theano.tensor as tt
8-
import theano
94

105
from .helpers import SeededTest
116

127

13-
@pytest.mark.xfail(condition=(theano.config.floatX == "float32"), reason="Fails on float32")
148
class TestSMC(SeededTest):
159

1610
def setup_class(self):
1711
super(TestSMC, self).setup_class()
18-
self.test_folder = mkdtemp(prefix='ATMIP_TEST')
19-
20-
self.samples = 1500
21-
self.chains = 200
12+
self.samples = 1000
2213
n = 4
2314
mu1 = np.ones(n) * (1. / 2)
2415
mu2 = - mu1
@@ -40,44 +31,35 @@ def two_gaussians(x):
4031
- 0.5 * (x - mu2).T.dot(isigma).dot(x - mu2)
4132
return tt.log(w1 * tt.exp(log_like1) + w2 * tt.exp(log_like2))
4233

43-
with pm.Model() as self.ATMIP_test:
34+
with pm.Model() as self.SMC_test:
4435
X = pm.Uniform('X', lower=-2, upper=2., shape=n)
4536
llk = pm.Potential('muh', two_gaussians(X))
4637

4738
self.muref = mu1
4839

4940

50-
@pytest.mark.parametrize(['cores', 'stage'], [[1, 0], [2, 6]])
51-
def test_sample_n_core(self, cores, stage):
52-
step_kwargs = {'homepath': self.test_folder, 'stage': stage}
53-
with self.ATMIP_test:
41+
def test_sample(self):
42+
with self.SMC_test:
5443
mtrace = pm.sample(draws=self.samples,
55-
chains=self.chains,
56-
cores=cores,
57-
step = pm.SMC(),
58-
step_kwargs=step_kwargs)
44+
step = pm.SMC())
5945

60-
x = mtrace.get_values('X')
46+
x = mtrace['X']
6147
mu1d = np.abs(x).mean(axis=0)
6248
np.testing.assert_allclose(self.muref, mu1d, rtol=0., atol=0.03)
63-
# Scenario IV Ching, J. & Chen, Y. 2007
64-
#assert np.round(np.log(self.ATMIP_test.marginal_likelihood)) == -12.0
65-
66-
def test_stage_handler(self):
67-
stage_number = -1
68-
stage_handler = TextStage(self.test_folder)
6949

70-
step = stage_handler.load_atmip_params(stage_number, model=self.ATMIP_test)
71-
assert step.stage == stage_number
50+
def test_ml(self):
51+
data = np.repeat([1, 0], [50, 50])
52+
marginals = []
53+
a_prior_0, b_prior_0 = 1., 1.
54+
a_prior_1, b_prior_1 = 20., 20.
7255

73-
corrupted_chains = stage_handler.recover_existing_results(stage_number,
74-
self.samples / self.chains,
75-
self.chains,
76-
step,
77-
model=self.ATMIP_test)
78-
assert len(corrupted_chains) == self.chains
56+
for alpha, beta in ((a_prior_0, b_prior_0), (a_prior_1, b_prior_1)):
57+
with pm.Model() as model:
58+
a = pm.Beta('a', alpha, beta)
59+
y = pm.Bernoulli('y', a, observed=data)
60+
trace = pm.sample(2000, step=pm.SMC())
61+
marginals.append(model.marginal_likelihood)
62+
# compare to the analytical result
63+
assert abs((marginals[1] / marginals[0]) - 4.0) <= 1
7964

80-
rtrace = stage_handler.load_result_trace(model=self.ATMIP_test)
8165

82-
def teardown_class(self):
83-
shutil.rmtree(self.test_folder)

‎pymc3/tests/test_step.py

Lines changed: 135 additions & 139 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.