Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
P
pymc3
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
0
Merge Requests
0
Requirements
Requirements
List
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issue
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ynic-debian
pymc3
Commits
0ae72c57
Commit
0ae72c57
authored
Oct 11, 2019
by
Robert P. Goldman
Committed by
Robert P. Goldman
Mar 10, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge from master.
parent
b8a67fea
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
111 additions
and
253 deletions
+111
-253
.pycheckers
.pycheckers
+0
-2
pymc3/distributions/distribution.py
pymc3/distributions/distribution.py
+1
-1
pymc3/distributions/posterior_predictive.py
pymc3/distributions/posterior_predictive.py
+4
-4
pymc3/sampling.py
pymc3/sampling.py
+27
-28
pymc3/tests/test_data_container.py
pymc3/tests/test_data_container.py
+3
-4
pymc3/tests/test_distributions_random.py
pymc3/tests/test_distributions_random.py
+74
-8
pymc3/tests/test_distributions_timeseries.py
pymc3/tests/test_distributions_timeseries.py
+2
-0
pymc3/tests/test_modelcontext.py-base
pymc3/tests/test_modelcontext.py-base
+0
-44
pymc3/tests/test_modelcontext.py-ours
pymc3/tests/test_modelcontext.py-ours
+0
-82
pymc3/tests/test_modelcontext.py-theirs
pymc3/tests/test_modelcontext.py-theirs
+0
-78
pymc3/tests/test_posterior_predictive.py
pymc3/tests/test_posterior_predictive.py
+0
-1
requirements-dev.txt
requirements-dev.txt
+0
-1
No files found.
.pycheckers
deleted
100644 → 0
View file @
b8a67fea
[DEFAULT]
pylint_rcfile = .pylintrc
\ No newline at end of file
pymc3/distributions/distribution.py
View file @
0ae72c57
...
...
@@ -538,7 +538,7 @@ def draw_values(params, point=None, size=None):
# The following check intercepts and redirects calls to
# draw_values in the context of sample_posterior_predictive
ppc_sampler
=
vectorized_ppc
.
get
(
None
)
if
ppc_sampler
:
if
ppc_sampler
is
not
None
:
# this is being done inside new, vectorized sample_posterior_predictive
return
ppc_sampler
(
params
,
trace
=
point
,
samples
=
size
)
...
...
pymc3/distributions/posterior_predictive.py
View file @
0ae72c57
...
...
@@ -310,6 +310,7 @@ class _PosteriorPredictiveSampler(AbstractContextManager):
givens
=
{
p
.
name
:
(
p
,
v
)
for
(
p
,
samples
),
v
in
drawn
.
items
()
if
getattr
(
p
,
'name'
,
None
)
is
not
None
}
stack
=
list
(
self
.
leaf_nodes
.
values
())
# A queue would be more appropriate
while
stack
:
next_
=
stack
.
pop
(
0
)
if
(
next_
,
samples
)
in
drawn
:
...
...
@@ -364,6 +365,7 @@ class _PosteriorPredictiveSampler(AbstractContextManager):
# The remaining params that must be drawn are all hashable
to_eval
=
set
()
# type: Set[int]
missing_inputs
=
set
([
j
for
j
,
p
in
self
.
symbolic_params
])
# type: Set[int]
while
to_eval
or
missing_inputs
:
if
to_eval
==
missing_inputs
:
raise
ValueError
(
'Cannot resolve inputs for {}'
.
format
([
str
(
trace
.
varnames
[
j
])
for
j
in
to_eval
]))
...
...
@@ -479,8 +481,6 @@ class _PosteriorPredictiveSampler(AbstractContextManager):
samples
=
self
.
samples
def
random_sample
(
meth
:
Callable
[...,
np
.
ndarray
],
param
,
point
:
_TraceDict
,
size
:
int
,
shape
:
Tuple
[
int
,
...])
->
np
.
ndarray
:
# if hasattr(param, 'name') and param.name == 'obs':
# import pdb; pdb.set_trace()
val
=
meth
(
point
=
point
,
size
=
size
)
if
size
==
1
:
val
=
np
.
expand_dims
(
val
,
axis
=
0
)
...
...
@@ -575,8 +575,8 @@ class _PosteriorPredictiveSampler(AbstractContextManager):
if
not
input_vars
:
assert
input_vals
==
[]
# AFAICT if there are now vars, there can't be vals
output
=
func
(
*
input_vals
)
if
hasattr
(
output
,
'shape'
,
None
):
val
=
np
.
ndarray
(
output
*
samples
)
if
hasattr
(
output
,
'shape'
):
val
=
np
.
repeat
(
np
.
expand_dims
(
output
,
0
),
samples
,
axis
=
0
)
else
:
val
=
np
.
full
(
samples
,
output
)
...
...
pymc3/sampling.py
View file @
0ae72c57
...
...
@@ -1475,52 +1475,54 @@ class _DefaultTrace:
self
.
trace_dict
[
k
][
idx
,
:]
=
v
def
sample_posterior_predictive
(
trace
,
samples
:
Optional
[
int
]
=
None
,
model
:
Optional
[
Model
]
=
None
,
vars
:
Optional
[
TIterable
[
Tensor
]]
=
None
,
var_names
:
Optional
[
List
[
str
]]
=
None
,
size
:
Optional
[
int
]
=
None
,
keep_size
:
Optional
[
bool
]
=
False
,
random_seed
=
None
,
progressbar
:
bool
=
True
)
->
Dict
[
str
,
np
.
ndarray
]:
def
sample_posterior_predictive
(
trace
,
samples
:
Optional
[
int
]
=
None
,
model
:
Optional
[
Model
]
=
None
,
vars
:
Optional
[
TIterable
[
Tensor
]]
=
None
,
var_names
:
Optional
[
List
[
str
]]
=
None
,
size
:
Optional
[
int
]
=
None
,
keep_size
:
Optional
[
bool
]
=
False
,
random_seed
=
None
,
progressbar
:
bool
=
True
,
)
->
Dict
[
str
,
np
.
ndarray
]:
"""Generate posterior predictive samples from a model given a trace.
Parameters
----------
trace
: backend, list, or MultiTrace
trace: backend, list, or MultiTrace
Trace generated from MCMC sampling. Or a list containing dicts from
find_MAP() or points
samples
: int
samples: int
Number of posterior predictive samples to generate. Defaults to one posterior predictive
sample per posterior sample, that is, the number of draws times the number of chains. It
is not recommended to modify this value; when modified, some chains may not be represented
in the posterior predictive sample.
model
: Model (optional if in ``with`` context)
model: Model (optional if in ``with`` context)
Model used to generate ``trace``
vars
: iterable
vars: iterable
Variables for which to compute the posterior predictive samples.
Deprecated: please use ``var_names`` instead.
var_names
: Iterable[str]
var_names: Iterable[str]
Alternative way to specify vars to sample, to make this function orthogonal with
others.
size
: int
size: int
The number of random draws from the distribution specified by the parameters in each
sample of the trace. Not recommended unless more than ndraws times nchains posterior
predictive samples are needed.
keep_size
: bool, optional
keep_size: bool, optional
Force posterior predictive sample to have the same shape as posterior and sample stats
data: ``(nchains, ndraws, ...)``. Overrides samples and size parameters.
random_seed
: int
random_seed: int
Seed for the random number generator.
progressbar
: bool
progressbar: bool
Whether or not to display a progress bar in the command line. The bar shows the percentage
of completion, the sampling speed in samples per second (SPS), and the estimated remaining
time until completion ("expected time of arrival"; ETA).
Returns
-------
samples
: dict
samples: dict
Dictionary with the variable names as keys, and values numpy arrays containing
posterior predictive samples.
"""
...
...
@@ -1539,9 +1541,11 @@ def sample_posterior_predictive(trace,
samples
=
sum
(
len
(
v
)
for
v
in
trace
.
_straces
.
values
())
if
samples
<
len_trace
*
nchain
:
warnings
.
warn
(
"samples parameter is smaller than nchains times ndraws, some draws "
"and/or chains may not be represented in the returned posterior "
"predictive sample"
)
warnings
.
warn
(
"samples parameter is smaller than nchains times ndraws, some draws "
"and/or chains may not be represented in the returned posterior "
"predictive sample"
)
model
=
modelcontext
(
model
)
...
...
@@ -1561,9 +1565,8 @@ def sample_posterior_predictive(trace,
indices
=
np
.
arange
(
samples
)
if
progressbar
:
indices
=
tqdm
(
indices
,
total
=
samples
)
indices
=
progress_bar
(
indices
,
total
=
samples
,
display
=
progressbar
)
ppc_trace_t
=
_DefaultTrace
(
samples
)
try
:
...
...
@@ -1581,10 +1584,6 @@ def sample_posterior_predictive(trace,
except
KeyboardInterrupt
:
pass
finally
:
if
progressbar
:
indices
.
close
()
ppc_trace
=
ppc_trace_t
.
trace_dict
if
keep_size
:
for
k
,
ary
in
ppc_trace
.
items
():
...
...
pymc3/tests/test_data_container.py
View file @
0ae72c57
...
...
@@ -32,10 +32,10 @@ class TestData(SeededTest):
x_pred
=
np
.
linspace
(
-
3
,
3
,
200
,
dtype
=
'float32'
)
with
pm
.
Model
()
as
model
:
with
pm
.
Model
():
x_shared
=
pm
.
Data
(
'x_shared'
,
x
)
b
=
pm
.
Normal
(
'b'
,
0.
,
10.
)
obsvar
=
pm
.
Normal
(
'obs'
,
b
*
x_shared
,
np
.
sqrt
(
1e-2
),
observed
=
y
)
pm
.
Normal
(
'obs'
,
b
*
x_shared
,
np
.
sqrt
(
1e-2
),
observed
=
y
)
prior_trace0
=
pm
.
sample_prior_predictive
(
1000
)
trace
=
pm
.
sample
(
1000
,
init
=
None
,
tune
=
1000
,
chains
=
1
)
...
...
@@ -53,7 +53,7 @@ class TestData(SeededTest):
assert
pp_trace0
[
'obs'
].
shape
==
(
1000
,
100
)
assert
pp_trace01
[
'obs'
].
shape
==
(
1000
,
100
)
np
.
testing
.
assert_allclose
(
x
,
pp_trace0
[
'obs'
].
mean
(
axis
=
0
),
atol
=
1e-1
)
np
.
testing
.
assert_allclose
(
x
,
pp_trace01
[
'obs'
].
mean
(
axis
=
0
),
atol
=
1e-1
)
...
...
@@ -108,7 +108,6 @@ class TestData(SeededTest):
atol
=
1e-1
)
np
.
testing
.
assert_allclose
(
new_y
,
pp_tracef
[
'obs'
].
mean
(
axis
=
0
),
atol
=
1e-1
)
def
test_creation_of_data_outside_model_context
(
self
):
with
pytest
.
raises
((
IndexError
,
TypeError
))
as
error
:
...
...
pymc3/tests/test_distributions_random.py
View file @
0ae72c57
...
...
@@ -948,14 +948,62 @@ def test_mixture_random_shape():
assert
ppc
[
'like2'
].
shape
==
(
200
,
20
)
assert
ppc
[
'like3'
].
shape
==
(
200
,
20
)
@
pytest
.
mark
.
xfail
def
test_mixture_random_shape_fast
():
# test the shape broadcasting in mixture random
y
=
np
.
concatenate
([
nr
.
poisson
(
5
,
size
=
10
),
nr
.
poisson
(
9
,
size
=
10
)])
with
pm
.
Model
()
as
m
:
comp0
=
pm
.
Poisson
.
dist
(
mu
=
np
.
ones
(
2
))
w0
=
pm
.
Dirichlet
(
'w0'
,
a
=
np
.
ones
(
2
))
like0
=
pm
.
Mixture
(
'like0'
,
w
=
w0
,
comp_dists
=
comp0
,
observed
=
y
)
comp1
=
pm
.
Poisson
.
dist
(
mu
=
np
.
ones
((
20
,
2
)),
shape
=
(
20
,
2
))
w1
=
pm
.
Dirichlet
(
'w1'
,
a
=
np
.
ones
(
2
))
like1
=
pm
.
Mixture
(
'like1'
,
w
=
w1
,
comp_dists
=
comp1
,
observed
=
y
)
comp2
=
pm
.
Poisson
.
dist
(
mu
=
np
.
ones
(
2
))
w2
=
pm
.
Dirichlet
(
'w2'
,
a
=
np
.
ones
(
2
),
shape
=
(
20
,
2
))
like2
=
pm
.
Mixture
(
'like2'
,
w
=
w2
,
comp_dists
=
comp2
,
observed
=
y
)
comp3
=
pm
.
Poisson
.
dist
(
mu
=
np
.
ones
(
2
),
shape
=
(
20
,
2
))
w3
=
pm
.
Dirichlet
(
'w3'
,
a
=
np
.
ones
(
2
),
shape
=
(
20
,
2
))
like3
=
pm
.
Mixture
(
'like3'
,
w
=
w3
,
comp_dists
=
comp3
,
observed
=
y
)
rand0
,
rand1
,
rand2
,
rand3
=
draw_values
([
like0
,
like1
,
like2
,
like3
],
point
=
m
.
test_point
,
size
=
100
)
assert
rand0
.
shape
==
(
100
,
20
)
assert
rand1
.
shape
==
(
100
,
20
)
assert
rand2
.
shape
==
(
100
,
20
)
assert
rand3
.
shape
==
(
100
,
20
)
# I *think* that the mixture means that this is not going to work,
# but I could be wrong. [2019/08/22:rpg]
#
with m:
#
ppc = pm.fast_sample_posterior_predictive([m.test_point], samples=200)
#
assert ppc['like0'].shape == (200, 20)
#
assert ppc['like1'].shape == (200, 20)
#
assert ppc['like2'].shape == (200, 20)
#
assert ppc['like3'].shape == (200, 20)
with
m
:
ppc
=
pm
.
fast_sample_posterior_predictive
([
m
.
test_point
],
samples
=
200
)
assert
ppc
[
'like0'
].
shape
==
(
200
,
20
)
assert
ppc
[
'like1'
].
shape
==
(
200
,
20
)
assert
ppc
[
'like2'
].
shape
==
(
200
,
20
)
assert
ppc
[
'like3'
].
shape
==
(
200
,
20
)
...
...
@@ -1050,8 +1098,26 @@ class TestDensityDist():
ppc
=
pm
.
sample_posterior_predictive
(
trace
,
samples
=
samples
,
model
=
model
,
size
=
size
)
assert
ppc
[
'density_dist'
].
shape
==
(
samples
,
size
)
+
obs
.
distribution
.
shape
# ppc = pm.fast_sample_posterior_predictive(trace, samples=samples, model=model, size=size)
# assert ppc['density_dist'].shape == (samples, size) + obs.distribution.shape
@
pytest
.
mark
.
xfail
def
test_density_dist_with_random_sampleable_handcrafted_success_fast
(
self
):
with
pm
.
Model
()
as
model
:
mu
=
pm
.
Normal
(
'mu'
,
0
,
1
)
normal_dist
=
pm
.
Normal
.
dist
(
mu
,
1
)
rvs
=
pm
.
Normal
.
dist
(
mu
,
1
,
shape
=
100
).
random
obs
=
pm
.
DensityDist
(
'density_dist'
,
normal_dist
.
logp
,
observed
=
np
.
random
.
randn
(
100
),
random
=
rvs
,
wrap_random_with_dist_shape
=
False
)
trace
=
pm
.
sample
(
100
)
samples
=
500
size
=
100
ppc
=
pm
.
fast_sample_posterior_predictive
(
trace
,
samples
=
samples
,
model
=
model
,
size
=
size
)
assert
ppc
[
'density_dist'
].
shape
==
(
samples
,
size
)
+
obs
.
distribution
.
shape
def
test_density_dist_without_random_not_sampleable
(
self
):
...
...
pymc3/tests/test_distributions_timeseries.py
View file @
0ae72c57
...
...
@@ -18,6 +18,8 @@ from ..distributions.timeseries import EulerMaruyama, AR1, AR, GARCH11
from
..sampling
import
sample
,
sample_posterior_predictive
,
fast_sample_posterior_predictive
from
..theanof
import
floatX
import
numpy
as
np
import
pytest
from
.helpers
import
select_by_precision
pytestmark
=
pytest
.
mark
.
usefixtures
(
'seeded_test'
)
...
...
pymc3/tests/test_modelcontext.py-base
deleted
100644 → 0
View file @
b8a67fea
import threading
from pymc3 import Model, Normal
class TestModelContext:
def test_thread_safety(self):
""" Regression test for issue #1552: Thread safety of model context manager
This test creates two threads that attempt to construct two
unrelated models at the same time.
For repeatable testing, the two threads are syncronised such
that thread A enters the context manager first, then B,
then A attempts to declare a variable while B is still in the context manager.
"""
aInCtxt,bInCtxt,aDone = [threading.Event() for _ in range(3)]
modelA = Model()
modelB = Model()
def make_model_a():
with modelA:
aInCtxt.set()
bInCtxt.wait()
Normal('a',0,1)
aDone.set()
def make_model_b():
aInCtxt.wait()
with modelB:
bInCtxt.set()
aDone.wait()
Normal('b', 0, 1)
threadA = threading.Thread(target=make_model_a)
threadB = threading.Thread(target=make_model_b)
threadA.start()
threadB.start()
threadA.join()
threadB.join()
# now let's see which model got which variable
# previous to #1555, the variables would be swapped:
# - B enters it's model context after A, but before a is declared -> a goes into B
# - A leaves it's model context before B attempts to declare b. A's context manager
# takes B from the stack, such that b ends up in model A
assert (
list(modelA.named_vars),
list(modelB.named_vars),
) == (['a'],['b'])
pymc3/tests/test_modelcontext.py-ours
deleted
100644 → 0
View file @
b8a67fea
import threading
from pytest import raises
from pymc3 import Model, Normal
from pymc3.distributions.distribution import _DrawValuesContext, _DrawValuesContextBlocker
from pymc3.model import modelcontext
class TestModelContext:
def test_thread_safety(self):
""" Regression test for issue #1552: Thread safety of model context manager
This test creates two threads that attempt to construct two
unrelated models at the same time.
For repeatable testing, the two threads are syncronised such
that thread A enters the context manager first, then B,
then A attempts to declare a variable while B is still in the context manager.
"""
aInCtxt,bInCtxt,aDone = [threading.Event() for _ in range(3)]
modelA = Model()
modelB = Model()
def make_model_a():
with modelA:
aInCtxt.set()
bInCtxt.wait()
Normal('a',0,1)
aDone.set()
def make_model_b():
aInCtxt.wait()
with modelB:
bInCtxt.set()
aDone.wait()
Normal('b', 0, 1)
threadA = threading.Thread(target=make_model_a)
threadB = threading.Thread(target=make_model_b)
threadA.start()
threadB.start()
threadA.join()
threadB.join()
# now let's see which model got which variable
# previous to #1555, the variables would be swapped:
# - B enters it's model context after A, but before a is declared -> a goes into B
# - A leaves it's model context before B attempts to declare b. A's context manager
# takes B from the stack, such that b ends up in model A
assert (
list(modelA.named_vars),
list(modelB.named_vars),
) == (['a'],['b'])
def test_mixed_contexts():
modelA = Model()
modelB = Model()
with raises((ValueError, TypeError)):
modelcontext(None)
with modelA:
with modelB:
assert Model.get_context() == modelB
assert modelcontext(None) == modelB
dvc = _DrawValuesContext()
with dvc:
assert Model.get_context() == modelB
assert modelcontext(None) == modelB
assert _DrawValuesContext.get_context() == dvc
dvcb = _DrawValuesContextBlocker()
with dvcb:
assert _DrawValuesContext.get_context() == dvcb
assert _DrawValuesContextBlocker.get_context() == dvcb
assert _DrawValuesContext.get_context() == dvc
assert _DrawValuesContextBlocker.get_context() is dvc
assert Model.get_context() == modelB
assert modelcontext(None) == modelB
assert _DrawValuesContext.get_context(error_if_none=False) is None
with raises(TypeError):
_DrawValuesContext.get_context()
assert Model.get_context() == modelB
assert modelcontext(None) == modelB
assert Model.get_context() == modelA
assert modelcontext(None) == modelA
assert Model.get_context(error_if_none=False) is None
with raises(TypeError):
Model.get_context(error_if_none=True)
with raises((ValueError, TypeError)):
modelcontext(None)
pymc3/tests/test_modelcontext.py-theirs
deleted
100644 → 0
View file @
b8a67fea
import threading
from pytest import raises
from pymc3 import Model, Normal
from pymc3.distributions.distribution import _DrawValuesContext, _DrawValuesContextBlocker
from pymc3.model import modelcontext
class TestModelContext:
def test_thread_safety(self):
""" Regression test for issue #1552: Thread safety of model context manager
This test creates two threads that attempt to construct two
unrelated models at the same time.
For repeatable testing, the two threads are syncronised such
that thread A enters the context manager first, then B,
then A attempts to declare a variable while B is still in the context manager.
"""
aInCtxt,bInCtxt,aDone = [threading.Event() for _ in range(3)]
modelA = Model()
modelB = Model()
def make_model_a():
with modelA:
aInCtxt.set()
bInCtxt.wait()
Normal('a',0,1)
aDone.set()
def make_model_b():
aInCtxt.wait()
with modelB:
bInCtxt.set()
aDone.wait()
Normal('b', 0, 1)
threadA = threading.Thread(target=make_model_a)
threadB = threading.Thread(target=make_model_b)
threadA.start()
threadB.start()
threadA.join()
threadB.join()
# now let's see which model got which variable
# previous to #1555, the variables would be swapped:
# - B enters it's model context after A, but before a is declared -> a goes into B
# - A leaves it's model context before B attempts to declare b. A's context manager
# takes B from the stack, such that b ends up in model A
assert (
list(modelA.named_vars),
list(modelB.named_vars),
) == (['a'],['b'])
def test_mixed_contexts():
modelA = Model()
modelB = Model()
with raises((ValueError, TypeError)):
modelcontext(None)
with modelA:
with modelB:
assert Model.get_context() == modelB
assert modelcontext(None) == modelB
dvc = _DrawValuesContext()
with dvc:
assert Model.get_context() == modelB
assert modelcontext(None) == modelB
assert _DrawValuesContext.get_context() == dvc
dvcb = _DrawValuesContextBlocker()
with dvcb:
assert _DrawValuesContext.get_context() == dvcb
assert _DrawValuesContextBlocker.get_context() == dvcb
assert _DrawValuesContext.get_context() == dvc
assert _DrawValuesContextBlocker.get_context() is None
assert Model.get_context() == modelB
assert modelcontext(None) == modelB
assert _DrawValuesContext.get_context() is None
assert Model.get_context() == modelB
assert modelcontext(None) == modelB
assert Model.get_context() == modelA
assert modelcontext(None) == modelA
assert Model.get_context() is None
with raises((ValueError, TypeError)):
modelcontext(None)
pymc3/tests/test_posterior_predictive.py
View file @
0ae72c57
import
pymc3
as
pm
import
pytest
from
pymc3.distributions.posterior_predictive
import
_TraceDict
import
numpy
as
np
...
...
requirements-dev.txt
View file @
0ae72c57
...
...
@@ -16,4 +16,3 @@ recommonmark>=0.4.0
seaborn>=0.8.1
sphinx-autobuild==0.7.1
sphinx>=1.5.5
typing-extensions>=3.7.4
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment