From df227a9b44f24057ae9b9b90d12648ba9ec0b401 Mon Sep 17 00:00:00 2001 From: aloctavodia Date: Thu, 19 Oct 2023 13:02:42 -0300 Subject: [PATCH] add more distributions to roulette --- preliz/distributions/continuous.py | 5 ++-- preliz/distributions/discrete.py | 16 +++++------ preliz/internal/optimization.py | 4 ++- preliz/tests/test_distributions.py | 2 ++ preliz/tests/test_maxent.py | 2 +- preliz/unidimensional/roulette.py | 45 +++++++++++++++++++++++++++--- 6 files changed, 57 insertions(+), 17 deletions(-) diff --git a/preliz/distributions/continuous.py b/preliz/distributions/continuous.py index 35f24f18..d50376a3 100644 --- a/preliz/distributions/continuous.py +++ b/preliz/distributions/continuous.py @@ -583,7 +583,8 @@ def _parametrization(self, mu=None, sigma=None, nu=None): self.sigma = sigma self.param_names = ("mu", "sigma", "nu") self.params = (mu, sigma, nu) - self.params_support = ((-np.inf, np.inf), (eps, np.inf), (eps, np.inf)) + # if nu is too small we get a non-smooth distribution + self.params_support = ((-np.inf, np.inf), (eps, np.inf), (1e-4, np.inf)) if all_not_none(mu, sigma, nu): self._update(mu, sigma, nu) @@ -602,7 +603,7 @@ def _update(self, mu, sigma, nu): def _fit_moments(self, mean, sigma): # Just assume this is a approximately Gaussian - self._update(mean, sigma, 1e-6) + self._update(mean, sigma, 1e-4) def _fit_mle(self, sample, **kwargs): K, mu, sigma = self.dist.fit(sample, **kwargs) diff --git a/preliz/distributions/discrete.py b/preliz/distributions/discrete.py index 7b28697d..b6f1aceb 100644 --- a/preliz/distributions/discrete.py +++ b/preliz/distributions/discrete.py @@ -856,9 +856,7 @@ def _update(self, mu, alpha): self._update_rv_frozen() def _fit_moments(self, mean, sigma): - mu = mean - alpha = mean**2 / (sigma**2 - mean) - self._update(mu, alpha) + optimize_moments(self, mean, sigma) def _fit_mle(self, sample): optimize_ml(self, sample) @@ -981,7 +979,7 @@ def __init__(self, psi=None, n=None, p=None): self.psi = psi self.n = n self.p = p - self.dist = ZIBinomial + self.dist = _ZIBinomial self.support = (0, np.inf) self._parametrization(psi, n, p) @@ -1092,7 +1090,7 @@ def __init__(self, psi=None, mu=None, alpha=None, p=None, n=None): self.p = p self.alpha = alpha self.mu = mu - self.dist = ZINegativeBinomial + self.dist = _ZINegativeBinomial self.support = (0, np.inf) self._parametrization(psi, mu, alpha, p, n) @@ -1204,7 +1202,7 @@ def __init__(self, psi=None, mu=None): super().__init__() self.psi = psi self.mu = mu - self.dist = ZIPoisson + self.dist = _ZIPoisson self.support = (0, np.inf) self._parametrization(psi, mu) @@ -1238,7 +1236,7 @@ def _fit_mle(self, sample): optimize_ml(self, sample) -class ZIBinomial(stats.rv_continuous): +class _ZIBinomial(stats.rv_continuous): def __init__(self, psi=None, n=None, p=None): super().__init__() self.psi = psi @@ -1296,7 +1294,7 @@ def rvs(self, size=1): # pylint: disable=arguments-differ return samples -class ZINegativeBinomial(stats.rv_continuous): +class _ZINegativeBinomial(stats.rv_continuous): def __init__(self, psi=None, p=None, n=None): super().__init__() self.psi = psi @@ -1355,7 +1353,7 @@ def rvs(self, size=1): # pylint: disable=arguments-differ return samples -class ZIPoisson(stats.rv_continuous): +class _ZIPoisson(stats.rv_continuous): def __init__(self, psi=None, mu=None): super().__init__() self.psi = psi diff --git a/preliz/internal/optimization.py b/preliz/internal/optimization.py index 2dd3849a..ec893ea7 100644 --- a/preliz/internal/optimization.py +++ b/preliz/internal/optimization.py @@ -84,8 +84,10 @@ def func(params, dist, x_vals, ecdf): return loss init_vals = np.array(dist.params)[none_idx] + bounds = np.array(dist.params_support)[none_idx] + bounds = list(zip(*bounds)) - opt = least_squares(func, x0=init_vals, args=(dist, x_vals, ecdf)) + opt = least_squares(func, x0=init_vals, args=(dist, x_vals, ecdf), bounds=bounds) dist._update(*opt["x"]) loss = opt["cost"] return loss diff --git a/preliz/tests/test_distributions.py b/preliz/tests/test_distributions.py index 0ce645d4..bec8b76a 100644 --- a/preliz/tests/test_distributions.py +++ b/preliz/tests/test_distributions.py @@ -119,6 +119,8 @@ def test_moments(distribution, params): "BetaBinomial", "Binomial", "DiscreteWeibull", + "ExGaussian", + "NegativeBinomial", "Kumaraswamy", "LogitNormal", "Rice", diff --git a/preliz/tests/test_maxent.py b/preliz/tests/test_maxent.py index 72185619..19eb077a 100644 --- a/preliz/tests/test_maxent.py +++ b/preliz/tests/test_maxent.py @@ -75,7 +75,7 @@ (Cauchy(), -1, 1, 0.6, (-np.inf, np.inf), (0, 0.726)), (Cauchy(alpha=0.5), -1, 1, 0.6, (-np.inf, np.inf), (0.6000)), (ChiSquared(), 2, 7, 0.6, (0, np.inf), (4.002)), - (ExGaussian(), 9, 10, 0.8, (-np.inf, np.inf), (9.112, 0.133, 0.495)), + (ExGaussian(), 9, 10, 0.8, (-np.inf, np.inf), (9.496, 0.390, 0.003)), (ExGaussian(sigma=0.2), 9, 10, 0.8, (-np.inf, np.inf), (9.168, 0.423)), (Exponential(), 0, 4, 0.9, (0, np.inf), (0.575)), (Gamma(), 0, 10, 0.7, (0, np.inf), (0.868, 0.103)), diff --git a/preliz/unidimensional/roulette.py b/preliz/unidimensional/roulette.py index e520daa4..32725f94 100644 --- a/preliz/unidimensional/roulette.py +++ b/preliz/unidimensional/roulette.py @@ -300,8 +300,9 @@ def reset_dist_panel(x_min, x_max, ax, yticks): def get_widgets(x_min, x_max, nrows, ncols): width_entry_text = widgets.Layout(width="150px") + width_distribution_text = widgets.Layout(width="150px", height="125px") - w_x_min = widgets.IntText( + w_x_min = widgets.FloatText( value=x_min, step=1, description="x_min:", @@ -309,7 +310,7 @@ def get_widgets(x_min, x_max, nrows, ncols): layout=width_entry_text, ) - w_x_max = widgets.IntText( + w_x_max = widgets.FloatText( value=x_max, step=1, description="x_max:", @@ -343,10 +344,46 @@ def get_widgets(x_min, x_max, nrows, ncols): layout=width_entry_text, ) - dist_names = ["Normal", "BetaScaled", "Gamma", "LogNormal", "StudentT"] + default_dist = ["Normal", "BetaScaled", "Gamma", "LogNormal", "StudentT"] + + dist_names = [ + "AsymmetricLaplace", + "BetaScaled", + "ChiSquared", + "ExGaussian", + "Exponential", + "Gamma", + "Gumbel", + "HalfNormal", + "HalfStudentT", + "InverseGamma", + "Laplace", + "LogNormal", + "Logistic", + # "LogitNormal", # fails if we add chips at x_value= 1 + "Moyal", + "Normal", + "Pareto", + "Rice", + "SkewNormal", + "StudentT", + "Triangular", + "VonMises", + "Wald", + "Weibull", + "BetaBinomial", + "DiscreteWeibull", + "Geometric", + "NegativeBinomial", + "Poisson", + ] w_distributions = widgets.SelectMultiple( - options=dist_names, value=dist_names, description="", disabled=False + options=dist_names, + value=default_dist, + description="", + disabled=False, + layout=width_distribution_text, ) return w_x_min, w_x_max, w_ncols, w_nrows, w_repr, w_distributions