Skip to content

Commit

Permalink
Add mode argument to maxent (#603)
Browse files Browse the repository at this point in the history
* Add mode argument to maxent

* disable abstract-method

* raise from exc
  • Loading branch information
aloctavodia authored Dec 12, 2024
1 parent 6e566f7 commit adec493
Show file tree
Hide file tree
Showing 28 changed files with 172 additions and 184 deletions.
3 changes: 2 additions & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ disable=missing-docstring,
too-few-public-methods,
import-error,
protected-access,
no-self-use
no-self-use,
abstract-method,


# Enable the message, report, category or checker with the given id(s). You can
Expand Down
134 changes: 68 additions & 66 deletions docs/examples/Direct_elicitation_in_1D.ipynb

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions preliz/distributions/bernoulli.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ def entropy(self):
def mean(self):
return self.p

def mode(self):
return self.median()

def median(self):
return np.where(self.p <= 0.5, 0, 1)

Expand Down
5 changes: 5 additions & 0 deletions preliz/distributions/beta.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ def entropy(self):
def mean(self):
return self.alpha / (self.alpha + self.beta)

def mode(self):
return np.where(
(self.alpha > 1) & (self.beta > 1), (self.alpha - 1) / (self.alpha + self.beta - 2), 0.5
)

def median(self):
return self.ppf(0.5)

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/cauchy.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ def entropy(self):
def mean(self):
return np.nan

def mode(self):
return self.alpha

def median(self):
return self.alpha

Expand Down
29 changes: 16 additions & 13 deletions preliz/distributions/distributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ def __repr__(self):
else f"{n}=[" + "".join(f"{vi:.3g}, " for vi in v).strip(", ") + "], "
for n, v in zip(self.param_names, self.params)
).strip(", ")

return f"{bolded_name}({description})"
else:
return name
Expand Down Expand Up @@ -141,7 +140,7 @@ def rvs(self, size=None, random_state=None):
random_state : {None, int, numpy.random.Generator, numpy.random.RandomState}
Defaults to None
"""
return self.rvs(size, random_state)
raise NotImplementedError

def pdf(self, x):
"""Probability density/mass function.
Expand All @@ -151,7 +150,7 @@ def pdf(self, x):
x : array_like
Values on which to evaluate the pdf
"""
return self.pdf(x)
raise NotImplementedError

def cdf(self, x):
"""Cumulative distribution function.
Expand All @@ -161,7 +160,7 @@ def cdf(self, x):
x : array_like
Values on which to evaluate the cdf
"""
return self.cdf(x)
raise NotImplementedError

def ppf(self, q):
"""Percent point function (inverse of cdf).
Expand All @@ -171,7 +170,7 @@ def ppf(self, q):
x : array_like
Values on which to evaluate the inverse of the cdf
"""
return self.ppf(q)
raise NotImplementedError

def logpdf(self, x):
"""Log probability density/mass function.
Expand All @@ -181,35 +180,39 @@ def logpdf(self, x):
x : array_like
Values on which to evaluate the logpdf
"""
return self.pdf(x)
raise NotImplementedError

def entropy(self):
"""Entropy"""
return self.entropy()
raise NotImplementedError

def mean(self):
"""Mean."""
return self.mean()
raise NotImplementedError

def median(self):
"""Median."""
return self.median()
raise NotImplementedError

def mode(self):
"""Mode."""
raise NotImplementedError

def std(self):
"""Standard deviation."""
return self.std()
raise NotImplementedError

def var(self):
"""Variance"""
return self.var()
raise NotImplementedError

def skewness(self):
"""Skewness."""
return self.skewness()
raise NotImplementedError

def kurtosis(self):
"""Excess kurtosis."""
return self.kurtosis()
raise NotImplementedError

def moments(self, types="mvsk"):
"""
Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/exponential.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ def median(self):
def mean(self):
return self.beta

def mode(self):
return np.zeros_like(self.beta)

def std(self):
return self.beta

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/gamma.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ def entropy(self):
def mean(self):
return self.alpha / self.beta

def mode(self):
return np.where(self.alpha <= 1, 0, (self.alpha - 1) / self.beta)

def median(self):
return self.ppf(0.5)

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/geometric.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ def entropy(self):
def mean(self):
return 1 / self.p

def mode(self):
return np.ones_like(self.p)

def median(self):
return np.ceil(-1 / np.log(1 - self.p))

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/gumbel.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ def entropy(self):
def mean(self):
return self.mu + self.beta * np.euler_gamma

def mode(self):
return self.mu

def median(self):
return self.mu - self.beta * np.log(np.log(2))

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/halfcauchy.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ def entropy(self):
def mean(self):
return np.inf

