|
40 | 40 | 'HalfCauchy', 'Gamma', 'Weibull', 'HalfStudentT', 'Lognormal',
|
41 | 41 | 'ChiSquared', 'HalfNormal', 'Wald', 'Pareto', 'InverseGamma',
|
42 | 42 | 'ExGaussian', 'VonMises', 'SkewNormal', 'Triangular', 'Gumbel',
|
43 |
| - 'Logistic', 'LogitNormal', 'Interpolated', 'Rice'] |
| 43 | + 'Logistic', 'LogitNormal', 'Interpolated', 'Rice', 'Moyal'] |
44 | 44 |
|
45 | 45 |
|
46 | 46 | class PositiveContinuous(Continuous):
|
@@ -1946,7 +1946,7 @@ class StudentT(Continuous):
|
1946 | 1946 | plt.show()
|
1947 | 1947 |
|
1948 | 1948 | ======== ========================
|
1949 |
| - Support :math:``x \in \mathbb{R}`` |
| 1949 | + Support :math:`x \in \mathbb{R}` |
1950 | 1950 | ======== ========================
|
1951 | 1951 |
|
1952 | 1952 | Parameters
|
@@ -4381,3 +4381,133 @@ def logp(self, value):
|
4381 | 4381 | TensorVariable
|
4382 | 4382 | """
|
4383 | 4383 | return tt.log(self.interp_op(value) / self.Z)
|
| 4384 | + |
| 4385 | + |
| 4386 | +class Moyal(Continuous): |
| 4387 | + R""" |
| 4388 | + Moyal log-likelihood. |
| 4389 | +
|
| 4390 | + The pdf of this distribution is |
| 4391 | +
|
| 4392 | + .. math:: |
| 4393 | +
|
| 4394 | + f(x \mid \mu,\sigma) = \frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{1}{2}\left(z + e^{-z}\right)}, |
| 4395 | +
|
| 4396 | + where |
| 4397 | +
|
| 4398 | + .. math:: |
| 4399 | +
|
| 4400 | + z = \frac{x-\mu}{\sigma}. |
| 4401 | +
|
| 4402 | + .. plot:: |
| 4403 | +
|
| 4404 | + import matplotlib.pyplot as plt |
| 4405 | + import numpy as np |
| 4406 | + import scipy.stats as st |
| 4407 | + plt.style.use('seaborn-darkgrid') |
| 4408 | + x = np.linspace(-10, 20, 200) |
| 4409 | + mus = [-1., 0., 4.] |
| 4410 | + sigmas = [2., 2., 4.] |
| 4411 | + for mu, sigma in zip(mus, sigmas): |
| 4412 | + pdf = st.moyal.pdf(x, loc=mu, scale=sigma) |
| 4413 | + plt.plot(x, pdf, label=r'$\mu$ = {}, $\sigma$ = {}'.format(mu, sigma)) |
| 4414 | + plt.xlabel('x', fontsize=12) |
| 4415 | + plt.ylabel('f(x)', fontsize=12) |
| 4416 | + plt.legend(loc=1) |
| 4417 | + plt.show() |
| 4418 | +
|
| 4419 | + ======== ============================================================== |
| 4420 | + Support :math:`x \in (-\infty, \infty)` |
| 4421 | + Mean :math:`\mu + \sigma\left(\gamma + \log 2\right)`, where :math:`\gamma` is the Euler-Mascheroni constant |
| 4422 | + Variance :math:`\frac{\pi^{2}}{2}\sigma^{2}` |
| 4423 | + ======== ============================================================== |
| 4424 | +
|
| 4425 | + Parameters |
| 4426 | + ---------- |
| 4427 | + mu: float |
| 4428 | + Location parameter. |
| 4429 | + sigma: float |
| 4430 | + Scale parameter (sigma > 0). |
| 4431 | + """ |
| 4432 | + |
| 4433 | + def __init__(self, mu=0, sigma=1., *args, **kwargs): |
| 4434 | + self.mu = tt.as_tensor_variable(floatX(mu)) |
| 4435 | + self.sigma = tt.as_tensor_variable(floatX(sigma)) |
| 4436 | + |
| 4437 | + assert_negative_support(sigma, 'sigma', 'Moyal') |
| 4438 | + |
| 4439 | + self.mean = self.mu + self.sigma * (np.euler_gamma + tt.log(2)) |
| 4440 | + self.median = self.mu - self.sigma * tt.log(2 * tt.erfcinv(1 / 2)**2) |
| 4441 | + self.mode = self.mu |
| 4442 | + self.variance = (np.pi**2 / 2.0) * self.sigma**2 |
| 4443 | + |
| 4444 | + super().__init__(*args, **kwargs) |
| 4445 | + |
| 4446 | + def random(self, point=None, size=None): |
| 4447 | + """ |
| 4448 | + Draw random values from Moyal distribution. |
| 4449 | +
|
| 4450 | + Parameters |
| 4451 | + ---------- |
| 4452 | + point: dict, optional |
| 4453 | + Dict of variable values on which random values are to be |
| 4454 | + conditioned (uses default point if not specified). |
| 4455 | + size: int, optional |
| 4456 | + Desired size of random sample (returns one sample if not |
| 4457 | + specified). |
| 4458 | +
|
| 4459 | + Returns |
| 4460 | + ------- |
| 4461 | + array |
| 4462 | + """ |
| 4463 | + mu, sigma = draw_values([self.mu, self.sigma], point=point, size=size) |
| 4464 | + return generate_samples(stats.moyal.rvs, loc=mu, scale=sigma, |
| 4465 | + dist_shape=self.shape, |
| 4466 | + size=size) |
| 4467 | + |
| 4468 | + def logp(self, value): |
| 4469 | + """ |
| 4470 | + Calculate log-probability of Moyal distribution at specified value. |
| 4471 | +
|
| 4472 | + Parameters |
| 4473 | + ---------- |
| 4474 | + value: numeric |
| 4475 | + Value(s) for which log-probability is calculated. If the log probabilities for multiple |
| 4476 | + values are desired the values must be provided in a numpy array or theano tensor |
| 4477 | +
|
| 4478 | + Returns |
| 4479 | + ------- |
| 4480 | + TensorVariable |
| 4481 | + """ |
| 4482 | + scaled = (value - self.mu) / self.sigma |
| 4483 | + return bound((-(1 / 2) * (scaled + tt.exp(-scaled)) |
| 4484 | + - tt.log(self.sigma) |
| 4485 | + - (1 / 2) * tt.log(2 * np.pi)), self.sigma > 0) |
| 4486 | + |
| 4487 | + def _repr_latex_(self, name=None, dist=None): |
| 4488 | + if dist is None: |
| 4489 | + dist = self |
| 4490 | + sigma = dist.sigma |
| 4491 | + mu = dist.mu |
| 4492 | + name = r'\text{%s}' % name |
| 4493 | + return r'${} \sim \text{{Moyal}}(\mathit{{mu}}={},~\mathit{{sigma}}={})$'.format(name, |
| 4494 | + get_variable_name(mu), |
| 4495 | + get_variable_name(sigma)) |
| 4496 | + |
| 4497 | + def logcdf(self, value): |
| 4498 | + """ |
| 4499 | + Compute the log of the cumulative distribution function for Moyal distribution |
| 4500 | + at the specified value. |
| 4501 | +
|
| 4502 | + Parameters |
| 4503 | + ---------- |
| 4504 | + value: numeric |
| 4505 | + Value(s) for which log CDF is calculated. If the log CDF for multiple |
| 4506 | + values are desired the values must be provided in a numpy array or theano tensor. |
| 4507 | +
|
| 4508 | + Returns |
| 4509 | + ------- |
| 4510 | + TensorVariable |
| 4511 | + """ |
| 4512 | + scaled = (value - self.mu) / self.sigma |
| 4513 | + return tt.log(tt.erfc(tt.exp(-scaled / 2) * (2**-0.5))) |
0 commit comments