diff --git a/docs/distributions.rst b/docs/distributions.rst index eef48d06..7310eac1 100644 --- a/docs/distributions.rst +++ b/docs/distributions.rst @@ -74,9 +74,6 @@ Distributions .. automodule:: preliz.distributions.rice :members: -.. automodule:: preliz.distributions.scaled_inverse_chi_squared - :members: - .. automodule:: preliz.distributions.skewnormal :members: diff --git a/docs/distributions/gallery/scaledinversechisquared.md b/docs/distributions/gallery/scaledinversechisquared.md deleted file mode 100644 index 66338d87..00000000 --- a/docs/distributions/gallery/scaledinversechisquared.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -jupytext: - text_representation: - extension: .md - format_name: myst -kernelspec: - display_name: Python 3 - language: python - name: python3 ---- -# Scaled Inverse Chi-Squared Distribution - - - -[Univariate](../../gallery_tags.rst#univariate), [Continuous](../../gallery_tags.rst#continuous), [Non-Negative](../../gallery_tags.rst#non-negative) - -The Scaled Inverse chi-squared (Scale-Inv-$\chi^2$) is a continuous probability distribution characterized by two parameters, $\nu$, usually called degrees of freedom, and $\tau^2$, a scale parameter. - -The Scaled Inverse chi-squared distribution is mainly used in Bayesian inference as a conjugate prior for variance parameters in normal models, particularly in Bayesian regression, hierarchical models, -and time-series analysis. - -## Key properties and parameters - -```{eval-rst} -======== ============================================================== -Support :math:`x \in [0, \infty)` -Mean :math:`\frac{\nu \tau^2}{\nu - 2}` for :math:`\nu > 2`, else :math:`\infty` -Variance :math:`\frac{2 \nu^2 \tau^4}{(\nu - 2)^2 (\nu - 4)}` - for :math:`\nu > 4`, else :math:`\infty` -======== ============================================================== -``` - -**Parameters:** - -- $\nu$ : (float) Degrees of freedom, $\nu > 0$. -- $\tau^2$ : (float) Scale parameter, $\tau^2 > 0$. - -### Probability Density Function (PDF) - -$$ -f(x \mid \nu, \tau^2) -= -\frac{(\tau^2 \nu / 2)^{\nu/2}}{\Gamma(\nu/2)} -\ -\frac{\exp\left[-\dfrac{\nu \tau^2}{2x}\right]}{x^{1+\nu/2}} -$$ - -where $\Gamma(\nu)$ is the [gamma function](https://en.wikipedia.org/wiki/Gamma_function). - -```{code-cell} ---- -tags: [remove-input] -mystnb: - image: - alt: Scaled Inverse Chi-Squared Distribution PDF ---- - -import numpy as np -from preliz import ScaledInverseChiSquared, style -style.use('preliz-doc') - -nus = [1, 5, 10] -tau2s = [1, 1, 1] - -for nu, tau2 in zip(nus,tau2s): - ax = ScaledInverseChiSquared(nu, tau2).plot_pdf(support=(np.finfo(float).eps, 5)) - ax.set_ylim(0, 1) -``` - -### Cumulative Distribution Function (CDF) - -$$ -F(x \mid \nu, \tau^2) = \frac{\Gamma\left(\dfrac{\nu}{2}, \dfrac{\tau^2\nu}{2x}\right)}{\Gamma\left(\dfrac{\nu}{2}\right)} -$$ - -where $\Gamma(\nu, x)$ is the [incomplete gamma function](https://en.wikipedia.org/wiki/Incomplete_gamma_function). - -```{code-cell} ---- -tags: [remove-input] -mystnb: - image: - alt: Scaled Inverse Chi-Squared Distribution CDF ---- - -for nu, tau2 in zip(nus,tau2s): - ax = ScaledInverseChiSquared(nu, tau2).plot_cdf(support=(np.finfo(float).eps, 5)) - ax.set_ylim(0, 1) -``` - -```{seealso} -:class: seealso - -**Related Distributions:** - -- [Chi-Squared](chisquared.md) - The Inverse Chi-Squared distribution can be thought of as the reciprocal of a scaled Chi-Squared random variable. -- [Gamma](gamma.md) - the Inverse Chi-Squared distribution can be seen as the reciprocal of a Gamma-distributed variable with specific parameters. -``` - -## References - -- [Wikipedia - Scaled Inverse Chi-squared distribution](https://en.wikipedia.org/wiki/Scaled_inverse_chi-squared_distribution) - diff --git a/docs/gallery_content.rst b/docs/gallery_content.rst index eef2649e..3caf90d6 100644 --- a/docs/gallery_content.rst +++ b/docs/gallery_content.rst @@ -282,18 +282,6 @@ Continuous Distributions +++ Rice - .. grid-item-card:: - :link: ./distributions/gallery/scaledinversechisquared.html - :text-align: center - :shadow: none - :class-card: example-gallery - - .. image:: distributions/img/ScaledInverseChiSquared.png - :alt: ScaledInverseChiSquared - - +++ - Scaled-Inverse-Chi-Squared - .. grid-item-card:: :link: ./distributions/gallery/skewnormal.html :text-align: center diff --git a/docs/gallery_tags.rst b/docs/gallery_tags.rst index 3e4db06c..3b7aa3cb 100644 --- a/docs/gallery_tags.rst +++ b/docs/gallery_tags.rst @@ -33,7 +33,6 @@ These distributions are defined over a continuous range of values. - `Normal <./distributions/gallery/normal.html>`_ - `Pareto <./distributions/gallery/pareto.html>`_ - `Rice <./distributions/gallery/rice.html>`_ -- `Scaled Inverse Chi-Squared <./distributions/gallery/scaledinversechisquared.html>`_ - `Skew-Normal <./distributions/gallery/skewnormal.html>`_ - `Student's t <./distributions/gallery/students_t.html>`_ - `Skew-Student's t <./distributions/gallery/skew_studentt.html>`_ @@ -107,7 +106,6 @@ Distributions with skewed (non‐symmetric) shapes include: - `Moyal <./distributions/gallery/moyal.html>`_ - `Pareto <./distributions/gallery/pareto.html>`_ - `Rice <./distributions/gallery/rice.html>`_ -- `Scaled Inverse Chi-Squared <./distributions/gallery/scaledinversechisquared.html>`_ - `Skew-Normal <./distributions/gallery/skewnormal.html>`_ - `Skew-Student's t <./distributions/gallery/skew_studentt.html>`_ - `Weibull <./distributions/gallery/weibull.html>`_ @@ -188,7 +186,6 @@ Distributions supported on the non‐negative real numbers. - `Wald <./distributions/gallery/wald.html>`_ - `Log-Logistic <./distributions/gallery/log_logistic.html>`_ - `Logit-Normal <./distributions/gallery/logit_normal.html>`_ -- `Scaled Inverse Chi-Squared <./distributions/gallery/scaledinversechisquared.html>`_ **Discrete:** @@ -247,7 +244,6 @@ The following distributions are univariate (one-dimensional). - `Normal <./distributions/gallery/normal.html>`_ - `Pareto <./distributions/gallery/pareto.html>`_ - `Rice <./distributions/gallery/rice.html>`_ -- `Scaled Inverse Chi-Squared <./distributions/gallery/scaledinversechisquared.html>`_ - `Skew-Normal <./distributions/gallery/skewnormal.html>`_ - `Student's t <./distributions/gallery/students_t.html>`_ - `Skew-Student's t <./distributions/gallery/skew_studentt.html>`_ diff --git a/docs/pronunciation.py b/docs/pronunciation.py index 883b7de6..dfe2d920 100644 --- a/docs/pronunciation.py +++ b/docs/pronunciation.py @@ -45,7 +45,6 @@ ("BetaBinomial", "βήταsBinomial"), ("Gamma", "γάμμα"), ("chisquared", "χι-squared"), - ("ScaledInverseChiSquared", "scaled inverse χι-squared"), ], "fr": ["Cauchy", "Dirichlet", "Laplace", "Poisson", "ZeroInflatedPoisson"], "it": ["pareto"], diff --git a/preliz/distributions/__init__.py b/preliz/distributions/__init__.py index fac3ba06..7138cd42 100644 --- a/preliz/distributions/__init__.py +++ b/preliz/distributions/__init__.py @@ -35,7 +35,6 @@ from preliz.distributions.pareto import Pareto from preliz.distributions.poisson import Poisson from preliz.distributions.rice import Rice -from preliz.distributions.scaled_inverse_chi_squared import ScaledInverseChiSquared from preliz.distributions.skew_studentt import SkewStudentT from preliz.distributions.skewnormal import SkewNormal from preliz.distributions.studentt import StudentT @@ -74,7 +73,6 @@ Normal, Pareto, Rice, - ScaledInverseChiSquared, SkewNormal, SkewStudentT, StudentT, diff --git a/preliz/distributions/scaled_inverse_chi_squared.py b/preliz/distributions/scaled_inverse_chi_squared.py deleted file mode 100644 index 4f19f27d..00000000 --- a/preliz/distributions/scaled_inverse_chi_squared.py +++ /dev/null @@ -1,183 +0,0 @@ -import numpy as np -from pytensor_distributions import scaledinversechisquared as ptd_scaledinversechisquared - -from preliz.distributions.distributions import Continuous -from preliz.internal.distribution_helper import all_not_none, eps, pytensor_jit, pytensor_rng_jit -from preliz.internal.optimization import optimize_ml - - -class ScaledInverseChiSquared(Continuous): - r""" - Scaled Inverse Chi squared distribution. - - The pdf of this distribution is - - .. math:: - - f(x \mid \nu, \tau^2) = - \frac{(\tau^2\nu/2)^{\nu/2}}{\Gamma(\nu/2)}~ - \frac{\exp\left[ \frac{-\nu \tau^2}{2 x}\right]}{x^{1+\nu/2}} - - - .. plot:: - :context: close-figs - - - from preliz import ScaledInverseChiSquared, style - style.use('preliz-doc') - nus = [4., 4, 10.] - tau2s = [1., 2, 1.] - for nu, tau2 in zip(nus, tau2s): - ScaledInverseChiSquared(nu, tau2).plot_pdf(support=(0, 5)) - - ======== =============================== - Support :math:`x \in [0, \infty)` - Mean :math:`\nu \tau^2 / (\nu - 2)` for :math:`\nu > 2`, else :math:`\infty` - Variance :math:`\frac{2 \nu^2 \tau^4}{(\nu - 2)^2 (\nu - 4)}` - for :math:`\nu > 4`, else :math:`\infty` - ======== =============================== - - - Parameters - ---------- - nu : float - Degrees of freedom (nu > 0). - tau2 : float - Scale (tau2 > 0). - """ - - def __init__(self, nu=None, tau2=None): - super().__init__() - self.nu = nu - self.tau2 = tau2 - self.support = (0, np.inf) - self._parametrization(nu, tau2) - - def _parametrization(self, nu=None, tau2=None): - self.nu = nu - self.tau2 = tau2 - self.param_names = ("nu", "tau2") - self.params_support = ((eps, np.inf), (eps, np.inf)) - self.params = (self.nu, self.tau2) - if all_not_none(nu, tau2): - self._update(self.nu, self.tau2) - - def _update(self, nu, tau2): - self.nu = np.float64(nu) - self.tau2 = np.float64(tau2) - self.params = (self.nu, self.tau2) - self.is_frozen = True - - def pdf(self, x): - return ptd_pdf(x, self.nu, self.tau2) - - def cdf(self, x): - return ptd_cdf(x, self.nu, self.tau2) - - def ppf(self, q): - return ptd_ppf(q, self.nu, self.tau2) - - def logpdf(self, x): - return ptd_logpdf(x, self.nu, self.tau2) - - def entropy(self): - return ptd_entropy(self.nu, self.tau2) - - def mean(self): - return ptd_mean(self.nu, self.tau2) - - def mode(self): - return ptd_mode(self.nu, self.tau2) - - def median(self): - return ptd_median(self.nu, self.tau2) - - def var(self): - return ptd_var(self.nu, self.tau2) - - def std(self): - return ptd_std(self.nu, self.tau2) - - def skewness(self): - return ptd_skewness(self.nu, self.tau2) - - def kurtosis(self): - return ptd_kurtosis(self.nu, self.tau2) - - def rvs(self, size=None, random_state=None): - random_state = np.random.default_rng(random_state) - return ptd_rvs(self.nu, self.tau2, size=size, rng=random_state) - - def _fit_moments(self, mean, sigma): - cv2 = sigma**2 / mean**2 - nu_hat = 4 + 2 / cv2 - tau2_hat = mean * (nu_hat - 2) / nu_hat - self._update(nu_hat, tau2_hat) - - def _fit_mle(self, sample): - optimize_ml(self, sample) - - -@pytensor_jit -def ptd_pdf(x, nu, tau2): - return ptd_scaledinversechisquared.pdf(x, nu, tau2) - - -@pytensor_jit -def ptd_cdf(x, nu, tau2): - return ptd_scaledinversechisquared.cdf(x, nu, tau2) - - -@pytensor_jit -def ptd_ppf(q, nu, tau2): - return ptd_scaledinversechisquared.ppf(q, nu, tau2) - - -@pytensor_jit -def ptd_logpdf(x, nu, tau2): - return ptd_scaledinversechisquared.logpdf(x, nu, tau2) - - -@pytensor_jit -def ptd_entropy(nu, tau2): - return ptd_scaledinversechisquared.entropy(nu, tau2) - - -@pytensor_jit -def ptd_mean(nu, tau2): - return ptd_scaledinversechisquared.mean(nu, tau2) - - -@pytensor_jit -def ptd_mode(nu, tau2): - return ptd_scaledinversechisquared.mode(nu, tau2) - - -@pytensor_jit -def ptd_median(nu, tau2): - return ptd_scaledinversechisquared.median(nu, tau2) - - -@pytensor_jit -def ptd_var(nu, tau2): - return ptd_scaledinversechisquared.var(nu, tau2) - - -@pytensor_jit -def ptd_std(nu, tau2): - return ptd_scaledinversechisquared.std(nu, tau2) - - -@pytensor_jit -def ptd_skewness(nu, tau2): - return ptd_scaledinversechisquared.skewness(nu, tau2) - - -@pytensor_jit -def ptd_kurtosis(nu, tau2): - return ptd_scaledinversechisquared.kurtosis(nu, tau2) - - -@pytensor_rng_jit -def ptd_rvs(nu, tau2, size, rng): - return ptd_scaledinversechisquared.rvs(nu, tau2, size=size, random_state=rng) diff --git a/preliz/internal/distribution_helper.py b/preliz/internal/distribution_helper.py index c0244bf7..b1c9634f 100644 --- a/preliz/internal/distribution_helper.py +++ b/preliz/internal/distribution_helper.py @@ -225,7 +225,6 @@ def inner_func(*args, size, rng, signature_to_function=signature_to_function): "Normal": {"mu": 0.0, "sigma": 1.0}, "Pareto": {"alpha": 5, "m": 2.0}, "Rice": {"nu": 2.0, "sigma": 1.0}, - "ScaledInverseChiSquared": {"nu": 10, "tau2": 1.0}, "SkewNormal": {"mu": 0.0, "sigma": 1, "alpha": 6.0}, "SkewStudentT": {"mu": 0.0, "sigma": 1, "a": 2, "b": 2}, "StudentT": {"nu": 7, "mu": 0.0, "sigma": 1}, diff --git a/preliz/tests/test_from_pymc.py b/preliz/tests/test_from_pymc.py index 54da1e87..81941c34 100644 --- a/preliz/tests/test_from_pymc.py +++ b/preliz/tests/test_from_pymc.py @@ -18,7 +18,6 @@ def test_from_pymc(): if dist_name in [ "BetaScaled", "LogLogistic", - "ScaledInverseChiSquared", "ChiSquared", "Truncated", "Censored", diff --git a/preliz/tests/test_maxent.py b/preliz/tests/test_maxent.py index ce21230e..82f9b9ee 100644 --- a/preliz/tests/test_maxent.py +++ b/preliz/tests/test_maxent.py @@ -36,7 +36,6 @@ Pareto, Poisson, Rice, - ScaledInverseChiSquared, SkewNormal, SkewStudentT, StudentT, @@ -107,7 +106,6 @@ (Rice(), 0, 4, 0.7, (0, np.inf), (0, 2.577)), (Rice(), 1, 10, 0.9, (0, np.inf), (3.454, 3.734)), (Rice(nu=4), 0, 6, 0.9, (0, np.inf), (1.402)), - (ScaledInverseChiSquared(), 0.1, 4, 0.9, (0, np.inf), (4.831, 1.253)), (SkewNormal(), -2, 10, 0.9, (-np.inf, np.inf), (4.0, 3.647, 0.0)), (SkewNormal(mu=-1), -2, 10, 0.9, (-np.inf, np.inf), (6.293, 4.908)), (SkewStudentT(), -1, 1, 0.9, (-np.inf, np.inf), (0.034, 0.522, 3.222, 3.356)), diff --git a/preliz/tests/test_mle.py b/preliz/tests/test_mle.py index 9d6650f0..89a1ba39 100644 --- a/preliz/tests/test_mle.py +++ b/preliz/tests/test_mle.py @@ -36,7 +36,6 @@ Pareto, Poisson, Rice, - ScaledInverseChiSquared, SkewNormal, SkewStudentT, StudentT, @@ -79,7 +78,6 @@ (Normal, (0, 1)), (Pareto, (5, 1)), (Rice, (0, 2)), - (ScaledInverseChiSquared, (10, 1.0)), (SkewNormal, (0, 1, -6)), (SkewStudentT, (0, 1, 2, 2)), (StudentT, (4, 0, 1)), diff --git a/preliz/tests/test_non_scipy.py b/preliz/tests/test_non_scipy.py index d933b70b..622f7944 100644 --- a/preliz/tests/test_non_scipy.py +++ b/preliz/tests/test_non_scipy.py @@ -1,9 +1,8 @@ import numpy as np from numpy.testing import assert_almost_equal -from scipy import integrate from scipy.stats import kurtosis, skew -from preliz.distributions import Categorical, DiscreteWeibull, ScaledInverseChiSquared +from preliz.distributions import Categorical, DiscreteWeibull def test_categorical(): @@ -37,30 +36,3 @@ def test_disc_weibull_vs_random(): assert_almost_equal(dist.cdf(x), np.sum(dist.pdf(np.arange(x + 1))), decimal=2) assert_almost_equal(dist.cdf(x), np.sum(np.exp(dist.logpdf(np.arange(x + 1)))), decimal=2) assert_almost_equal(dist.cdf(x), np.mean(rvs <= x), decimal=2) - - -def test_scaled_inverse_chi2(): - dist = ScaledInverseChiSquared(15, 1) - - rng = np.random.default_rng(1) - rvs = dist.rvs(500_000, random_state=rng) - - assert_almost_equal(dist.mean(), rvs.mean(), decimal=2) - assert_almost_equal(dist.median(), np.median(rvs), decimal=2) - assert_almost_equal(dist.var(), rvs.var(), decimal=1) - assert_almost_equal(dist.std(), rvs.std(), decimal=1) - assert_almost_equal(dist.skewness(), skew(rvs), decimal=0) - assert_almost_equal(dist.kurtosis(), kurtosis(rvs), decimal=0) - - q = np.linspace(0.1, 0.9, 10) - assert_almost_equal(dist.ppf(q), np.quantile(rvs, q), decimal=2) - assert_almost_equal(dist.cdf(dist.ppf(q)), q, decimal=2) - - for x in np.arange(6): - assert_almost_equal(dist.cdf(x), np.mean(rvs <= x), decimal=2) - - assert_almost_equal(integrate.quad(dist.pdf, 0.1, 50)[0], 1, decimal=5) - - for x in np.linspace(0.2, 10, 5): - val, _ = integrate.quad(dist.pdf, 0, x) - assert_almost_equal(val, dist.cdf(x)) diff --git a/preliz/tests/test_quartile.py b/preliz/tests/test_quartile.py index 6c2b983a..aa418ca1 100644 --- a/preliz/tests/test_quartile.py +++ b/preliz/tests/test_quartile.py @@ -35,7 +35,6 @@ Pareto, Poisson, Rice, - ScaledInverseChiSquared, SkewStudentT, StudentT, Triangular, @@ -76,7 +75,6 @@ (Normal(), -1, 0, 1, (0, 1.482)), (Pareto(), 0.5, 1, 4, (0.541, 0.289)), (Rice(), 2, 4, 6, (0, 3.395)), - (ScaledInverseChiSquared(), 0.9, 1.4, 2.4, (4.366, 1.199)), (SkewStudentT(), 2, 4, 6, (4.000, 2.648, 1.663, 1.663)), pytest.param( StudentT(),