Families/ adding base version of exponential family#67
Families/ adding base version of exponential family#67domosedy wants to merge 5 commits intoPySATL:mainfrom
Conversation
There was a problem hiding this comment.
Change ExponentialFamily name to ContinuousExponentialClassFamily and other derivals
| PDF = "pdf" | ||
| CDF = "cdf" | ||
| PPF = "ppf" | ||
| CF = "char_func" | ||
| MEAN = "mean" | ||
| VAR = "var" | ||
| SKEW = "skewness" | ||
| KURT = "kurtosis" |
There was a problem hiding this comment.
We have EnumStr with the names of the characteristic. We should use it to avoid declarations in each file
| class ExponentialConjugateHyperparameters: | ||
| def __init__(self, alpha: Any, beta: int): | ||
| self.alpha = alpha | ||
| self.beta = beta | ||
|
|
||
| def __str__(self) -> str: | ||
| return f"alpha={self.alpha}, beta={self.beta}" |
There was a problem hiding this comment.
Use dataclass
@dataclass
class ExponentialConjugateHyperparameters:
self.alpha : Any
self.beta : int
def __str__(self) -> str:
return f"alpha={self.alpha}, beta={self.beta}"| def doesAccept(x: list[float] | float, support: list[tuple[float, float]]) -> bool: | ||
| if not hasattr(x, "__len__"): | ||
| x = [x] |
There was a problem hiding this comment.
Not list in the annotations but Iterable or Sequence
| def doesAccept(x: list[float] | float, support: list[tuple[float, float]]) -> bool: | ||
| if not hasattr(x, "__len__"): | ||
| x = [x] |
There was a problem hiding this comment.
Support can be list[ContinuousSupport] or just list[Interval1D]
| def accept_1D(x: float, borders: tuple[float, float]) -> bool: | ||
| left, right = borders | ||
| if abs(x) == 0 and (abs(left) == 0 or abs(right) == 0): | ||
| return False | ||
| return left <= x <= right |
There was a problem hiding this comment.
Could be replaced with Interval1D.contains
| def conjugate_sufficient( | ||
| theta: float, | ||
| ) -> list[Any]: |
There was a problem hiding this comment.
Accept multivariate parameter
| class SpacePredicate: | ||
| def __init__(self, predicate: Callable[[Any], bool]): | ||
| self._predicate = predicate | ||
|
|
||
| def accepts(self, x: Any) -> bool: | ||
| return self._predicate(x) | ||
|
|
There was a problem hiding this comment.
move to types.py as type allias
| class SpacePredicateArray(SpacePredicate): | ||
| def __init__(self, space: list[tuple[float, float]]): | ||
| SpacePredicate.__init__(self, lambda x: doesAccept(x, space)) | ||
| self._space = space |
There was a problem hiding this comment.
move to support.py; use interval_1d contains, or add doesAccept functionality to contains method
| parametrization: ExponentialFamilyParametrization, | ||
| ) -> Any: | ||
| alpha = parametrization.theta[0] | ||
| beta = parametrization.theta[1] | ||
|
|
There was a problem hiding this comment.
Accept multivariate parameter
| if not hasattr(theta, "__len__"): | ||
| theta = [theta] | ||
| parametrization = ExponentialFamilyParametrization(theta=theta) | ||
| return np.exp(np.dot(theta, alpha) + beta * self._log_partition(parametrization))[0] |
There was a problem hiding this comment.
Instead x[0] use x.item() for single element array
| alpha = parametrization.theta[0] | ||
| beta = parametrization.theta[1] | ||
|
|
||
| def pdf(theta: Any) -> Any: |
There was a problem hiding this comment.
use conjugate_sufficent instead
something like
np.exp(np.dot(conjugate_sufficient(theta), chi + [nu])).item()|
|
||
| def transform( | ||
| self, | ||
| transform_function: Callable[[Any], Any], |
There was a problem hiding this comment.
add docstring
transform function is mapping from user parametrization to canonical
| alpha = prior_hyper.alpha | ||
| beta = prior_hyper.beta |
There was a problem hiding this comment.
naming:
alpha -> effective_suff_stat_value
beta -> effective_sample_size
| self, | ||
| *, | ||
| log_partition: Callable[[ExponentialFamilyParametrization], float], | ||
| sufficient_statistics: Callable[[Any], Any], |
There was a problem hiding this comment.
Maybe enforce Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]]?
| def __init__( | ||
| self, | ||
| *, | ||
| log_partition: Callable[[ExponentialFamilyParametrization], float], |
There was a problem hiding this comment.
Since for density from Exponential class, one has to take product between vector of parameters and vector of statistics, we should
- either enforce both log_partition and sufficent_statistics had annotated arguments
- or leave checking correctness of argument order to user;
In the second case maybe it is better to use Callable[[npt.NDArray[np.float64]], np.float64]?
Currently, it seems that we have a kind of prototype to annotate natural parameters, but if want keep it, we should make possible to give arbitrary names to parameters.
There was a problem hiding this comment.
Note that NEF is actually a class of families where sufficient statistic is provided by identity function; Functionality of ExponentialClass can be derived from existing functionality for multiple parametrizations
For example add optional argument to conjugate_prior which will highlight parametrization name.
No description provided.