Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 35 additions & 34 deletions pymc3/distributions/continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,24 @@ def __init__(self, transform=transforms.logodds, *args, **kwargs):
super(UnitContinuous, self).__init__(
transform=transform, *args, **kwargs)

def assert_nonpos_support(var, label, distname):
def assert_negative_support(var, label, distname, value=-1e-6):
# Checks for evidence of positive support for a variable
if var is None:
return
try:
# Transformed distribution
support = np.isfinite(var.transformed.distribution.dist.logp(0).tag.test_value)
support = np.isfinite(var.transformed.distribution.dist
.logp(value).tag.test_value)
except AttributeError:
try:
# Untransformed distribution
support = np.isfinite(var.distribution.logp(0).tag.test_value)
support = np.isfinite(var.distribution.logp(value).tag.test_value)
except AttributeError:
# Otherwise no direct evidence of non-positive support
support = False

if np.any(support):
msg = "The variable specified for {0} has non-positive support for {1}, ".format(label, distname)
msg = "The variable specified for {0} has negative support for {1}, ".format(label, distname)
msg += "likely making it unsuitable for this parameter."
warnings.warn(msg)

Expand Down Expand Up @@ -226,8 +227,8 @@ def __init__(self, *args, **kwargs):
self.tau, self.sd = get_tau_sd(tau=tau, sd=sd)
self.variance = 1. / self.tau

assert_nonpos_support(sd, 'sd', 'Normal')
assert_nonpos_support(tau, 'tau', 'Normal')
assert_negative_support(sd, 'sd', 'Normal')
assert_negative_support(tau, 'tau', 'Normal')

super(Normal, self).__init__(**kwargs)

Expand Down Expand Up @@ -276,8 +277,8 @@ def __init__(self, sd=None, tau=None, *args, **kwargs):
self.mean = tt.sqrt(2 / (np.pi * self.tau))
self.variance = (1. - 2 / np.pi) / self.tau

assert_nonpos_support(tau, 'tau', 'HalfNormal')
assert_nonpos_support(sd, 'sd', 'HalfNormal')
assert_negative_support(tau, 'tau', 'HalfNormal')
assert_negative_support(sd, 'sd', 'HalfNormal')

def random(self, point=None, size=None, repeat=None):
sd = draw_values([self.sd], point=point)
Expand Down Expand Up @@ -358,9 +359,9 @@ def __init__(self, mu=None, lam=None, phi=None, alpha=0., *args, **kwargs):
- 1.5 * self.mu / self.lam) + alpha
self.variance = (self.mu**3) / self.lam

assert_nonpos_support(phi, 'phi', 'Wald')
assert_nonpos_support(mu, 'mu', 'Wald')
assert_nonpos_support(lam, 'lam', 'Wald')
assert_negative_support(phi, 'phi', 'Wald')
assert_negative_support(mu, 'mu', 'Wald')
assert_negative_support(lam, 'lam', 'Wald')

def get_mu_lam_phi(self, mu, lam, phi):
if mu is None:
Expand Down Expand Up @@ -464,8 +465,8 @@ def __init__(self, alpha=None, beta=None, mu=None, sd=None,
self.variance = alpha * beta / (
(alpha + beta)**2 * (alpha + beta + 1))

assert_nonpos_support(alpha, 'alpha', 'Beta')
assert_nonpos_support(beta, 'beta', 'Beta')
assert_negative_support(alpha, 'alpha', 'Beta')
assert_negative_support(beta, 'beta', 'Beta')

def get_alpha_beta(self, alpha=None, beta=None, mu=None, sd=None):
if (alpha is not None) and (beta is not None):
Expand Down Expand Up @@ -526,7 +527,7 @@ def __init__(self, lam, *args, **kwargs):

self.variance = lam**-2

assert_nonpos_support(lam, 'lam', 'Exponential')
assert_negative_support(lam, 'lam', 'Exponential')

def random(self, point=None, size=None, repeat=None):
lam = draw_values([self.lam], point=point)
Expand Down Expand Up @@ -569,7 +570,7 @@ def __init__(self, mu, b, *args, **kwargs):

self.variance = 2 * b**2

assert_nonpos_support(b, 'b', 'Laplace')
assert_negative_support(b, 'b', 'Laplace')

def random(self, point=None, size=None, repeat=None):
mu, b = draw_values([self.mu, self.b], point=point)
Expand Down Expand Up @@ -624,8 +625,8 @@ def __init__(self, mu=0, sd=None, tau=None, *args, **kwargs):
self.mode = tt.exp(mu - 1. / self.tau)
self.variance = (tt.exp(1. / self.tau) - 1) * tt.exp(2 * mu + 1. / self.tau)

assert_nonpos_support(tau, 'tau', 'Lognormal')
assert_nonpos_support(sd, 'sd', 'Lognormal')
assert_negative_support(tau, 'tau', 'Lognormal')
assert_negative_support(sd, 'sd', 'Lognormal')

def _random(self, mu, tau, size=None):
samples = np.random.normal(size=size)
Expand Down Expand Up @@ -685,8 +686,8 @@ def __init__(self, nu, mu=0, lam=None, sd=None, *args, **kwargs):
(1 / self.lam) * (nu / (nu - 2)),
np.inf)

assert_nonpos_support(lam, 'lam (sd)', 'StudentT')
assert_nonpos_support(nu, 'nu', 'StudentT')
assert_negative_support(lam, 'lam (sd)', 'StudentT')
assert_negative_support(nu, 'nu', 'StudentT')

def random(self, point=None, size=None, repeat=None):
nu, mu, lam = draw_values([self.nu, self.mu, self.lam],
Expand Down Expand Up @@ -746,8 +747,8 @@ def __init__(self, alpha, m, *args, **kwargs):
(alpha * m**2) / ((alpha - 2.) * (alpha - 1.)**2),
np.inf)

assert_nonpos_support(alpha, 'alpha', 'Pareto')
assert_nonpos_support(m, 'm', 'Pareto')
assert_negative_support(alpha, 'alpha', 'Pareto')
assert_negative_support(m, 'm', 'Pareto')


def _random(self, alpha, m, size=None):
Expand Down Expand Up @@ -800,7 +801,7 @@ def __init__(self, alpha, beta, *args, **kwargs):
self.median = self.mode = self.alpha = alpha
self.beta = beta

assert_nonpos_support(beta, 'beta', 'Cauchy')
assert_negative_support(beta, 'beta', 'Cauchy')

def _random(self, alpha, beta, size=None):
u = np.random.uniform(size=size)
Expand Down Expand Up @@ -848,7 +849,7 @@ def __init__(self, beta, *args, **kwargs):
self.median = beta
self.beta = beta

assert_nonpos_support(beta, 'beta', 'HalfCauchy')
assert_negative_support(beta, 'beta', 'HalfCauchy')

def _random(self, beta, size=None):
u = np.random.uniform(size=size)
Expand Down Expand Up @@ -916,8 +917,8 @@ def __init__(self, alpha=None, beta=None, mu=None, sd=None,
self.mode = tt.maximum((alpha - 1) / beta, 0)
self.variance = alpha / beta**2

assert_nonpos_support(alpha, 'alpha', 'Gamma')
assert_nonpos_support(beta, 'beta', 'Gamma')
assert_negative_support(alpha, 'alpha', 'Gamma')
assert_negative_support(beta, 'beta', 'Gamma')

def get_alpha_beta(self, alpha=None, beta=None, mu=None, sd=None):
if (alpha is not None) and (beta is not None):
Expand Down Expand Up @@ -985,8 +986,8 @@ def __init__(self, alpha, beta=1, *args, **kwargs):
self.variance = tt.switch(tt.gt(alpha, 2),
(beta**2) / (alpha * (alpha - 1.)**2),
np.inf)
assert_nonpos_support(alpha, 'alpha', 'InverseGamma')
assert_nonpos_support(beta, 'beta', 'InverseGamma')
assert_negative_support(alpha, 'alpha', 'InverseGamma')
assert_negative_support(beta, 'beta', 'InverseGamma')

def _calculate_mean(self):
m = self.beta / (self.alpha - 1.)
Expand Down Expand Up @@ -1070,8 +1071,8 @@ def __init__(self, alpha, beta, *args, **kwargs):
self.variance = (beta**2) * \
tt.exp(gammaln(1 + 2. / alpha - self.mean**2))

assert_nonpos_support(alpha, 'alpha', 'Weibull')
assert_nonpos_support(beta, 'beta', 'Weibull')
assert_negative_support(alpha, 'alpha', 'Weibull')
assert_negative_support(beta, 'beta', 'Weibull')

def random(self, point=None, size=None, repeat=None):
alpha, beta = draw_values([self.alpha, self.beta],
Expand Down Expand Up @@ -1259,8 +1260,8 @@ def __init__(self, mu, sigma, nu, *args, **kwargs):
self.mean = mu + nu
self.variance = (sigma**2) + (nu**2)

assert_nonpos_support(sigma, 'sigma', 'ExGaussian')
assert_nonpos_support(nu, 'nu', 'ExGaussian')
assert_negative_support(sigma, 'sigma', 'ExGaussian')
assert_negative_support(nu, 'nu', 'ExGaussian')

def random(self, point=None, size=None, repeat=None):
mu, sigma, nu = draw_values([self.mu, self.sigma, self.nu],
Expand Down Expand Up @@ -1320,7 +1321,7 @@ def __init__(self, mu=0.0, kappa=None, transform='circular',
if transform == 'circular':
self.transform = transforms.Circular()

assert_nonpos_support(kappa, 'kappa', 'VonMises')
assert_negative_support(kappa, 'kappa', 'VonMises')

def random(self, point=None, size=None, repeat=None):
mu, kappa = draw_values([self.mu, self.kappa],
Expand Down Expand Up @@ -1377,8 +1378,8 @@ def __init__(self, mu=0.0, sd=None, tau=None, alpha=1, *args, **kwargs):
self.mean = mu + self.sd * (2 / np.pi)**0.5 * alpha / (1 + alpha**2)**0.5
self.variance = self.sd**2 * (1 - (2 * alpha**2) / ((1 + alpha**2) * np.pi))

assert_nonpos_support(tau, 'tau', 'SkewNormal')
assert_nonpos_support(sd, 'sd', 'SkewNormal')
assert_negative_support(tau, 'tau', 'SkewNormal')
assert_negative_support(sd, 'sd', 'SkewNormal')

def random(self, point=None, size=None, repeat=None):
mu, tau, sd, alpha = draw_values(
Expand Down