From 836c3f9741162bbdfb6f3497dc328b26f94b65a2 Mon Sep 17 00:00:00 2001 From: Eric Ma Date: Sat, 22 Jul 2017 15:28:09 -0400 Subject: [PATCH 1/9] fixed multivariate --- pymc3/distributions/multivariate.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index 8a2c753ad2..0505b1ff83 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -505,7 +505,14 @@ def __init__(self, n, p, *args, **kwargs): def _random(self, n, p, size=None): if size == p.shape: size = None - return np.random.multinomial(n, p, size=size) + # return np.random.multinomial(n, p, size=size) + # print(p.sum(axis=1)) + if p.ndim > 1 and p.shape[0] > 1: + p = p / (p.sum(axis=1, keepdims=True)+1E-6) + randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) + else: + randnum = np.random.multinomial(n, p, size=size) + return randnum def random(self, point=None, size=None): n, p = draw_values([self.n, self.p], point=point) From 57f4ba8dae1ede0892ed7f86c52f3d7b901dd74a Mon Sep 17 00:00:00 2001 From: Eric Ma Date: Thu, 27 Jul 2017 20:33:33 -0400 Subject: [PATCH 2/9] multivariate fix for pvals > 1 --- pymc3/distributions/multivariate.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index 5173587de5..86818949e6 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -506,9 +506,16 @@ def _random(self, n, p, size=None): if size == p.shape: size = None if p.ndim == 1: + p = p.squeeze() + p[-1] = 1 - np.sum(p[:-1]) randnum = np.random.multinomial(n, p.squeeze(), size=size) elif p.ndim == 2: - randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) + nums = [] + for pp in p: + pp[-1] = 1 - np.sum(p[:-1]) + nums = np.random.multinomial(n, pp, size=size) + randnum = np.asarray(nums) + # randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) else: raise ValueError('Outcome probabilities must be 1- or 2-dimensional ' '(supplied `p` has {} dimensions)'.format(p.ndim)) From 731bc6b6856c3ac3128029981d0a4cfcb254660c Mon Sep 17 00:00:00 2001 From: Eric Ma Date: Fri, 28 Jul 2017 09:38:52 -0400 Subject: [PATCH 3/9] updated multivariate with hack --- pymc3/distributions/multivariate.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index 86818949e6..8ee6a1df65 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -503,16 +503,15 @@ def __init__(self, n, p, *args, **kwargs): self.mode = tt.cast(tround(self.mean), 'int32') def _random(self, n, p, size=None): + p = p / (np.sum(p, axis=1, keepdims=True) + 1E-6) if size == p.shape: size = None if p.ndim == 1: - p = p.squeeze() - p[-1] = 1 - np.sum(p[:-1]) randnum = np.random.multinomial(n, p.squeeze(), size=size) elif p.ndim == 2: nums = [] for pp in p: - pp[-1] = 1 - np.sum(p[:-1]) + # pp = pp / (pp.sum(axis=1, keepdims=True) + 1E-6) nums = np.random.multinomial(n, pp, size=size) randnum = np.asarray(nums) # randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) From 01e267e25abda5c06c700247fe236943450c6faf Mon Sep 17 00:00:00 2001 From: Eric Ma Date: Fri, 28 Jul 2017 09:44:51 -0400 Subject: [PATCH 4/9] bugfix --- pymc3/distributions/multivariate.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index 8ee6a1df65..0963628402 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -503,18 +503,17 @@ def __init__(self, n, p, *args, **kwargs): self.mode = tt.cast(tround(self.mean), 'int32') def _random(self, n, p, size=None): - p = p / (np.sum(p, axis=1, keepdims=True) + 1E-6) + p = p / (p.sum(axis=1, keepdims=True) + 1E-6) if size == p.shape: size = None if p.ndim == 1: - randnum = np.random.multinomial(n, p.squeeze(), size=size) + randnum = np.random.multinomial(n, p, size=size) elif p.ndim == 2: - nums = [] - for pp in p: - # pp = pp / (pp.sum(axis=1, keepdims=True) + 1E-6) - nums = np.random.multinomial(n, pp, size=size) - randnum = np.asarray(nums) - # randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) + # nums = [] + # for pp in p: + # nums = np.random.multinomial(n, pp, size=size) + # randnum = np.asarray(nums) + randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) else: raise ValueError('Outcome probabilities must be 1- or 2-dimensional ' '(supplied `p` has {} dimensions)'.format(p.ndim)) From 0d7f754fc1c864eb18ba0d29cbacce7f7e49ddf7 Mon Sep 17 00:00:00 2001 From: Eric Ma Date: Wed, 2 Aug 2017 15:26:58 -0400 Subject: [PATCH 5/9] float64 patch to multivariate's multinomial --- pymc3/distributions/multivariate.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index 0963628402..cff09dbdaf 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -503,16 +503,15 @@ def __init__(self, n, p, *args, **kwargs): self.mode = tt.cast(tround(self.mean), 'int32') def _random(self, n, p, size=None): - p = p / (p.sum(axis=1, keepdims=True) + 1E-6) + # Set float type to float64 for numpy. + p = p.astype('float64') + # Now, re-normalize all of the values in float64 precision. + p = p / (p.sum(axis=1, keepdims=True)) if size == p.shape: size = None if p.ndim == 1: randnum = np.random.multinomial(n, p, size=size) elif p.ndim == 2: - # nums = [] - # for pp in p: - # nums = np.random.multinomial(n, pp, size=size) - # randnum = np.asarray(nums) randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) else: raise ValueError('Outcome probabilities must be 1- or 2-dimensional ' From b48fd99ea7882fcc261999a88e6c5753947660f0 Mon Sep 17 00:00:00 2001 From: Eric Ma Date: Wed, 2 Aug 2017 15:31:15 -0400 Subject: [PATCH 6/9] reinstated p.squeeze(), accidentally took it out --- 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 cff09dbdaf..b77700b974 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -510,7 +510,7 @@ def _random(self, n, p, size=None): if size == p.shape: size = None if p.ndim == 1: - randnum = np.random.multinomial(n, p, size=size) + randnum = np.random.multinomial(n, p.squeeze(), size=size) elif p.ndim == 2: randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) else: From 4d0fc943bd9bf11b2e6a577ea92d1440c3d87b9d Mon Sep 17 00:00:00 2001 From: Eric Ma Date: Wed, 2 Aug 2017 15:44:34 -0400 Subject: [PATCH 7/9] updated based on failed test --- pymc3/distributions/multivariate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index b77700b974..3a79ce6b02 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -506,12 +506,13 @@ def _random(self, n, p, size=None): # Set float type to float64 for numpy. p = p.astype('float64') # Now, re-normalize all of the values in float64 precision. - p = p / (p.sum(axis=1, keepdims=True)) if size == p.shape: size = None if p.ndim == 1: + p = p / (p.sum()) randnum = np.random.multinomial(n, p.squeeze(), size=size) elif p.ndim == 2: + p = p / (p.sum(axis=1, keepdims=True)) randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) else: raise ValueError('Outcome probabilities must be 1- or 2-dimensional ' From c28382fbec280d1953b234822549ed902f78956e Mon Sep 17 00:00:00 2001 From: Eric Ma Date: Wed, 2 Aug 2017 18:43:53 -0400 Subject: [PATCH 8/9] further minor fixes to multinomial --- pymc3/distributions/multivariate.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pymc3/distributions/multivariate.py b/pymc3/distributions/multivariate.py index 3a79ce6b02..3f028282f5 100755 --- a/pymc3/distributions/multivariate.py +++ b/pymc3/distributions/multivariate.py @@ -503,21 +503,22 @@ def __init__(self, n, p, *args, **kwargs): self.mode = tt.cast(tround(self.mean), 'int32') def _random(self, n, p, size=None): - # Set float type to float64 for numpy. + original_dtype = p.dtype + # Set float type to float64 for numpy. This change is related to numpy issue #8317 (https://github.com/numpy/numpy/issues/8317) p = p.astype('float64') - # Now, re-normalize all of the values in float64 precision. + # Now, re-normalize all of the values in float64 precision. This is done inside the conditionals if size == p.shape: size = None if p.ndim == 1: - p = p / (p.sum()) + p = p / p.sum() randnum = np.random.multinomial(n, p.squeeze(), size=size) elif p.ndim == 2: - p = p / (p.sum(axis=1, keepdims=True)) + p = p / p.sum(axis=1, keepdims=True) randnum = np.asarray([np.random.multinomial(n, pp, size=size) for pp in p]) else: raise ValueError('Outcome probabilities must be 1- or 2-dimensional ' '(supplied `p` has {} dimensions)'.format(p.ndim)) - return randnum + return randnum.astype(original_dtype) def random(self, point=None, size=None): n, p = draw_values([self.n, self.p], point=point) From 5047cb4c4dee7e8d31b8c43626ee0d21ff626625 Mon Sep 17 00:00:00 2001 From: Eric Ma Date: Wed, 2 Aug 2017 20:16:21 -0400 Subject: [PATCH 9/9] Force push to restart Travis