Skip to content

Commit 4d53a36

Browse files
committed
WIP Perform initializing inside of sample instead of adding new sample_init() as per @fonnesbeck suggestion.
1 parent e3c8b63 commit 4d53a36

File tree

1 file changed

+35
-34
lines changed

1 file changed

+35
-34
lines changed

pymc3/sampling.py

+35-34
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import sys
1717
sys.setrecursionlimit(10000)
1818

19-
__all__ = ['sample', 'iter_sample', 'sample_ppc', 'sample_init']
19+
__all__ = ['sample', 'iter_sample', 'sample_ppc', 'init_nuts']
2020

2121

2222
def assign_step_methods(model, step=None, methods=(NUTS, HamiltonianMC, Metropolis,
@@ -81,8 +81,9 @@ def assign_step_methods(model, step=None, methods=(NUTS, HamiltonianMC, Metropol
8181
return steps
8282

8383

84-
def sample(draws, step=None, start=None, trace=None, chain=0, njobs=1, tune=None,
85-
progressbar=True, model=None, random_seed=-1):
84+
def sample(draws, step=None, init='advi', n_init=500000, start=None,
85+
trace=None, chain=0, njobs=1, tune=None, progressbar=True,
86+
model=None, random_seed=-1):
8687
"""
8788
Draw a number of samples using the given step method.
8889
Multiple step methods supported via compound step method
@@ -97,6 +98,15 @@ def sample(draws, step=None, start=None, trace=None, chain=0, njobs=1, tune=None
9798
A step function or collection of functions. If no step methods are
9899
specified, or are partially specified, they will be assigned
99100
automatically (defaults to None).
101+
init : str {'advi', 'advi_map', 'map', 'nuts'}
102+
Initialization method to use.
103+
* advi : Run ADVI to estimate posterior mean and diagonal covariance matrix.
104+
* advi_map: Initialize ADVI with MAP and use MAP as starting point.
105+
* map : Use the MAP as starting point.
106+
* nuts : Run NUTS and estimate posterior mean and covariance matrix.
107+
n_init : int
108+
Number of iterations of initializer
109+
If 'advi', number of iterations, if 'nuts', number of draws.
100110
start : dict
101111
Starting point in parameter space (or partial point)
102112
Defaults to trace.point(-1)) if there is a trace provided and
@@ -132,7 +142,14 @@ def sample(draws, step=None, start=None, trace=None, chain=0, njobs=1, tune=None
132142
"""
133143
model = modelcontext(model)
134144

135-
step = assign_step_methods(model, step)
145+
if step is None and init is not None and pm.model.all_continuous(model.vars):
146+
# By default, use NUTS sampler
147+
pm._log.info('Auto-assigning NUTS sampler...')
148+
start_, step = init_nuts(init=init, n_init=n_init, model=model)
149+
if start is None:
150+
start = start_
151+
else:
152+
step = assign_step_methods(model, step)
136153

137154
if njobs is None:
138155
import multiprocessing as mp
@@ -375,19 +392,16 @@ def sample_ppc(trace, samples=None, model=None, vars=None, size=None, random_see
375392
return {k: np.asarray(v) for k, v in ppc.items()}
376393

377394

378-
def sample_init(draws=2000, init='advi', n_init=500000, sampler='nuts',
379-
model=None, **kwargs):
395+
def init_nuts(init='advi', n_init=500000, model=None):
380396
"""Initialize and sample from posterior of a continuous model.
381397
382398
This is a convenience function. NUTS convergence and sampling speed is extremely
383399
dependent on the choice of mass/scaling matrix. In our experience, using ADVI
384400
to estimate a diagonal covariance matrix and using this as the scaling matrix
385401
produces robust results over a wide class of continuous models.
386402
387-
Parameteres
388-
-----------
389-
draws : int
390-
Number of posterior samples to draw.
403+
Parameters
404+
----------
391405
init : str {'advi', 'advi_map', 'map', 'nuts'}
392406
Initialization method to use.
393407
* advi : Run ADVI to estimate posterior mean and diagonal covariance matrix.
@@ -397,21 +411,21 @@ def sample_init(draws=2000, init='advi', n_init=500000, sampler='nuts',
397411
n_init : int
398412
Number of iterations of initializer
399413
If 'advi', number of iterations, if 'metropolis', number of draws.
400-
sampler : str {'nuts', 'hmc', advi'}
401-
Sampler to use. Will be initialized using init algorithm.
402-
* nuts : Run NUTS sampler with the init covariance estimation as the scaling matrix.
403-
* hmc : Run HamiltonianMC sampler with the init covariance estimation as the scaling matrix.
404-
* advi : Sample from variational posterior, requires init='advi'.
405-
**kwargs : additional keyword argumemts
406-
Additional keyword argumemts are forwared to pymc3.sample()
414+
model : Model (optional if in `with` context)
407415
408416
Returns
409417
-------
410-
MultiTrace object with access to sampling values
418+
start, nuts_sampler
419+
420+
start : pymc3.model.Point
421+
Starting point for sampler
422+
nuts_sampler : pymc3.step_methods.NUTS
423+
Instantiated and initialized NUTS sampler object
411424
"""
412425

413426
model = pm.modelcontext(model)
414-
pm._log.info('Initializing using {}...'.format(init))
427+
428+
pm._log.info('Initializing NUTS using {}...'.format(init))
415429

416430
if init == 'advi':
417431
v_params = pm.variational.advi(n=n_init)
@@ -433,19 +447,6 @@ def sample_init(draws=2000, init='advi', n_init=500000, sampler='nuts',
433447
else:
434448
raise NotImplemented('Initializer {} is not supported.'.format(init))
435449

436-
pm._log.info('Sampling using {}...'.format(sampler))
437-
if sampler == 'nuts':
438-
step = pm.NUTS(scaling=cov, is_cov=True)
439-
elif sampler == 'hmc':
440-
step = pm.HamiltonianMC(scaling=cov, is_cov=True)
441-
elif sampler != 'advi':
442-
raise NotImplemented('Sampler {} is not supported.'.format(init))
443-
444-
if sampler == 'advi':
445-
if init != 'advi':
446-
raise ValueError("To sample via ADVI, you have to set init='advi'.")
447-
trace = pm.variational.sample_vp(v_params, draws=draws)
448-
else:
449-
trace = pm.sample(step=step, start=start, draws=draws, **kwargs)
450+
step = pm.NUTS(scaling=cov, is_cov=True)
450451

451-
return trace
452+
return start, step

0 commit comments

Comments
 (0)