From f877ca8263bfd8c8e23f1926e4da9534a4a4546c Mon Sep 17 00:00:00 2001 From: AlexAndorra Date: Wed, 25 Mar 2020 18:56:36 +0100 Subject: [PATCH 1/7] Added check that a>0 in Dirichlet --- pymc3/distributions/multivariate.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index ece8eaf807..697315ed63 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -488,6 +488,8 @@ class Dirichlet(Continuous): def __init__(self, a, transform=transforms.stick_breaking, *args, **kwargs): + if (a <= 0).any(): + raise ValueError("All concentration parameters must be > 0.") shape = np.atleast_1d(a.shape)[-1] kwargs.setdefault("shape", shape) From bfa1b990456e870b3c21210ac2fdd061b9346279 Mon Sep 17 00:00:00 2001 From: AlexAndorra Date: Fri, 27 Mar 2020 18:55:33 +0100 Subject: [PATCH 2/7] Cast a as array for tests --- pymc3/distributions/multivariate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index 697315ed63..6bf82dfb39 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -488,7 +488,7 @@ class Dirichlet(Continuous): def __init__(self, a, transform=transforms.stick_breaking, *args, **kwargs): - if (a <= 0).any(): + if (np.asarray(a) <= 0).any(): raise ValueError("All concentration parameters must be > 0.") shape = np.atleast_1d(a.shape)[-1] From 4ea89b66550307dc36b74d13f33c4d24e1914509 Mon Sep 17 00:00:00 2001 From: AlexAndorra Date: Sat, 28 Mar 2020 17:56:17 +0100 Subject: [PATCH 3/7] Test a>0 only when a not an RV and convert to array when list --- pymc3/distributions/multivariate.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index 6bf82dfb39..c198865738 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -488,8 +488,16 @@ class Dirichlet(Continuous): def __init__(self, a, transform=transforms.stick_breaking, *args, **kwargs): - if (np.asarray(a) <= 0).any(): - raise ValueError("All concentration parameters must be > 0.") + + if not isinstance(a, pm.model.TensorVariable): + if not isinstance(a, list) and not isinstance(a, np.ndarray): + raise TypeError( + 'The vector of concentration parameters (a) must be a python list ' + 'or numpy array.') + a = np.array(a) + if (a <= 0).any(): + raise ValueError("All concentration parameters (a) must be > 0.") + shape = np.atleast_1d(a.shape)[-1] kwargs.setdefault("shape", shape) From 12c11446244462c1df5890bfa3f1100334d2fcc2 Mon Sep 17 00:00:00 2001 From: AlexAndorra Date: Wed, 1 Apr 2020 19:29:58 +0200 Subject: [PATCH 4/7] Added test for init of Dirichlet with negative values --- pymc3/tests/test_distributions.py | 34 +++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/pymc3/tests/test_distributions.py b/pymc3/tests/test_distributions.py index 581b1a8358..7ea159c081 100644 --- a/pymc3/tests/test_distributions.py +++ b/pymc3/tests/test_distributions.py @@ -944,17 +944,39 @@ def test_lkj(self, x, eta, n, lp): @pytest.mark.parametrize('n', [2, 3]) def test_dirichlet(self, n): - self.pymc3_matches_scipy(Dirichlet, Simplex( - n), {'a': Vector(Rplus, n)}, dirichlet_logpdf) + self.pymc3_matches_scipy( + Dirichlet, + Simplex(n), + {'a': Vector(Rplus, n)}, + dirichlet_logpdf + ) + + @pytest.mark.parametrize('n', [3, 4]) + def test_dirichlet_init_fail(self, n): + with Model(): + with pytest.raises(ValueError) as err: + _ = Dirichlet('x', a=np.zeros(n), shape=n) + err.match("All concentration parameters (a) must be > 0.") + with pytest.raises(ValueError) as err: + _ = Dirichlet('x', a=np.array([-1.] * n), shape=n) + err.match("All concentration parameters (a) must be > 0.") def test_dirichlet_2D(self): - self.pymc3_matches_scipy(Dirichlet, MultiSimplex(2, 2), - {'a': Vector(Vector(Rplus, 2), 2)}, dirichlet_logpdf) + self.pymc3_matches_scipy( + Dirichlet, + MultiSimplex(2, 2), + {'a': Vector(Vector(Rplus, 2), 2)}, + dirichlet_logpdf + ) @pytest.mark.parametrize('n', [2, 3]) def test_multinomial(self, n): - self.pymc3_matches_scipy(Multinomial, Vector(Nat, n), {'p': Simplex(n), 'n': Nat}, - multinomial_logpdf) + self.pymc3_matches_scipy( + Multinomial, + Vector(Nat, n), + {'p': Simplex(n), 'n': Nat}, + multinomial_logpdf + ) @pytest.mark.parametrize('p,n', [ [[.25, .25, .25, .25], 1], From 23ea13426ea002b228abf5e3fcad60e7b315a018 Mon Sep 17 00:00:00 2001 From: AlexAndorra Date: Wed, 1 Apr 2020 19:33:33 +0200 Subject: [PATCH 5/7] Added release note --- RELEASE-NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 802f40f816..7ae41ca2cc 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -16,6 +16,7 @@ - Tuning results no longer leak into sequentially sampled `Metropolis` chains (see #3733 and #3796). - Deprecated `sd` in version 3.7 has been replaced by `sigma` now raises `DepreciationWarning` on using `sd` in continuous, mixed and timeseries distributions. (see #3837 and #3688). - In named models, `pm.Data` objects now get model-relative names (see [#3843](https://github.com/pymc-devs/pymc3/pull/3843)) +- The Dirichlet distribution now raises a ValueError when it's initialized with <= 0 values (see [#3853](https://github.com/pymc-devs/pymc3/pull/3853)). ## PyMC3 3.8 (November 29 2019) From 5ba3b50e2282b954d2eb3b52f330f0812e76d1e5 Mon Sep 17 00:00:00 2001 From: AlexAndorra Date: Wed, 1 Apr 2020 19:46:42 +0200 Subject: [PATCH 6/7] Resolved conflict in release notes --- RELEASE-NOTES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 7ae41ca2cc..06bfe46abd 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -15,7 +15,10 @@ - Remove `sample_ppc` and `sample_ppc_w` that were deprecated in 3.6. - Tuning results no longer leak into sequentially sampled `Metropolis` chains (see #3733 and #3796). - Deprecated `sd` in version 3.7 has been replaced by `sigma` now raises `DepreciationWarning` on using `sd` in continuous, mixed and timeseries distributions. (see #3837 and #3688). -- In named models, `pm.Data` objects now get model-relative names (see [#3843](https://github.com/pymc-devs/pymc3/pull/3843)) +- In named models, `pm.Data` objects now get model-relative names (see [#3843](https://github.com/pymc-devs/pymc3/pull/3843)). +- `pm.sample` now takes 1000 draws and 1000 tuning samples by default, instead of 500 previously (see [#3855](https://github.com/pymc-devs/pymc3/pull/3855)). +- Dropped the outdated 'nuts' initialization method for `pm.sample` (see [#3863](https://github.com/pymc-devs/pymc3/pull/3863)). +- Moved argument division out of `NegativeBinomial` `random` method. Fixes [#3864](https://github.com/pymc-devs/pymc3/issues/3864) in the style of [#3509](https://github.com/pymc-devs/pymc3/pull/3509). - The Dirichlet distribution now raises a ValueError when it's initialized with <= 0 values (see [#3853](https://github.com/pymc-devs/pymc3/pull/3853)). ## PyMC3 3.8 (November 29 2019) From 4023db63301725ac6a0c1b64da1369cc6f565b9a Mon Sep 17 00:00:00 2001 From: AlexAndorra Date: Wed, 1 Apr 2020 22:16:07 +0200 Subject: [PATCH 7/7] Escaped parenthesis in match regexp --- pymc3/tests/test_distributions.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pymc3/tests/test_distributions.py b/pymc3/tests/test_distributions.py index 7ea159c081..9353405451 100644 --- a/pymc3/tests/test_distributions.py +++ b/pymc3/tests/test_distributions.py @@ -954,12 +954,16 @@ def test_dirichlet(self, n): @pytest.mark.parametrize('n', [3, 4]) def test_dirichlet_init_fail(self, n): with Model(): - with pytest.raises(ValueError) as err: + with pytest.raises( + ValueError, + match=r"All concentration parameters \(a\) must be > 0." + ): _ = Dirichlet('x', a=np.zeros(n), shape=n) - err.match("All concentration parameters (a) must be > 0.") - with pytest.raises(ValueError) as err: + with pytest.raises( + ValueError, + match=r"All concentration parameters \(a\) must be > 0." + ): _ = Dirichlet('x', a=np.array([-1.] * n), shape=n) - err.match("All concentration parameters (a) must be > 0.") def test_dirichlet_2D(self): self.pymc3_matches_scipy(