Skip to content

Commit 955370c

Browse files
Fix NegativeBinomial parameterization and enable its tests
1 parent e68e757 commit 955370c

File tree

2 files changed

+21
-28
lines changed

2 files changed

+21
-28
lines changed

pymc3/distributions/discrete.py

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -727,35 +727,33 @@ def NegBinom(a, m, x):
727727

728728
@classmethod
729729
def dist(cls, mu=None, alpha=None, p=None, n=None, *args, **kwargs):
730-
mu, alpha = cls.get_mu_alpha(mu, alpha, p, n)
731-
mu = aet.as_tensor_variable(floatX(mu))
732-
alpha = aet.as_tensor_variable(floatX(alpha))
733-
# mode = intX(aet.floor(mu))
734-
return super().dist([mu, alpha], *args, **kwargs)
730+
n, p = cls.get_mu_alpha(mu, alpha, p, n)
731+
n = aet.as_tensor_variable(floatX(n))
732+
p = aet.as_tensor_variable(floatX(p))
733+
return super().dist([n, p], *args, **kwargs)
735734

736735
@classmethod
737736
def get_mu_alpha(cls, mu=None, alpha=None, p=None, n=None):
738-
if alpha is None:
739-
if n is not None:
740-
n = aet.as_tensor_variable(intX(n))
741-
alpha = n
737+
if n is None:
738+
if alpha is not None:
739+
n = aet.as_tensor_variable(floatX(alpha))
742740
else:
743741
raise ValueError("Incompatible parametrization. Must specify either alpha or n.")
744-
elif n is not None:
742+
elif alpha is not None:
745743
raise ValueError("Incompatible parametrization. Can't specify both alpha and n.")
746744

747-
if mu is None:
748-
if p is not None:
749-
p = aet.as_tensor_variable(floatX(p))
750-
mu = alpha * (1 - p) / p
745+
if p is None:
746+
if mu is not None:
747+
mu = aet.as_tensor_variable(floatX(mu))
748+
p = n / (mu + n)
751749
else:
752750
raise ValueError("Incompatible parametrization. Must specify either mu or p.")
753-
elif p is not None:
751+
elif mu is not None:
754752
raise ValueError("Incompatible parametrization. Can't specify both mu and p.")
755753

756-
return mu, alpha
754+
return n, p
757755

758-
def logp(value, mu, alpha):
756+
def logp(value, n, p):
759757
r"""
760758
Calculate log-probability of NegativeBinomial distribution at specified value.
761759
@@ -769,6 +767,8 @@ def logp(value, mu, alpha):
769767
-------
770768
TensorVariable
771769
"""
770+
alpha = n
771+
mu = alpha * (1 - p) / p
772772
negbinom = bound(
773773
binomln(value + alpha - 1, value)
774774
+ logpow(mu / (mu + alpha), value)
@@ -779,9 +779,9 @@ def logp(value, mu, alpha):
779779
)
780780

781781
# Return Poisson when alpha gets very large.
782-
return aet.switch(aet.gt(alpha, 1e10), Poisson.dist(mu).logp(value), negbinom)
782+
return aet.switch(aet.gt(alpha, 1e10), Poisson.logp(value, mu), negbinom)
783783

784-
def logcdf(value, mu, alpha):
784+
def logcdf(value, n, p):
785785
"""
786786
Compute the log of the cumulative distribution function for NegativeBinomial distribution
787787
at the specified value.
@@ -801,20 +801,14 @@ def logcdf(value, mu, alpha):
801801
f"NegativeBinomial.logcdf expects a scalar value but received a {np.ndim(value)}-dimensional object."
802802
)
803803

804-
# TODO: avoid `p` recomputation if distribution was defined in terms of `p`
805-
p = alpha / (mu + alpha)
806-
807804
return bound(
808-
aet.log(incomplete_beta(alpha, aet.floor(value) + 1, p)),
805+
aet.log(incomplete_beta(n, aet.floor(value) + 1, p)),
809806
0 <= value,
810-
0 < alpha,
807+
0 < n,
811808
0 <= p,
812809
p <= 1,
813810
)
814811

815-
def _distr_parameters_for_repr(self):
816-
return self._param_type
817-
818812

819813
class Geometric(Discrete):
820814
R"""

pymc3/tests/test_distributions.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,6 @@ def modified_scipy_hypergeom_logcdf(value, N, k, n):
11711171
{"N": NatSmall, "k": NatSmall, "n": NatSmall},
11721172
)
11731173

1174-
@pytest.mark.xfail(reason="Distribution not refactored yet")
11751174
def test_negative_binomial(self):
11761175
def scipy_mu_alpha_logpmf(value, mu, alpha):
11771176
return sp.nbinom.logpmf(value, alpha, 1 - mu / (mu + alpha))

0 commit comments

Comments
 (0)