From ac99de5117adc1092a0693e7dd31e496e4dfb7c4 Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Thu, 11 Nov 2021 16:46:00 +0530 Subject: [PATCH 01/12] Add MvNormal moment --- pymc/distributions/multivariate.py | 3 +++ pymc/tests/test_distributions_moments.py | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/pymc/distributions/multivariate.py b/pymc/distributions/multivariate.py index cfa372e037..b06eb732ed 100644 --- a/pymc/distributions/multivariate.py +++ b/pymc/distributions/multivariate.py @@ -224,6 +224,9 @@ def dist(cls, mu, cov=None, tau=None, chol=None, lower=True, **kwargs): cov = quaddist_matrix(cov, chol, tau, lower) return super().dist([mu, cov], **kwargs) + def get_moment(rv, size, mu, cov): + return mu + def logp(value, mu, cov): """ Calculate log-probability of Multivariate Normal distribution diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index ce9fec627f..8a8c50984c 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -36,6 +36,7 @@ ZeroInflatedBinomial, ZeroInflatedPoisson, ) +from pymc.distributions.multivariate import MvNormal from pymc.distributions.shape_utils import rv_size_is_none from pymc.initial_point import make_initial_point_fn from pymc.model import Model @@ -595,3 +596,16 @@ def test_discrete_uniform_moment(lower, upper, size, expected): with Model() as model: DiscreteUniform("x", lower=lower, upper=upper, size=size) assert_moment_is_expected(model, expected) + + +@pytest.mark.parametrize( + "mu, cov, size, expected", + [ + (np.array([1.]), np.array([[1.]]), None, np.array([1.])), + (np.ones((10, )), np.identity(10), None, np.ones((10, ))) + ] +) +def test_mv_normal_moment(mu, cov, size, expected): + with Model() as model: + MvNormal("x", mu=mu, cov=cov, size=size) + assert_moment_is_expected(model, expected) From bca1be6853d24c6e87e90a6c71a90f6c594227b9 Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Sat, 13 Nov 2021 16:14:13 +0530 Subject: [PATCH 02/12] fix MvNormal moment test --- pymc/distributions/multivariate.py | 13 +++++++++++-- pymc/tests/test_distributions_moments.py | 4 +++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pymc/distributions/multivariate.py b/pymc/distributions/multivariate.py index b06eb732ed..593c253d45 100644 --- a/pymc/distributions/multivariate.py +++ b/pymc/distributions/multivariate.py @@ -21,6 +21,7 @@ import aesara import aesara.tensor as at +from aesara.tensor.extra_ops import broadcast_shape import numpy as np import scipy @@ -46,7 +47,11 @@ from pymc.distributions.continuous import ChiSquared, Normal, assert_negative_support from pymc.distributions.dist_math import bound, factln, logpow, multigammaln from pymc.distributions.distribution import Continuous, Discrete -from pymc.distributions.shape_utils import broadcast_dist_samples_to, to_tuple +from pymc.distributions.shape_utils import ( + broadcast_dist_samples_to, + rv_size_is_none, + to_tuple +) from pymc.math import kron_diag, kron_dot __all__ = [ @@ -225,7 +230,11 @@ def dist(cls, mu, cov=None, tau=None, chol=None, lower=True, **kwargs): return super().dist([mu, cov], **kwargs) def get_moment(rv, size, mu, cov): - return mu + moment = mu + if not rv_size_is_none(size): + m_size = at.concatenate([size, mu.shape]) + moment = at.full(m_size, mu) + return moment def logp(value, mu, cov): """ diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index 8a8c50984c..4e31390956 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -602,7 +602,9 @@ def test_discrete_uniform_moment(lower, upper, size, expected): "mu, cov, size, expected", [ (np.array([1.]), np.array([[1.]]), None, np.array([1.])), - (np.ones((10, )), np.identity(10), None, np.ones((10, ))) + (np.ones((10, )), np.identity(10), None, np.ones((10, ))), + (np.ones(2), np.identity(2), 4, np.ones((4, 2))), + (np.ones(2), np.identity(2), (4, 2), np.ones((4, 2, 2))), ] ) def test_mv_normal_moment(mu, cov, size, expected): From 109de6d49b465d4b50b96da4c7fd70de106629fb Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Sun, 14 Nov 2021 11:54:48 +0530 Subject: [PATCH 03/12] add mu 2-dim case in MvNormal tests --- pymc/distributions/multivariate.py | 10 +++------- pymc/tests/test_distributions_moments.py | 6 ++++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/pymc/distributions/multivariate.py b/pymc/distributions/multivariate.py index 593c253d45..e5eae26046 100644 --- a/pymc/distributions/multivariate.py +++ b/pymc/distributions/multivariate.py @@ -47,11 +47,7 @@ from pymc.distributions.continuous import ChiSquared, Normal, assert_negative_support from pymc.distributions.dist_math import bound, factln, logpow, multigammaln from pymc.distributions.distribution import Continuous, Discrete -from pymc.distributions.shape_utils import ( - broadcast_dist_samples_to, - rv_size_is_none, - to_tuple -) +from pymc.distributions.shape_utils import broadcast_dist_samples_to, rv_size_is_none, to_tuple from pymc.math import kron_diag, kron_dot __all__ = [ @@ -232,8 +228,8 @@ def dist(cls, mu, cov=None, tau=None, chol=None, lower=True, **kwargs): def get_moment(rv, size, mu, cov): moment = mu if not rv_size_is_none(size): - m_size = at.concatenate([size, mu.shape]) - moment = at.full(m_size, mu) + moment_size = at.concatenate([size, mu.shape]) + moment = at.full(moment_size, mu) return moment def logp(value, mu, cov): diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index 4e31390956..0d57a807bc 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -601,10 +601,12 @@ def test_discrete_uniform_moment(lower, upper, size, expected): @pytest.mark.parametrize( "mu, cov, size, expected", [ - (np.array([1.]), np.array([[1.]]), None, np.array([1.])), - (np.ones((10, )), np.identity(10), None, np.ones((10, ))), + (np.ones(1), np.identity(1), None, np.ones(1)), + (np.ones(10), np.identity(10), None, np.ones(10)), (np.ones(2), np.identity(2), 4, np.ones((4, 2))), (np.ones(2), np.identity(2), (4, 2), np.ones((4, 2, 2))), + (np.ones((2, 2)), np.identity(2), 4, np.ones((4, 2, 2))), + (np.ones((2, 2)), np.identity(2), (4, 2), np.ones((4, 2, 2, 2))), ] ) def test_mv_normal_moment(mu, cov, size, expected): From 716d7fa8b8e7785e3897b77a12b886105af4ceff Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Sun, 14 Nov 2021 12:00:27 +0530 Subject: [PATCH 04/12] add more cases in MvNormal moment tests --- pymc/tests/test_distributions_moments.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index 0d57a807bc..231ae2f729 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -605,6 +605,7 @@ def test_discrete_uniform_moment(lower, upper, size, expected): (np.ones(10), np.identity(10), None, np.ones(10)), (np.ones(2), np.identity(2), 4, np.ones((4, 2))), (np.ones(2), np.identity(2), (4, 2), np.ones((4, 2, 2))), + (np.ones((2, 2)), np.identity(2), None, np.ones((2, 2))), (np.ones((2, 2)), np.identity(2), 4, np.ones((4, 2, 2))), (np.ones((2, 2)), np.identity(2), (4, 2), np.ones((4, 2, 2, 2))), ] From 6b4d26a2cef07a8692a06ad5dbbb89700c693d03 Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Sun, 14 Nov 2021 14:29:54 +0530 Subject: [PATCH 05/12] fix pre-commit --- pymc/distributions/multivariate.py | 8 ++++++-- pymc/tests/test_distributions_moments.py | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pymc/distributions/multivariate.py b/pymc/distributions/multivariate.py index 917c139b38..ee9bb79cc5 100644 --- a/pymc/distributions/multivariate.py +++ b/pymc/distributions/multivariate.py @@ -21,7 +21,6 @@ import aesara import aesara.tensor as at -from aesara.tensor.extra_ops import broadcast_shape import numpy as np import scipy @@ -30,6 +29,7 @@ from aesara.graph.op import Op from aesara.sparse.basic import sp_sum from aesara.tensor import gammaln, sigmoid +from aesara.tensor.extra_ops import broadcast_shape from aesara.tensor.nlinalg import det, eigh, matrix_inverse, trace from aesara.tensor.random.basic import MultinomialRV, dirichlet, multivariate_normal from aesara.tensor.random.op import RandomVariable, default_shape_from_params @@ -47,7 +47,11 @@ from pymc.distributions.continuous import ChiSquared, Normal, assert_negative_support from pymc.distributions.dist_math import bound, factln, logpow, multigammaln from pymc.distributions.distribution import Continuous, Discrete -from pymc.distributions.shape_utils import broadcast_dist_samples_to, rv_size_is_none, to_tuple +from pymc.distributions.shape_utils import ( + broadcast_dist_samples_to, + rv_size_is_none, + to_tuple, +) from pymc.math import kron_diag, kron_dot __all__ = [ diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index 7471a94d3e..afea0dd958 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -761,7 +761,7 @@ def test_categorical_moment(p, size, expected): (np.ones((2, 2)), np.identity(2), None, np.ones((2, 2))), (np.ones((2, 2)), np.identity(2), 4, np.ones((4, 2, 2))), (np.ones((2, 2)), np.identity(2), (4, 2), np.ones((4, 2, 2, 2))), - ] + ], ) def test_mv_normal_moment(mu, cov, size, expected): with Model() as model: From 29b08560727a405f0f49a895466b2f8d83198758 Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Sun, 14 Nov 2021 14:35:33 +0530 Subject: [PATCH 06/12] fix pylint issue --- pymc/distributions/multivariate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymc/distributions/multivariate.py b/pymc/distributions/multivariate.py index ee9bb79cc5..5ce1d2c73a 100644 --- a/pymc/distributions/multivariate.py +++ b/pymc/distributions/multivariate.py @@ -48,8 +48,8 @@ from pymc.distributions.dist_math import bound, factln, logpow, multigammaln from pymc.distributions.distribution import Continuous, Discrete from pymc.distributions.shape_utils import ( - broadcast_dist_samples_to, - rv_size_is_none, + broadcast_dist_samples_to, + rv_size_is_none, to_tuple, ) from pymc.math import kron_diag, kron_dot From 0c6f57f634a8bd25cc48a490584f872050ae071c Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Sun, 14 Nov 2021 14:41:46 +0530 Subject: [PATCH 07/12] remove unused imports --- pymc/distributions/multivariate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pymc/distributions/multivariate.py b/pymc/distributions/multivariate.py index 5ce1d2c73a..19d130905d 100644 --- a/pymc/distributions/multivariate.py +++ b/pymc/distributions/multivariate.py @@ -29,7 +29,6 @@ from aesara.graph.op import Op from aesara.sparse.basic import sp_sum from aesara.tensor import gammaln, sigmoid -from aesara.tensor.extra_ops import broadcast_shape from aesara.tensor.nlinalg import det, eigh, matrix_inverse, trace from aesara.tensor.random.basic import MultinomialRV, dirichlet, multivariate_normal from aesara.tensor.random.op import RandomVariable, default_shape_from_params From 9edbdb1520f66443cfef6adb913cee906b7b7737 Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Mon, 15 Nov 2021 18:28:47 +0530 Subject: [PATCH 08/12] remove incorrect and add new test cases --- pymc/tests/test_distributions_moments.py | 27 ++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index a8a0441c53..b35d016ba9 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -758,15 +758,34 @@ def test_categorical_moment(p, size, expected): (np.ones(1), np.identity(1), None, np.ones(1)), (np.ones(10), np.identity(10), None, np.ones(10)), (np.ones(2), np.identity(2), 4, np.ones((4, 2))), - (np.ones(2), np.identity(2), (4, 2), np.ones((4, 2, 2))), - (np.ones((2, 2)), np.identity(2), None, np.ones((2, 2))), - (np.ones((2, 2)), np.identity(2), 4, np.ones((4, 2, 2))), - (np.ones((2, 2)), np.identity(2), (4, 2), np.ones((4, 2, 2, 2))), + (np.ones(2), np.identity(2), (4, 3), np.ones((4, 3, 2))), + (np.array([1, 0, 3.0]), np.identity(3), None, np.array([1, 0, 3.0])), + (np.array([1, 0, 3.0]), np.identity(3), 4, np.full((4, 3), [1, 0, 3.0])), + (np.array([1, 0, 3.0]), np.identity(3), (4, 2), np.full((4, 2, 3), [1, 0, 3.0])), + ( + np.array([1, 3.0]), + np.identity(2), + (4, 5), + np.full((4, 5, 2), [1, 3.0]), + ), + ( + np.array([1, 3.0]), + np.array([[1.0, 0.5], [0.5, 2]]), + (4, 5), + np.full((4, 5, 2), [1, 3.0]), + ), + ( + np.array([1, 3, 0.0]), + np.array([[1.0, 0.5, 0.1], [0.5, 2, 0.5], [0.1, 0.5, 5]]), + (4, 5), + np.full((4, 5, 3), [1, 3, 0.0]), + ), ], ) def test_mv_normal_moment(mu, cov, size, expected): with Model() as model: MvNormal("x", mu=mu, cov=cov, size=size) + assert_moment_is_expected(model, expected) @pytest.mark.parametrize( From a81959a16cbf25c3257fb61e3ab1b63604ce7e6b Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Mon, 15 Nov 2021 20:20:01 +0530 Subject: [PATCH 09/12] readd mu 2-dim test cases --- pymc/tests/test_distributions_moments.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index b35d016ba9..c36e480827 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -759,6 +759,9 @@ def test_categorical_moment(p, size, expected): (np.ones(10), np.identity(10), None, np.ones(10)), (np.ones(2), np.identity(2), 4, np.ones((4, 2))), (np.ones(2), np.identity(2), (4, 3), np.ones((4, 3, 2))), + (np.ones((2, 2)), np.identity(2), None, np.ones((2, 2))), + (np.ones((2, 2)), np.identity(2), 4, np.ones((4, 2, 2))), + (np.ones((2, 2)), np.identity(2), (4, 2), np.ones((4, 2, 2, 2))), (np.array([1, 0, 3.0]), np.identity(3), None, np.array([1, 0, 3.0])), (np.array([1, 0, 3.0]), np.identity(3), 4, np.full((4, 3), [1, 0, 3.0])), (np.array([1, 0, 3.0]), np.identity(3), (4, 2), np.full((4, 2, 3), [1, 0, 3.0])), @@ -780,6 +783,12 @@ def test_categorical_moment(p, size, expected): (4, 5), np.full((4, 5, 3), [1, 3, 0.0]), ), + ( + np.array([[3., 5], [1, 4]]), + np.identity(2), + (4, 5), + np.full((4, 5, 2, 2), [[3., 5], [1, 4]]) + ), ], ) def test_mv_normal_moment(mu, cov, size, expected): From d4945ab8b328417b03120e9d82786b32a4f62266 Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Mon, 15 Nov 2021 20:26:14 +0530 Subject: [PATCH 10/12] fix format --- pymc/tests/test_distributions_moments.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index c36e480827..293a905c1a 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -784,10 +784,10 @@ def test_categorical_moment(p, size, expected): np.full((4, 5, 3), [1, 3, 0.0]), ), ( - np.array([[3., 5], [1, 4]]), + np.array([[3.0, 5], [1, 4]]), np.identity(2), (4, 5), - np.full((4, 5, 2, 2), [[3., 5], [1, 4]]) + np.full((4, 5, 2, 2), [[3.0, 5], [1, 4]]), ), ], ) From c9ec32fa00453344ff25cd179d4fe1b47635d6ee Mon Sep 17 00:00:00 2001 From: yadav-sachin Date: Tue, 16 Nov 2021 00:24:51 +0530 Subject: [PATCH 11/12] remove few test cases --- pymc/tests/test_distributions_moments.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index 293a905c1a..e63c7d81b8 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -756,20 +756,17 @@ def test_categorical_moment(p, size, expected): "mu, cov, size, expected", [ (np.ones(1), np.identity(1), None, np.ones(1)), - (np.ones(10), np.identity(10), None, np.ones(10)), + (np.ones(3), np.identity(3), None, np.ones(3)), (np.ones(2), np.identity(2), 4, np.ones((4, 2))), - (np.ones(2), np.identity(2), (4, 3), np.ones((4, 3, 2))), (np.ones((2, 2)), np.identity(2), None, np.ones((2, 2))), - (np.ones((2, 2)), np.identity(2), 4, np.ones((4, 2, 2))), - (np.ones((2, 2)), np.identity(2), (4, 2), np.ones((4, 2, 2, 2))), (np.array([1, 0, 3.0]), np.identity(3), None, np.array([1, 0, 3.0])), (np.array([1, 0, 3.0]), np.identity(3), 4, np.full((4, 3), [1, 0, 3.0])), (np.array([1, 0, 3.0]), np.identity(3), (4, 2), np.full((4, 2, 3), [1, 0, 3.0])), ( np.array([1, 3.0]), np.identity(2), - (4, 5), - np.full((4, 5, 2), [1, 3.0]), + 5, + np.full((5, 2), [1, 3.0]), ), ( np.array([1, 3.0]), From 2595160183050cad9f7758d907562a1ced1dbf14 Mon Sep 17 00:00:00 2001 From: Sachin Yadav <40866128+yadav-sachin@users.noreply.github.com> Date: Tue, 16 Nov 2021 03:20:03 +0530 Subject: [PATCH 12/12] remove suggested test cases Co-authored-by: Ricardo Vieira <28983449+ricardoV94@users.noreply.github.com> --- pymc/tests/test_distributions_moments.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pymc/tests/test_distributions_moments.py b/pymc/tests/test_distributions_moments.py index e63c7d81b8..c2ec034af0 100644 --- a/pymc/tests/test_distributions_moments.py +++ b/pymc/tests/test_distributions_moments.py @@ -757,10 +757,8 @@ def test_categorical_moment(p, size, expected): [ (np.ones(1), np.identity(1), None, np.ones(1)), (np.ones(3), np.identity(3), None, np.ones(3)), - (np.ones(2), np.identity(2), 4, np.ones((4, 2))), (np.ones((2, 2)), np.identity(2), None, np.ones((2, 2))), (np.array([1, 0, 3.0]), np.identity(3), None, np.array([1, 0, 3.0])), - (np.array([1, 0, 3.0]), np.identity(3), 4, np.full((4, 3), [1, 0, 3.0])), (np.array([1, 0, 3.0]), np.identity(3), (4, 2), np.full((4, 2, 3), [1, 0, 3.0])), ( np.array([1, 3.0]), @@ -774,12 +772,6 @@ def test_categorical_moment(p, size, expected): (4, 5), np.full((4, 5, 2), [1, 3.0]), ), - ( - np.array([1, 3, 0.0]), - np.array([[1.0, 0.5, 0.1], [0.5, 2, 0.5], [0.1, 0.5, 5]]), - (4, 5), - np.full((4, 5, 3), [1, 3, 0.0]), - ), ( np.array([[3.0, 5], [1, 4]]), np.identity(2),