From 7119756de8d5a7d8131c191e87e5b176244a1420 Mon Sep 17 00:00:00 2001 From: VincentBt Date: Tue, 4 Feb 2020 18:43:33 +0100 Subject: [PATCH 01/10] numpyro - Add more data to InferenceData objects --- arviz/data/io_numpyro.py | 29 ++++++++++++------------ arviz/tests/test_data_numpyro.py | 38 +++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/arviz/data/io_numpyro.py b/arviz/data/io_numpyro.py index 5b0926f69f..04bd6816ec 100644 --- a/arviz/data/io_numpyro.py +++ b/arviz/data/io_numpyro.py @@ -103,24 +103,22 @@ def sample_stats_to_xarray(self): data[name] = value if stat == "num_steps": data["depth"] = np.log2(value).astype(int) + 1 - - # extract log_likelihood - dims = None - if self.observations is not None and len(self.observations) == 1: + return dict_to_dataset(data, library=self.numpyro, dims=None, coords=self.coords) + + @requires("posterior") + @requires("model") + def log_likelihood_to_xarray(self): + """Extract log likelihood from NumPyro posterior.""" + data = {} + if self.observations is not None: samples = self.posterior.get_samples(group_by_chain=False) - log_likelihood = self.numpyro.infer.log_likelihood( + log_likelihood_dict = self.numpyro.infer.log_likelihood( self.model, samples, *self._args, **self._kwargs ) - obs_name, log_likelihood = list(log_likelihood.items())[0] - if self.dims is not None: - coord_name = self.dims.get("log_likelihood", self.dims.get(obs_name)) - else: - coord_name = None - shape = (self.nchains, self.ndraws) + log_likelihood.shape[1:] - data["log_likelihood"] = np.reshape(log_likelihood.copy(), shape) - dims = {"log_likelihood": coord_name} - - return dict_to_dataset(data, library=self.numpyro, dims=dims, coords=self.coords) + for obs_name, log_like in log_likelihood_dict.items(): + shape = (self.nchains, self.ndraws) + log_like.shape[1:] + data[obs_name] = np.reshape(log_like.copy(), shape) + return dict_to_dataset(data, library=self.numpyro, dims=self.dims, coords=self.coords) @requires("posterior_predictive") def posterior_predictive_to_xarray(self): @@ -197,6 +195,7 @@ def to_inference_data(self): **{ "posterior": self.posterior_to_xarray(), "sample_stats": self.sample_stats_to_xarray(), + "log_likelihood": self.log_likelihood_to_xarray(), "posterior_predictive": self.posterior_predictive_to_xarray(), **self.priors_to_xarray(), "observed_data": self.observed_data_to_xarray(), diff --git a/arviz/tests/test_data_numpyro.py b/arviz/tests/test_data_numpyro.py index 86a227cee5..c411103da9 100644 --- a/arviz/tests/test_data_numpyro.py +++ b/arviz/tests/test_data_numpyro.py @@ -3,6 +3,7 @@ import pytest from jax.random import PRNGKey from numpyro.infer import Predictive +import jax.numpy from ..data.io_numpyro import from_numpyro from .helpers import ( # pylint: disable=unused-import @@ -25,10 +26,10 @@ class Data: def get_inference_data(self, data, eight_schools_params): posterior_samples = data.obj.get_samples() model = data.obj.sampler.model - posterior_predictive = Predictive(model, posterior_samples).get_samples( + posterior_predictive = Predictive(model, posterior_samples).__call__( PRNGKey(1), eight_schools_params["J"], eight_schools_params["sigma"] ) - prior = Predictive(model, num_samples=500).get_samples( + prior = Predictive(model, num_samples=500).__call__( PRNGKey(2), eight_schools_params["J"], eight_schools_params["sigma"] ) return from_numpyro( @@ -43,7 +44,8 @@ def test_inference_data(self, data, eight_schools_params): inference_data = self.get_inference_data(data, eight_schools_params) test_dict = { "posterior": ["mu", "tau", "eta"], - "sample_stats": ["diverging", "tree_size", "depth", "log_likelihood"], + "sample_stats": ["diverging", "tree_size", "depth"], + "log_likelihood": ["obs"], "posterior_predictive": ["obs"], "prior": ["mu", "tau", "eta"], "prior_predictive": ["obs"], @@ -51,3 +53,33 @@ def test_inference_data(self, data, eight_schools_params): } fails = check_multiple_attrs(test_dict, inference_data) assert not fails + + def test_multiple_observed_rv(self): + import numpyro + import numpyro.distributions as dist + from numpyro.infer import MCMC, NUTS + + y1 = np.random.randn(10) + y2 = np.random.randn(100) + def model_example_multiple_obs(y1=None, y2=None): + x = numpyro.sample('x', dist.Normal(1, 3)) + numpyro.sample('y1', dist.Normal(x, 1), obs=y1) + numpyro.sample('y2', dist.Normal(x, 1), obs=y2) + nuts_kernel = NUTS(model_example_multiple_obs) + mcmc = MCMC(nuts_kernel, num_warmup=20, num_samples=20) + mcmc.run(PRNGKey(0), y1=y1, y2=y2) + inference_data = from_numpyro(mcmc) + test_dict = { + "posterior": ["x"], + "sample_stats": ["diverging"], + "log_likelihood": ["y1", "y2"], + "observed_data": ["y1", "y2"], + } + fails = check_multiple_attrs(test_dict, inference_data) + waic_results = az.stats.waic(inference_data) + print(waic_results) + print(waic_results.keys()) + print(waic_results.waic, waic_results.waic_se) + assert not fails + assert not hasattr(inference_data.sample_stats, "log_likelihood") + \ No newline at end of file From c49262d9f1ed755d14bfdc3cdbc52a73dbfe6e90 Mon Sep 17 00:00:00 2001 From: VincentBt Date: Tue, 4 Feb 2020 18:46:20 +0100 Subject: [PATCH 02/10] resolves pyro deprecation warnings --- arviz/tests/test_data_pyro.py | 198 +++++++++++++++++----------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/arviz/tests/test_data_pyro.py b/arviz/tests/test_data_pyro.py index 523315f4bd..7d43ea16c5 100644 --- a/arviz/tests/test_data_pyro.py +++ b/arviz/tests/test_data_pyro.py @@ -1,99 +1,99 @@ -# pylint: disable=no-member, invalid-name, redefined-outer-name -import numpy as np -import packaging -import pytest -import torch -import pyro -from pyro.infer import Predictive - -from ..data.io_pyro import from_pyro -from .helpers import ( # pylint: disable=unused-import - chains, - check_multiple_attrs, - draws, - eight_schools_params, - load_cached_models, -) - - -class TestDataPyro: - @pytest.fixture(scope="class") - def data(self, eight_schools_params, draws, chains): - class Data: - obj = load_cached_models(eight_schools_params, draws, chains, "pyro")["pyro"] - - return Data - - def get_inference_data(self, data, eight_schools_params): - posterior_samples = data.obj.get_samples() - model = data.obj.kernel.model - posterior_predictive = Predictive(model, posterior_samples).get_samples( - eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() - ) - prior = Predictive(model, num_samples=500).get_samples( - eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() - ) - return from_pyro( - posterior=data.obj, - prior=prior, - posterior_predictive=posterior_predictive, - coords={"school": np.arange(eight_schools_params["J"])}, - dims={"theta": ["school"], "eta": ["school"]}, - ) - - def test_inference_data(self, data, eight_schools_params): - inference_data = self.get_inference_data(data, eight_schools_params) - test_dict = { - "posterior": ["mu", "tau", "eta"], - "sample_stats": ["diverging"], - "posterior_predictive": ["obs"], - "prior": ["mu", "tau", "eta"], - "prior_predictive": ["obs"], - } - fails = check_multiple_attrs(test_dict, inference_data) - assert not fails - - @pytest.mark.skipif( - packaging.version.parse(pyro.__version__) < packaging.version.parse("1.0.0"), - reason="requires pyro 1.0.0 or higher", - ) - def test_inference_data_has_log_likelihood_and_observed_data(self, data): - idata = from_pyro(data.obj) - test_dict = {"sample_stats": ["log_likelihood"], "observed_data": ["obs"]} - fails = check_multiple_attrs(test_dict, idata) - assert not fails - - def test_inference_data_no_posterior(self, data, eight_schools_params): - posterior_samples = data.obj.get_samples() - model = data.obj.kernel.model - posterior_predictive = Predictive(model, posterior_samples).get_samples( - eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() - ) - prior = Predictive(model, num_samples=500).get_samples( - eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() - ) - idata = from_pyro( - prior=prior, - posterior_predictive=posterior_predictive, - coords={"school": np.arange(eight_schools_params["J"])}, - dims={"theta": ["school"], "eta": ["school"]}, - ) - test_dict = {"posterior_predictive": ["obs"], "prior": ["mu", "tau", "eta", "obs"]} - fails = check_multiple_attrs(test_dict, idata) - assert not fails - - def test_inference_data_only_posterior(self, data): - idata = from_pyro(data.obj) - test_dict = {"posterior": ["mu", "tau", "eta"], "sample_stats": ["diverging"]} - fails = check_multiple_attrs(test_dict, idata) - assert not fails - - @pytest.mark.skipif( - packaging.version.parse(pyro.__version__) < packaging.version.parse("1.0.0"), - reason="requires pyro 1.0.0 or higher", - ) - def test_inference_data_only_posterior_has_log_likelihood(self, data): - idata = from_pyro(data.obj) - test_dict = {"sample_stats": ["log_likelihood"]} - fails = check_multiple_attrs(test_dict, idata) - assert not fails +# pylint: disable=no-member, invalid-name, redefined-outer-name +import numpy as np +import packaging +import pytest +import torch +import pyro +from pyro.infer import Predictive + +from ..data.io_pyro import from_pyro +from .helpers import ( # pylint: disable=unused-import + chains, + check_multiple_attrs, + draws, + eight_schools_params, + load_cached_models, +) + + +class TestDataPyro: + @pytest.fixture(scope="class") + def data(self, eight_schools_params, draws, chains): + class Data: + obj = load_cached_models(eight_schools_params, draws, chains, "pyro")["pyro"] + + return Data + + def get_inference_data(self, data, eight_schools_params): + posterior_samples = data.obj.get_samples() + model = data.obj.kernel.model + posterior_predictive = Predictive(model, posterior_samples).forward( + eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() + ) + prior = Predictive(model, num_samples=500).forward( + eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() + ) + return from_pyro( + posterior=data.obj, + prior=prior, + posterior_predictive=posterior_predictive, + coords={"school": np.arange(eight_schools_params["J"])}, + dims={"theta": ["school"], "eta": ["school"]}, + ) + + def test_inference_data(self, data, eight_schools_params): + inference_data = self.get_inference_data(data, eight_schools_params) + test_dict = { + "posterior": ["mu", "tau", "eta"], + "sample_stats": ["diverging"], + "posterior_predictive": ["obs"], + "prior": ["mu", "tau", "eta"], + "prior_predictive": ["obs"], + } + fails = check_multiple_attrs(test_dict, inference_data) + assert not fails + + @pytest.mark.skipif( + packaging.version.parse(pyro.__version__) < packaging.version.parse("1.0.0"), + reason="requires pyro 1.0.0 or higher", + ) + def test_inference_data_has_log_likelihood_and_observed_data(self, data): + idata = from_pyro(data.obj) + test_dict = {"sample_stats": ["log_likelihood"], "observed_data": ["obs"]} + fails = check_multiple_attrs(test_dict, idata) + assert not fails + + def test_inference_data_no_posterior(self, data, eight_schools_params): + posterior_samples = data.obj.get_samples() + model = data.obj.kernel.model + posterior_predictive = Predictive(model, posterior_samples).forward( + eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() + ) + prior = Predictive(model, num_samples=500).forward( + eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() + ) + idata = from_pyro( + prior=prior, + posterior_predictive=posterior_predictive, + coords={"school": np.arange(eight_schools_params["J"])}, + dims={"theta": ["school"], "eta": ["school"]}, + ) + test_dict = {"posterior_predictive": ["obs"], "prior": ["mu", "tau", "eta", "obs"]} + fails = check_multiple_attrs(test_dict, idata) + assert not fails + + def test_inference_data_only_posterior(self, data): + idata = from_pyro(data.obj) + test_dict = {"posterior": ["mu", "tau", "eta"], "sample_stats": ["diverging"]} + fails = check_multiple_attrs(test_dict, idata) + assert not fails + + @pytest.mark.skipif( + packaging.version.parse(pyro.__version__) < packaging.version.parse("1.0.0"), + reason="requires pyro 1.0.0 or higher", + ) + def test_inference_data_only_posterior_has_log_likelihood(self, data): + idata = from_pyro(data.obj) + test_dict = {"sample_stats": ["log_likelihood"]} + fails = check_multiple_attrs(test_dict, idata) + assert not fails From 549f201ac997b5d90a6f33dc9633187f6cdaa7ee Mon Sep 17 00:00:00 2001 From: VincentBt Date: Tue, 4 Feb 2020 20:07:47 +0100 Subject: [PATCH 03/10] pyro - Add more data to InferenceData objects --- arviz/data/io_pyro.py | 26 ++++++++++++++------------ arviz/tests/test_data_numpyro.py | 12 ++++++------ arviz/tests/test_data_pyro.py | 29 +++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/arviz/data/io_pyro.py b/arviz/data/io_pyro.py index ed0f3e0747..54273ec8fc 100644 --- a/arviz/data/io_pyro.py +++ b/arviz/data/io_pyro.py @@ -85,24 +85,25 @@ def sample_stats_to_xarray(self): for i, k in enumerate(sorted(divergences)): diverging[i, divergences[k]] = True data = {"diverging": diverging} + return dict_to_dataset(data, library=self.pyro, coords=self.coords, dims=None) - # extract log_likelihood + @requires("posterior") + @requires("model") + def log_likelihood_to_xarray(self): + """Extract log likelihood from Pyro posterior.""" + data = {} dims = None - if self.observations is not None and len(self.observations) == 1: + if self.observations is not None: try: - obs_name = list(self.observations.keys())[0] samples = self.posterior.get_samples(group_by_chain=False) predictive = self.pyro.infer.Predictive(self.model, samples) vectorized_trace = predictive.get_vectorized_trace(*self._args, **self._kwargs) - obs_site = vectorized_trace.nodes[obs_name] - log_likelihood = obs_site["fn"].log_prob(obs_site["value"]).detach().cpu().numpy() - if self.dims is not None: - coord_name = self.dims.get("log_likelihood", self.dims.get(obs_name)) - else: - coord_name = None - shape = (self.nchains, self.ndraws) + log_likelihood.shape[1:] - data["log_likelihood"] = np.reshape(log_likelihood, shape) - dims = {"log_likelihood": coord_name} + data = {} + for obs_name in self.observations.keys(): + obs_site = vectorized_trace.nodes[obs_name] + log_likelihood = obs_site["fn"].log_prob(obs_site["value"]).detach().cpu().numpy() + shape = (self.nchains, self.ndraws) + log_likelihood.shape[1:] + data[obs_name] = np.reshape(log_likelihood.copy(), shape) except: # pylint: disable=bare-except # cannot get vectorized trace pass @@ -179,6 +180,7 @@ def to_inference_data(self): **{ "posterior": self.posterior_to_xarray(), "sample_stats": self.sample_stats_to_xarray(), + "log_likelihood": self.log_likelihood_to_xarray(), "posterior_predictive": self.posterior_predictive_to_xarray(), **self.priors_to_xarray(), "observed_data": self.observed_data_to_xarray(), diff --git a/arviz/tests/test_data_numpyro.py b/arviz/tests/test_data_numpyro.py index c411103da9..17f659c134 100644 --- a/arviz/tests/test_data_numpyro.py +++ b/arviz/tests/test_data_numpyro.py @@ -58,7 +58,6 @@ def test_multiple_observed_rv(self): import numpyro import numpyro.distributions as dist from numpyro.infer import MCMC, NUTS - y1 = np.random.randn(10) y2 = np.random.randn(100) def model_example_multiple_obs(y1=None, y2=None): @@ -66,7 +65,7 @@ def model_example_multiple_obs(y1=None, y2=None): numpyro.sample('y1', dist.Normal(x, 1), obs=y1) numpyro.sample('y2', dist.Normal(x, 1), obs=y2) nuts_kernel = NUTS(model_example_multiple_obs) - mcmc = MCMC(nuts_kernel, num_warmup=20, num_samples=20) + mcmc = MCMC(nuts_kernel, num_samples=10, num_warmup=2) mcmc.run(PRNGKey(0), y1=y1, y2=y2) inference_data = from_numpyro(mcmc) test_dict = { @@ -76,10 +75,11 @@ def model_example_multiple_obs(y1=None, y2=None): "observed_data": ["y1", "y2"], } fails = check_multiple_attrs(test_dict, inference_data) - waic_results = az.stats.waic(inference_data) - print(waic_results) - print(waic_results.keys()) - print(waic_results.waic, waic_results.waic_se) +# from ..stats import waic +# waic_results = waic(inference_data) +# print(waic_results) +# print(waic_results.keys()) +# print(waic_results.waic, waic_results.waic_se) assert not fails assert not hasattr(inference_data.sample_stats, "log_likelihood") \ No newline at end of file diff --git a/arviz/tests/test_data_pyro.py b/arviz/tests/test_data_pyro.py index 7d43ea16c5..0dbe6b1548 100644 --- a/arviz/tests/test_data_pyro.py +++ b/arviz/tests/test_data_pyro.py @@ -59,7 +59,7 @@ def test_inference_data(self, data, eight_schools_params): ) def test_inference_data_has_log_likelihood_and_observed_data(self, data): idata = from_pyro(data.obj) - test_dict = {"sample_stats": ["log_likelihood"], "observed_data": ["obs"]} + test_dict = {"log_likelihood": ["obs"], "observed_data": ["obs"]} fails = check_multiple_attrs(test_dict, idata) assert not fails @@ -94,6 +94,31 @@ def test_inference_data_only_posterior(self, data): ) def test_inference_data_only_posterior_has_log_likelihood(self, data): idata = from_pyro(data.obj) - test_dict = {"sample_stats": ["log_likelihood"]} + test_dict = {"log_likelihood": ["obs"]} fails = check_multiple_attrs(test_dict, idata) assert not fails + + def test_multiple_observed_rv(self): + import pyro + import pyro.distributions as dist + from pyro.infer import MCMC, NUTS + import torch + y1 = torch.randn(10) + y2 = torch.randn(10) #does not work with 100 instead of 10 + def model_example_multiple_obs(y1=None, y2=None): + x = pyro.sample('x', dist.Normal(1, 3)) + pyro.sample('y1', dist.Normal(x, 1), obs=y1) + pyro.sample('y2', dist.Normal(x, 1), obs=y2) + nuts_kernel = NUTS(model_example_multiple_obs) + mcmc = MCMC(nuts_kernel, num_samples=10) + mcmc.run(y1=y1, y2=y2) + inference_data = from_pyro(mcmc) + test_dict = { + "posterior": ["x"], + "sample_stats": ["diverging"], + "log_likelihood": ["y1", "y2"], + "observed_data": ["y1", "y2"], + } + fails = check_multiple_attrs(test_dict, inference_data) + assert not fails + assert not hasattr(inference_data.sample_stats, "log_likelihood") \ No newline at end of file From 023646b25f4228fb49df66e9e61b86f93bcfe1ad Mon Sep 17 00:00:00 2001 From: VincentBt Date: Tue, 4 Feb 2020 20:10:24 +0100 Subject: [PATCH 04/10] removing comment in pyro test --- arviz/tests/test_data_pyro.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arviz/tests/test_data_pyro.py b/arviz/tests/test_data_pyro.py index 0dbe6b1548..a870f53abd 100644 --- a/arviz/tests/test_data_pyro.py +++ b/arviz/tests/test_data_pyro.py @@ -104,7 +104,7 @@ def test_multiple_observed_rv(self): from pyro.infer import MCMC, NUTS import torch y1 = torch.randn(10) - y2 = torch.randn(10) #does not work with 100 instead of 10 + y2 = torch.randn(10) def model_example_multiple_obs(y1=None, y2=None): x = pyro.sample('x', dist.Normal(1, 3)) pyro.sample('y1', dist.Normal(x, 1), obs=y1) From 08db69325af175ed50d0d6e10d6d078cd8dd65cb Mon Sep 17 00:00:00 2001 From: VincentBt Date: Tue, 4 Feb 2020 23:25:29 +0100 Subject: [PATCH 05/10] resolves pylint failures --- arviz/data/io_numpyro.py | 2 +- arviz/data/io_pyro.py | 9 ++++----- arviz/tests/test_data_numpyro.py | 25 +++++++++++++------------ arviz/tests/test_data_pyro.py | 15 ++++++++------- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/arviz/data/io_numpyro.py b/arviz/data/io_numpyro.py index 04bd6816ec..fe64e765fd 100644 --- a/arviz/data/io_numpyro.py +++ b/arviz/data/io_numpyro.py @@ -104,7 +104,7 @@ def sample_stats_to_xarray(self): if stat == "num_steps": data["depth"] = np.log2(value).astype(int) + 1 return dict_to_dataset(data, library=self.numpyro, dims=None, coords=self.coords) - + @requires("posterior") @requires("model") def log_likelihood_to_xarray(self): diff --git a/arviz/data/io_pyro.py b/arviz/data/io_pyro.py index 54273ec8fc..5ebb74946a 100644 --- a/arviz/data/io_pyro.py +++ b/arviz/data/io_pyro.py @@ -91,7 +91,6 @@ def sample_stats_to_xarray(self): @requires("model") def log_likelihood_to_xarray(self): """Extract log likelihood from Pyro posterior.""" - data = {} dims = None if self.observations is not None: try: @@ -101,9 +100,9 @@ def log_likelihood_to_xarray(self): data = {} for obs_name in self.observations.keys(): obs_site = vectorized_trace.nodes[obs_name] - log_likelihood = obs_site["fn"].log_prob(obs_site["value"]).detach().cpu().numpy() - shape = (self.nchains, self.ndraws) + log_likelihood.shape[1:] - data[obs_name] = np.reshape(log_likelihood.copy(), shape) + log_like = obs_site["fn"].log_prob(obs_site["value"]).detach().cpu().numpy() + shape = (self.nchains, self.ndraws) + log_like.shape[1:] + data[obs_name] = np.reshape(log_like, shape) except: # pylint: disable=bare-except # cannot get vectorized trace pass @@ -123,7 +122,7 @@ def posterior_predictive_to_xarray(self): else: data[k] = utils.expand_dims(ary) _log.warning( - "posterior predictive shape not compatible with number of chains and draws. " + "posterior predictive shape not compatible with number of chains and draws." "This can mean that some draws or even whole chains are not represented." ) return dict_to_dataset(data, library=self.pyro, coords=self.coords, dims=self.dims) diff --git a/arviz/tests/test_data_numpyro.py b/arviz/tests/test_data_numpyro.py index 17f659c134..d36257947e 100644 --- a/arviz/tests/test_data_numpyro.py +++ b/arviz/tests/test_data_numpyro.py @@ -3,7 +3,6 @@ import pytest from jax.random import PRNGKey from numpyro.infer import Predictive -import jax.numpy from ..data.io_numpyro import from_numpyro from .helpers import ( # pylint: disable=unused-import @@ -26,10 +25,10 @@ class Data: def get_inference_data(self, data, eight_schools_params): posterior_samples = data.obj.get_samples() model = data.obj.sampler.model - posterior_predictive = Predictive(model, posterior_samples).__call__( + posterior_predictive = Predictive(model, posterior_samples)( PRNGKey(1), eight_schools_params["J"], eight_schools_params["sigma"] ) - prior = Predictive(model, num_samples=500).__call__( + prior = Predictive(model, num_samples=500)( PRNGKey(2), eight_schools_params["J"], eight_schools_params["sigma"] ) return from_numpyro( @@ -58,12 +57,15 @@ def test_multiple_observed_rv(self): import numpyro import numpyro.distributions as dist from numpyro.infer import MCMC, NUTS + y1 = np.random.randn(10) y2 = np.random.randn(100) + def model_example_multiple_obs(y1=None, y2=None): - x = numpyro.sample('x', dist.Normal(1, 3)) - numpyro.sample('y1', dist.Normal(x, 1), obs=y1) - numpyro.sample('y2', dist.Normal(x, 1), obs=y2) + x = numpyro.sample("x", dist.Normal(1, 3)) + numpyro.sample("y1", dist.Normal(x, 1), obs=y1) + numpyro.sample("y2", dist.Normal(x, 1), obs=y2) + nuts_kernel = NUTS(model_example_multiple_obs) mcmc = MCMC(nuts_kernel, num_samples=10, num_warmup=2) mcmc.run(PRNGKey(0), y1=y1, y2=y2) @@ -75,11 +77,10 @@ def model_example_multiple_obs(y1=None, y2=None): "observed_data": ["y1", "y2"], } fails = check_multiple_attrs(test_dict, inference_data) -# from ..stats import waic -# waic_results = waic(inference_data) -# print(waic_results) -# print(waic_results.keys()) -# print(waic_results.waic, waic_results.waic_se) + # from ..stats import waic + # waic_results = waic(inference_data) + # print(waic_results) + # print(waic_results.keys()) + # print(waic_results.waic, waic_results.waic_se) assert not fails assert not hasattr(inference_data.sample_stats, "log_likelihood") - \ No newline at end of file diff --git a/arviz/tests/test_data_pyro.py b/arviz/tests/test_data_pyro.py index a870f53abd..2ff574024f 100644 --- a/arviz/tests/test_data_pyro.py +++ b/arviz/tests/test_data_pyro.py @@ -38,7 +38,7 @@ def get_inference_data(self, data, eight_schools_params): prior=prior, posterior_predictive=posterior_predictive, coords={"school": np.arange(eight_schools_params["J"])}, - dims={"theta": ["school"], "eta": ["school"]}, + dims={"theta": ["school"], "eta": ["school"]} ) def test_inference_data(self, data, eight_schools_params): @@ -99,16 +99,17 @@ def test_inference_data_only_posterior_has_log_likelihood(self, data): assert not fails def test_multiple_observed_rv(self): - import pyro import pyro.distributions as dist from pyro.infer import MCMC, NUTS - import torch + y1 = torch.randn(10) y2 = torch.randn(10) + def model_example_multiple_obs(y1=None, y2=None): - x = pyro.sample('x', dist.Normal(1, 3)) - pyro.sample('y1', dist.Normal(x, 1), obs=y1) - pyro.sample('y2', dist.Normal(x, 1), obs=y2) + x = pyro.sample("x", dist.Normal(1, 3)) + pyro.sample("y1", dist.Normal(x, 1), obs=y1) + pyro.sample("y2", dist.Normal(x, 1), obs=y2) + nuts_kernel = NUTS(model_example_multiple_obs) mcmc = MCMC(nuts_kernel, num_samples=10) mcmc.run(y1=y1, y2=y2) @@ -121,4 +122,4 @@ def model_example_multiple_obs(y1=None, y2=None): } fails = check_multiple_attrs(test_dict, inference_data) assert not fails - assert not hasattr(inference_data.sample_stats, "log_likelihood") \ No newline at end of file + assert not hasattr(inference_data.sample_stats, "log_likelihood") From a4c6e7980203c4efc96697d5879248602c9bf5ee Mon Sep 17 00:00:00 2001 From: VincentBt Date: Wed, 5 Feb 2020 00:36:08 +0100 Subject: [PATCH 06/10] resolving additionnal failures (Predictive().forward does not exist) --- arviz/tests/test_data_pyro.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arviz/tests/test_data_pyro.py b/arviz/tests/test_data_pyro.py index 2ff574024f..d09d9b9fa9 100644 --- a/arviz/tests/test_data_pyro.py +++ b/arviz/tests/test_data_pyro.py @@ -27,10 +27,10 @@ class Data: def get_inference_data(self, data, eight_schools_params): posterior_samples = data.obj.get_samples() model = data.obj.kernel.model - posterior_predictive = Predictive(model, posterior_samples).forward( + posterior_predictive = Predictive(model, posterior_samples)( eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() ) - prior = Predictive(model, num_samples=500).forward( + prior = Predictive(model, num_samples=500)( eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() ) return from_pyro( @@ -38,7 +38,7 @@ def get_inference_data(self, data, eight_schools_params): prior=prior, posterior_predictive=posterior_predictive, coords={"school": np.arange(eight_schools_params["J"])}, - dims={"theta": ["school"], "eta": ["school"]} + dims={"theta": ["school"], "eta": ["school"]}, ) def test_inference_data(self, data, eight_schools_params): @@ -66,10 +66,10 @@ def test_inference_data_has_log_likelihood_and_observed_data(self, data): def test_inference_data_no_posterior(self, data, eight_schools_params): posterior_samples = data.obj.get_samples() model = data.obj.kernel.model - posterior_predictive = Predictive(model, posterior_samples).forward( + posterior_predictive = Predictive(model, posterior_samples)( eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() ) - prior = Predictive(model, num_samples=500).forward( + prior = Predictive(model, num_samples=500)( eight_schools_params["J"], torch.from_numpy(eight_schools_params["sigma"]).float() ) idata = from_pyro( From 0d1e3949140391d35b7c6ff0b2966bab98f96b10 Mon Sep 17 00:00:00 2001 From: VincentBt Date: Wed, 5 Feb 2020 10:26:17 +0100 Subject: [PATCH 07/10] updates pyro version requirements --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 39a8690558..6d8211fea9 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -8,7 +8,7 @@ nbsphinx numpydoc pydocstyle<5.0 pylint -pyro-ppl>=0.5.1 +pyro-ppl>=1.0.0 tensorflow tensorflow-probability pytest From 180a994509bdbcf4e90ed4bae7794b4cb0d5cd61 Mon Sep 17 00:00:00 2001 From: VincentBt Date: Wed, 5 Feb 2020 10:46:44 +0100 Subject: [PATCH 08/10] updates pyro version for travis (Predictive.forward does not exist) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index eff88ff0eb..e2a9570ac0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,9 +11,9 @@ matrix: - name: "Python 3.6 Unit Test" python: 3.6 env: PYTHON_VERSION=3.6 PYSTAN_VERSION=latest PYRO_VERSION=latest EMCEE_VERSION=latest COVERALLS_PARALLEL=true NAME="UNIT" - - name: "Python 3.6 Unit Test - PyStan=3 Pyro=0.5.1 Emcee=2 TF=1" + - name: "Python 3.6 Unit Test - PyStan=3 Pyro=1.0.0 Emcee=2 TF=1" python: 3.6 - env: PYTHON_VERSION=3.6 PYSTAN_VERSION=preview PYRO_VERSION=0.5.1 PYTORCH_VERSION=1.3.0 EMCEE_VERSION=2 TF_VERSION=1 COVERALLS_PARALLEL=true NAME="UNIT" + env: PYTHON_VERSION=3.6 PYSTAN_VERSION=preview PYRO_VERSION=1.0.0 PYTORCH_VERSION=1.3.0 EMCEE_VERSION=2 TF_VERSION=1 COVERALLS_PARALLEL=true NAME="UNIT" - name: "Python 3.5 Unit Test" python: 3.5 env: PYTHON_VERSION=3.5 PYSTAN_VERSION=latest PYRO_VERSION=latest EMCEE_VERSION=latest PYMC3_VERSION=3.8 COVERALLS_PARALLEL=true NAME="UNIT" From f2c1ea9f57bb581b3c6eae510cc7719aecc65998 Mon Sep 17 00:00:00 2001 From: VincentBt Date: Wed, 5 Feb 2020 12:32:05 +0100 Subject: [PATCH 09/10] modifies case vectorized trace cannot be obtained (pyro) --- arviz/data/io_pyro.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arviz/data/io_pyro.py b/arviz/data/io_pyro.py index 5ebb74946a..30cdcc0714 100644 --- a/arviz/data/io_pyro.py +++ b/arviz/data/io_pyro.py @@ -91,13 +91,13 @@ def sample_stats_to_xarray(self): @requires("model") def log_likelihood_to_xarray(self): """Extract log likelihood from Pyro posterior.""" + data = {} dims = None if self.observations is not None: try: samples = self.posterior.get_samples(group_by_chain=False) predictive = self.pyro.infer.Predictive(self.model, samples) vectorized_trace = predictive.get_vectorized_trace(*self._args, **self._kwargs) - data = {} for obs_name in self.observations.keys(): obs_site = vectorized_trace.nodes[obs_name] log_like = obs_site["fn"].log_prob(obs_site["value"]).detach().cpu().numpy() @@ -105,7 +105,7 @@ def log_likelihood_to_xarray(self): data[obs_name] = np.reshape(log_like, shape) except: # pylint: disable=bare-except # cannot get vectorized trace - pass + return None return dict_to_dataset(data, library=self.pyro, coords=self.coords, dims=dims) @requires("posterior_predictive") From fa86c5807f56c0c61faba633a8ada9b22319cd3d Mon Sep 17 00:00:00 2001 From: VincentBt Date: Wed, 5 Feb 2020 13:27:10 +0100 Subject: [PATCH 10/10] updates Pyro version for Azure --- CHANGELOG.md | 2 +- azure-pipelines.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5762d99cb..24b3054598 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### New features * Add out-of-sample predictions (`predictions` and `predictions_constant_data` groups) to pymc3 and pystan translations (#983 and #1032) -* Started adding pointwise log likelihood storage support (#794) +* Started adding pointwise log likelihood storage support (#794, #1044) * Violinplot: rug-plot option (#997) * Integrated rcParams `plot.point_estimate` (#994), `stats.ic_scale` (#993) and `stats.credible_interval` (#1017) * Added `group` argument to `plot_ppc` (#1008), `plot_pair` (#1009) and `plot_joint` (#1012) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index aac9d7fde3..c9b1d5974b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -14,10 +14,10 @@ jobs: PYRO_VERSION: "latest" EMCEE_VERSION: "latest" NAME: "UNIT" - Python_36_Unit_Test_PyStan_3_Pyro_0.5.1_Emcee_2_tf_1: + Python_36_Unit_Test_PyStan_3_Pyro_1.0.0_Emcee_2_tf_1: PYTHON_VERSION: 3.6 PYSTAN_VERSION: "preview" - PYRO_VERSION: 0.5.1 + PYRO_VERSION: 1.0.0 PYTORCH_VERSION: 1.3.0 EMCEE_VERSION: 2 TF_VERSION: 1