def mode(self):
return np.zeros_like(self.beta)

def median(self):
return self.ppf(0.5)

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/halfnormal.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ def entropy(self):
def mean(self):
return self.sigma * 0.7978845608028655

def mode(self):
return np.zeros_like(self.sigma)

def median(self):
return self.sigma * 0.6744897501960818

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/halfstudentt.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ def mean(self):
mean = self.sigma * (2 / np.pi) ** 0.5
return mean

def mode(self):
return np.zeros_like(self.sigma)

def median(self):
return self.ppf(0.5)

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/inversegamma.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ def entropy(self):
def mean(self):
return np.where(self.alpha > 1, self.beta / (self.alpha - 1), np.inf)

def mode(self):
return self.beta / (self.alpha + 1)

def median(self):
return self.ppf(0.5)

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/laplace.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ def median(self):
def mean(self):
return self.mu

def mode(self):
return self.mu

def std(self):
return self.var() ** 0.5

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/logistic.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ def entropy(self):
def mean(self):
return self.mu

def mode(self):
return self.mu

def median(self):
return self.mu

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/lognormal.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ def entropy(self):
def mean(self):
return np.exp(self.mu + self.sigma**2 / 2)

def mode(self):
return np.exp(self.mu - self.sigma**2)

def median(self):
return np.exp(self.mu)

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/moyal.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ def entropy(self):
def mean(self):
return self.mu + self.sigma * (np.euler_gamma + np.log(2))

def mode(self):
return self.mu

def median(self):
return self.ppf(0.5)

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/negativebinomial.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ def entropy(self):
def mean(self):
return self.mu

def mode(self):
return np.where(self.n < 1, 0, np.floor((self.n - 1) * (1 - self.p) / self.p))

def median(self):
return self.ppf(0.5)

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/normal.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ def entropy(self):
def mean(self):
return self.mu

def mode(self):
return self.mu

def median(self):
return self.mu

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/poisson.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ def entropy(self):
def mean(self):
return self.mu

def mode(self):
return np.floor(self.mu)

def median(self):
return np.floor(self.mu + 1 / 3 - 0.02 / self.mu)

Expand Down
3 changes: 3 additions & 0 deletions preliz/distributions/triangular.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ def entropy(self):
def mean(self):
return (self.lower + self.c + self.upper) / 3

def mode(self):
return self.c

def median(self):
return np.where(
self.c >= (self.lower + self.upper) / 2,
Expand Down
4 changes: 3 additions & 1 deletion preliz/internal/optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .distribution_helper import init_vals as default_vals


def optimize_max_ent(dist, lower, upper, mass, none_idx, fixed):
def optimize_max_ent(dist, lower, upper, mass, none_idx, fixed, mode=None):
def prob_bound(params, dist, lower, upper, mass):
params = get_params(dist, params, none_idx, fixed)
dist._parametrization(**params)
Expand All @@ -19,6 +19,8 @@ def prob_bound(params, dist, lower, upper, mass):
cdf0 = dist.cdf(lower)
cdf1 = dist.cdf(upper)
loss = (cdf1 - cdf0) - mass
if mode is not None:
loss = loss - abs(dist.mode() - mode)
return loss

def entropy_loss(params, dist):
Expand Down
30 changes: 0 additions & 30 deletions preliz/tests/test_beta_mode.py

This file was deleted.

12 changes: 12 additions & 0 deletions preliz/tests/test_maxent.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,5 +180,17 @@ def test_maxent(dist, lower, upper, mass, support, result):
assert_allclose(dist.opt.x, result, atol=0.001)


def test_maxent_mode():
dist = Beta()
maxent(dist, 0.1, 0.7, 0.94, mode=0.3)
assert_almost_equal(dist.mode(), 0.3)
assert_almost_equal(dist.params, (2.7, 5.1), 1)

dist = Gamma()
maxent(dist, 0, 3, 0.8, mode=2)
assert_almost_equal(dist.mode(), 2)
assert_almost_equal(dist.params, (7.2, 3.1), 1)


def test_maxent_plot():
maxent(Normal(), plot_kwargs={"support": "restricted", "pointinterval": True})
2 changes: 0 additions & 2 deletions preliz/unidimensional/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from .beta_mode import beta_mode
from .combine import combine
from .combine_roulette import combine_roulette
from .maxent import maxent
Expand All @@ -8,7 +7,6 @@
from .roulette import Roulette

__all__ = [
"beta_mode",
"combine",
"combine_roulette",
"maxent",
Expand Down
Loading

0 comments on commit adec493

Please sign in to comment.