From 03a0267d957a01559848f376cd4cb66775a0b7da Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Fri, 17 Mar 2023 13:11:39 -0700 Subject: [PATCH 01/16] overhaul gp docstrings --- pymc/gp/gp.py | 252 +++++++++++++++++++++++++------------------------- 1 file changed, 127 insertions(+), 125 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index b2c415ee02..b149cbd431 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -111,10 +111,10 @@ class Latent(Base): Parameters ---------- - cov_func: None, 2D array, or instance of Covariance - The covariance function. Defaults to zero. - mean_func: None, instance of Mean - The mean function. Defaults to zero. + cov_func : 2D array, or instance of Covariance, default Zero + The covariance function. + mean_func : instance of Mean, default Zero + The mean function. Examples -------- @@ -171,14 +171,15 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - X: array-like - Function input values. - reparameterize: bool + X : array-like + Function input values. If one-dimensional, must be a column + vector with shape `(n, 1)`. + reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -233,15 +234,16 @@ def conditional(self, name, Xnew, given=None, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like - Function input values. - given: dict - Can optionally take as key value pairs: `X`, `y`, - and `gp`. See the section in the documentation on additive GP + Xnew : array-like + Function input values. If one-dimensional, must be a column + vector with shape `(n, 1)`. + given : dict, optional + Can take as key value pairs: `X`, `y`, + and `gp`. See the section in the documentation on additive GP models in PyMC for more information. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -260,7 +262,7 @@ class TP(Latent): The usage is nearly identical to that of `gp.Latent`. The differences are that it must be initialized with a degrees of freedom parameter, and - TP is not additive. Given a mean and covariance function, and a degrees of + TP is not additive. Given a mean and covariance function, and a degrees of freedom parameter, the function :math:`f(x)` is modeled as, .. math:: @@ -270,10 +272,10 @@ class TP(Latent): Parameters ---------- - scale_func : None, 2D array, or instance of Covariance - The scale function. Defaults to zero. - mean_func : None, instance of Mean - The mean function. Defaults to zero. + scale_func : 2D array, or instance of Covariance, default Zero + The scale function. + mean_func : instance of Mean, default Zero + The mean function. nu : float The degrees of freedom @@ -320,15 +322,19 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - X: array-like - Function input values. - reparameterize: bool + X : array-like + Function input values. If one-dimensional, must be a column + vector with shape `(n, 1)`. + reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. + jitter : scalar, default 1e-6 + A small correction added to the diagonal of positive semi-definite + covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to distribution constructor. + Extra keyword arguments that are passed to 'MvStudentT' distribution constructor. """ f = self._build_prior(name, X, reparameterize, jitter, **kwargs) @@ -361,15 +367,16 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like - Function input values. - jitter: scalar + Xnew : array-like + Function input values. If one-dimensional, must be a column + vector with shape `(n, 1)`. + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to `MvNormal` distribution + Extra keyword arguments that are passed to `MvStudentT` distribution constructor. """ @@ -388,14 +395,15 @@ class Marginal(Base): prior and additive noise. It has `marginal_likelihood`, `conditional` and `predict` methods. This GP implementation can be used to implement regression on data that is normally distributed. For more - information on the `prior` and `conditional` methods, see their docstrings. + information on the `marginal_likelihood`, `conditional` + and `predict` methods, see their docstrings. Parameters ---------- - cov_func: None, 2D array, or instance of Covariance - The covariance function. Defaults to zero. - mean_func: None, instance of Mean - The mean function. Defaults to zero. + cov_func : 2D array, or instance of Covariance, default Zero + The covariance function. + mean_func: instance of Mean, default Zero + The mean function. Examples -------- @@ -439,7 +447,7 @@ def marginal_likelihood( Returns the marginal likelihood distribution, given the input locations `X` and the data `y`. - This is integral over the product of the GP prior and a normal likelihood. + This is the integral over the product of the GP prior and a normal likelihood. .. math:: @@ -447,20 +455,20 @@ def marginal_likelihood( Parameters ---------- - name: string + name : str Name of the random variable - X: array-like + X : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - y: array-like + y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma: scalar, Variable, or Covariance + sigma : scalar, Variable, or Covariance Standard deviation of the Gaussian noise. Can also be a Covariance for non-white noise. - noise: scalar, Variable, or Covariance + noise : scalar, Variable, or Covariance, optional Previous parameterization of `sigma`. - jitter: scalar + jitter : scalar, 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -548,19 +556,18 @@ def conditional( Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - pred_noise: bool + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. - given: dict - Can optionally take as key value pairs: `X`, `y`, `sigma`, + given : dict, optional + Can take key value pairs: `X`, `y`, `sigma`, and `gp`. See the section in the documentation on additive GP models in PyMC for more information. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -589,20 +596,21 @@ def predict( Parameters ---------- - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - point: pymc.model.Point + point : pymc.model.Point, optional A specific point to condition on. - diag: bool + diag : bool, default False If `True`, return the diagonal instead of the full covariance - matrix. Default is `False`. - pred_noise: bool + matrix. + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. - given: dict - Same as `conditional` method. - jitter: scalar + given : dict, optional + Can take key value pairs: `X`, `y`, `sigma`, + and `gp`. See the section in the documentation on additive GP + models in PyMC for more information. + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. """ @@ -618,17 +626,18 @@ def _predict_at(self, Xnew, diag=False, pred_noise=False, given=None, jitter=JIT Parameters ---------- - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - diag: bool + diag : bool, default False If `True`, return the diagonal instead of the full covariance - matrix. Default is `False`. - pred_noise: bool + matrix. + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. - given: dict - Same as `conditional` method. + given : dict, optional + Can take key value pairs: `X`, `y`, `sigma`, + and `gp`. See the section in the documentation on additive GP + models in PyMC for more information. """ givens = self._get_given_vals(given) mu, cov = self._build_conditional(Xnew, pred_noise, diag, *givens, jitter) @@ -652,13 +661,12 @@ class MarginalApprox(Marginal): Parameters ---------- - cov_func: None, 2D array, or instance of Covariance - The covariance function. Defaults to zero. - mean_func: None, instance of Mean - The mean function. Defaults to zero. - approx: string + cov_func : 2D array, or instance of Covariance, default Zero + The covariance function. + mean_func : instance of Mean, default Zero + The mean function. + approx : str, default 'VFE' The approximation to use. Must be one of `VFE`, `FITC` or `DTC`. - Default is VFE. Examples -------- @@ -756,21 +764,21 @@ def marginal_likelihood( Parameters ---------- - name: string + name : str Name of the random variable - X: array-like + X : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - Xu: array-like + Xu : array-like The inducing points. Must have the same number of columns as `X`. - y: array-like + y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma: scalar, Variable + sigma : scalar, Variable Standard deviation of the Gaussian noise. - noise: scalar, Variable - Previous parameterization of `sigma` - jitter: scalar + noise : scalar, Variable, optional + Previous parameterization of `sigma`. + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -848,19 +856,18 @@ def conditional( Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - pred_noise: bool + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. - given: dict - Can optionally take as key value pairs: `X`, `Xu`, `y`, `sigma`, + given : dict, optional + Can take key value pairs: `X`, `Xu`, `y`, `sigma`, and `gp`. See the section in the documentation on additive GP models in PyMC for more information. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -892,20 +899,19 @@ class LatentKron(Base): Kronecker structured covariance, without reference to any noise or specific likelihood. The GP is constructed with the `prior` method, and the conditional GP over new input locations is constructed with - the `conditional` method. `conditional` and method. For more + the `conditional` method. For more information on these methods, see their docstrings. This GP implementation can be used to model a Gaussian process whose inputs cover evenly spaced grids on more than one dimension. `LatentKron` - is relies on the `KroneckerNormal` distribution, see its docstring + relies on the `KroneckerNormal` distribution, see its docstring for more information. Parameters ---------- - cov_funcs: list of Covariance objects + cov_funcs : list of Covariance objects, default [Zero] The covariance functions that compose the tensor (Kronecker) product. - Defaults to [zero]. - mean_func: None, instance of Mean - The mean function. Defaults to zero. + mean_func : instance of Mean, default Zero. + The mean function. Examples -------- @@ -963,14 +969,14 @@ def prior(self, name, Xs, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xs: list of array-like + Xs : list of array-like Function input values for each covariance function. Each entry must be passable to its respective covariance without error. The total covariance function is measured on the full grid `cartesian(*Xs)`. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -1024,12 +1030,12 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -1053,15 +1059,15 @@ class MarginalKron(Base): are measured on a full grid of inputs: `cartesian(*Xs)`. `MarginalKron` is based on the `KroneckerNormal` distribution, see its docstring for more information. For more information on the - `prior` and `conditional` methods, see their docstrings. + `marginal_likelihood`, `conditional` and `predict` methods, + see their docstrings. Parameters ---------- - cov_funcs: list of Covariance objects + cov_funcs : list of Covariance objects, default [Zero] The covariance functions that compose the tensor (Kronecker) product. - Defaults to [zero]. - mean_func: None, instance of Mean - The mean function. Defaults to zero. + mean_func : instance of Mean, default Zero + The mean function. Examples -------- @@ -1131,21 +1137,20 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xs: list of array-like + Xs : list of array-like Function input values for each covariance function. Each entry must be passable to its respective covariance without error. The total covariance function is measured on the full grid `cartesian(*Xs)`. - y: array-like + y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma: scalar, Variable + sigma : scalar, Variable Standard deviation of the white Gaussian noise. - is_observed: bool + is_observed : bool, default True Whether to set `y` as an `observed` variable in the `model`. - Default is `True`. **kwargs Extra keyword arguments that are passed to `KroneckerNormal` distribution constructor. @@ -1226,14 +1231,13 @@ def conditional(self, name, Xnew, pred_noise=False, diag=False, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - pred_noise: bool + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. **kwargs Extra keyword arguments that are passed to `MvNormal` distribution constructor. @@ -1249,17 +1253,16 @@ def predict(self, Xnew, point=None, diag=False, pred_noise=False, model=None): Parameters ---------- - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - point: pymc.model.Point + point : pymc.model.Point, optional A specific point to condition on. - diag: bool + diag : bool, default False If `True`, return the diagonal instead of the full covariance - matrix. Default is `False`. - pred_noise: bool + matrix. + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. """ mu, cov = self._predict_at(Xnew, diag, pred_noise) return replace_with_values([mu, cov], replacements=point, model=model) @@ -1271,15 +1274,14 @@ def _predict_at(self, Xnew, diag=False, pred_noise=False): Parameters ---------- - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - diag: bool + diag : bool, default False If `True`, return the diagonal instead of the full covariance - matrix. Default is `False`. - pred_noise: bool + matrix. + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. """ mu, cov = self._build_conditional(Xnew, diag, pred_noise) return mu, cov From 67925df692484939ef84199fa2f302993a0a632c Mon Sep 17 00:00:00 2001 From: Nathaniel Date: Sat, 18 Mar 2023 08:20:45 +0000 Subject: [PATCH 02/16] Fix a typo in the docstring of OderedLogistic (#6611) --- pymc/distributions/discrete.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymc/distributions/discrete.py b/pymc/distributions/discrete.py index f0af73ea66..ad52ff72b0 100644 --- a/pymc/distributions/discrete.py +++ b/pymc/distributions/discrete.py @@ -1572,7 +1572,7 @@ class OrderedLogistic: # Ordered logistic regression with pm.Model() as model: cutpoints = pm.Normal("cutpoints", mu=[-1,1], sigma=10, shape=2, - transform=pm.distributions.transforms.ordered) + transform=pm.distributions.transforms.univariate_ordered) y_ = pm.OrderedLogistic("y", cutpoints=cutpoints, eta=x, observed=y) idata = pm.sample() From 473c9528e56fc291e323e30082c8f4295dbd6149 Mon Sep 17 00:00:00 2001 From: Michal Raczycki <119355382+michaelraczycki@users.noreply.github.com> Date: Sun, 19 Mar 2023 18:28:37 +0300 Subject: [PATCH 03/16] Implement icdf for Univariate distribution (#6528) Also extended testing.check_icdf with skip_paradomain_outside_edge_test param --------- Co-authored-by: Michal Raczycki --- pymc/distributions/continuous.py | 5 +++++ pymc/testing.py | 31 +++++++++++++++----------- tests/distributions/test_continuous.py | 12 ++++++++-- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/pymc/distributions/continuous.py b/pymc/distributions/continuous.py index 9cffa3c111..b45eaeb96f 100644 --- a/pymc/distributions/continuous.py +++ b/pymc/distributions/continuous.py @@ -345,6 +345,11 @@ def logcdf(value, lower, upper): msg="lower <= upper", ) + def icdf(value, lower, upper): + res = lower + (upper - lower) * value + res = check_icdf_value(res, value) + return check_icdf_parameters(res, lower < upper) + @_default_transform.register(Uniform) def uniform_default_transform(op, rv): diff --git a/pymc/testing.py b/pymc/testing.py index ea3ccfc46f..3bb222222f 100644 --- a/pymc/testing.py +++ b/pymc/testing.py @@ -526,6 +526,7 @@ def check_icdf( pymc_dist: Distribution, paramdomains: Dict[str, Domain], scipy_icdf: Callable, + skip_paramdomain_outside_edge_test=False, decimal: Optional[int] = None, n_samples: int = 100, ) -> None: @@ -548,7 +549,7 @@ def check_icdf( paramdomains : Dictionary of Parameter : Domain pairs Supported domains of distribution parameters scipy_icdf : Scipy icdf method - Scipy icdf (ppp) method of equivalent pymc_dist distribution + Scipy icdf (ppf) method of equivalent pymc_dist distribution decimal : int, optional Level of precision with which pymc_dist and scipy_icdf are compared. Defaults to 6 for float64 and 3 for float32 @@ -557,6 +558,9 @@ def check_icdf( are compared between pymc and scipy methods. If n_samples is below the total number of combinations, a random subset is evaluated. Setting n_samples = -1, will return all possible combinations. Defaults to 100 + skip_paradomain_outside_edge_test : Bool + Whether to run test 2., which checks that pymc distribution icdf + returns nan for invalid parameter values outside the supported domain edge """ if decimal is None: @@ -586,19 +590,20 @@ def check_icdf( valid_params = {param: paramdomain.vals[0] for param, paramdomain in paramdomains.items()} valid_params["q"] = valid_value - # Test pymc distribution raises ParameterValueError for parameters outside the - # supported domain edges (excluding edges) - invalid_params = find_invalid_scalar_params(paramdomains) - for invalid_param, invalid_edges in invalid_params.items(): - for invalid_edge in invalid_edges: - if invalid_edge is None: - continue + if not skip_paramdomain_outside_edge_test: + # Test pymc distribution raises ParameterValueError for parameters outside the + # supported domain edges (excluding edges) + invalid_params = find_invalid_scalar_params(paramdomains) + for invalid_param, invalid_edges in invalid_params.items(): + for invalid_edge in invalid_edges: + if invalid_edge is None: + continue - point = valid_params.copy() - point[invalid_param] = invalid_edge - with pytest.raises(ParameterValueError): - pymc_icdf(**point) - pytest.fail(f"test_params={point}") + point = valid_params.copy() + point[invalid_param] = invalid_edge + with pytest.raises(ParameterValueError): + pymc_icdf(**point) + pytest.fail(f"test_params={point}") # Test that values below 0 or above 1 evaluate to nan invalid_values = find_invalid_scalar_params({"q": domain})["q"] diff --git a/tests/distributions/test_continuous.py b/tests/distributions/test_continuous.py index 8b4d2ef2b0..8b4484a66c 100644 --- a/tests/distributions/test_continuous.py +++ b/tests/distributions/test_continuous.py @@ -26,9 +26,9 @@ import pymc as pm -from pymc.distributions.continuous import Normal, get_tau_sigma, interpolated +from pymc.distributions.continuous import Normal, Uniform, get_tau_sigma, interpolated from pymc.distributions.dist_math import clipped_beta_rvs -from pymc.logprob.abstract import logcdf +from pymc.logprob.abstract import icdf, logcdf from pymc.logprob.joint_logprob import logp from pymc.logprob.utils import ParameterValueError from pymc.pytensorf import floatX @@ -176,6 +176,12 @@ def test_uniform(self): lambda value, lower, upper: st.uniform.logcdf(value, lower, upper - lower), skip_paramdomain_outside_edge_test=True, ) + check_icdf( + pm.Uniform, + {"lower": -Rplusunif, "upper": Rplusunif}, + lambda q, lower, upper: st.uniform.ppf(q=q, loc=lower, scale=upper - lower), + skip_paramdomain_outside_edge_test=True, + ) # Custom logp / logcdf check for invalid parameters invalid_dist = pm.Uniform.dist(lower=1, upper=0) with pytensor.config.change_flags(mode=Mode("py")): @@ -183,6 +189,8 @@ def test_uniform(self): logp(invalid_dist, np.array(0.5)).eval() with pytest.raises(ParameterValueError): logcdf(invalid_dist, np.array(0.5)).eval() + with pytest.raises(ParameterValueError): + icdf(invalid_dist, np.array(0.5)).eval() def test_triangular(self): check_logp( From 067d89bf8046a32038df4b4a73c81e81d4cb50b6 Mon Sep 17 00:00:00 2001 From: Chris Fonnesbeck Date: Wed, 22 Mar 2023 17:51:18 -0500 Subject: [PATCH 04/16] Improved docstring for predictions argument in sample_posterior_predictive (#6616) * Improved docstring for predictions argument in sample_posterior_predictive * Fix typos Co-authored-by: Ravin Kumar <7213793+canyon289@users.noreply.github.com> --------- Co-authored-by: Ravin Kumar <7213793+canyon289@users.noreply.github.com> --- pymc/sampling/forward.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pymc/sampling/forward.py b/pymc/sampling/forward.py index a03c598c9e..fd0260c3ae 100644 --- a/pymc/sampling/forward.py +++ b/pymc/sampling/forward.py @@ -481,8 +481,7 @@ def sample_posterior_predictive( Whether to automatically use :meth:`arviz.InferenceData.extend` to add the posterior predictive samples to ``trace`` or not. If True, ``trace`` is modified inplace but still returned. predictions : bool, default False - Choose the function used to convert the samples to inferencedata. See ``idata_kwargs`` - for more details. + Flag used to set the location of posterior predictive samples within the returned ``arviz.InferenceData`` object. If False, assumes samples are generated based on the fitting data to be used for posterior predictive checks, and samples are stored in the ``posterior_predictive``. If True, assumes samples are generated based on out-of-sample data as predictions, and samples are stored in the ``predictions`` group. idata_kwargs : dict, optional Keyword arguments for :func:`pymc.to_inference_data` if ``predictions=False`` or to :func:`pymc.predictions_to_inference_data` otherwise. From 2fcce433548a411f695d684ffb2d001a82a35f20 Mon Sep 17 00:00:00 2001 From: Gokul D Date: Thu, 23 Mar 2023 16:25:12 +0530 Subject: [PATCH 05/16] Added ICDF for the discrete uniform distribution. --- pymc/distributions/discrete.py | 9 +++++++++ tests/distributions/test_discrete.py | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/pymc/distributions/discrete.py b/pymc/distributions/discrete.py index ad52ff72b0..fa39ac0370 100644 --- a/pymc/distributions/discrete.py +++ b/pymc/distributions/discrete.py @@ -1058,6 +1058,15 @@ def logcdf(value, lower, upper): msg="lower <= upper", ) + def icdf(value, lower, upper): + res = pt.ceil(value * (upper - lower + 1)).astype("int64") + lower - 1 + res = check_icdf_value(res, value) + return check_icdf_parameters( + res, + lower <= upper, + msg="lower <= upper", + ) + class Categorical(Discrete): R""" diff --git a/tests/distributions/test_discrete.py b/tests/distributions/test_discrete.py index f3152268ea..78dbd7999b 100644 --- a/tests/distributions/test_discrete.py +++ b/tests/distributions/test_discrete.py @@ -29,7 +29,7 @@ import pymc as pm from pymc.distributions.discrete import Geometric, _OrderedLogistic, _OrderedProbit -from pymc.logprob.abstract import logcdf +from pymc.logprob.abstract import icdf, logcdf from pymc.logprob.joint_logprob import logp from pymc.logprob.utils import ParameterValueError from pymc.pytensorf import floatX @@ -118,6 +118,12 @@ def test_discrete_unif(self): Domain([-10, 0, 10], "int64"), {"lower": -Rplusdunif, "upper": Rplusdunif}, ) + check_icdf( + pm.DiscreteUniform, + {"lower": -Rplusdunif, "upper": Rplusdunif}, + lambda q, lower, upper: st.randint.ppf(q=q, low=lower, high=upper + 1), + skip_paramdomain_outside_edge_test=True, + ) # Custom logp / logcdf check for invalid parameters invalid_dist = pm.DiscreteUniform.dist(lower=1, upper=0) with pytensor.config.change_flags(mode=Mode("py")): @@ -125,6 +131,8 @@ def test_discrete_unif(self): logp(invalid_dist, 0.5).eval() with pytest.raises(ParameterValueError): logcdf(invalid_dist, 2).eval() + with pytest.raises(ParameterValueError): + icdf(invalid_dist, np.array(1)).eval() def test_geometric(self): check_logp( From bb4e7a13b751d6a87012e6334ed508ac127046d3 Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Fri, 17 Mar 2023 13:11:39 -0700 Subject: [PATCH 06/16] overhaul gp docstrings --- pymc/gp/gp.py | 252 +++++++++++++++++++++++++------------------------- 1 file changed, 127 insertions(+), 125 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index b2c415ee02..b149cbd431 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -111,10 +111,10 @@ class Latent(Base): Parameters ---------- - cov_func: None, 2D array, or instance of Covariance - The covariance function. Defaults to zero. - mean_func: None, instance of Mean - The mean function. Defaults to zero. + cov_func : 2D array, or instance of Covariance, default Zero + The covariance function. + mean_func : instance of Mean, default Zero + The mean function. Examples -------- @@ -171,14 +171,15 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - X: array-like - Function input values. - reparameterize: bool + X : array-like + Function input values. If one-dimensional, must be a column + vector with shape `(n, 1)`. + reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -233,15 +234,16 @@ def conditional(self, name, Xnew, given=None, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like - Function input values. - given: dict - Can optionally take as key value pairs: `X`, `y`, - and `gp`. See the section in the documentation on additive GP + Xnew : array-like + Function input values. If one-dimensional, must be a column + vector with shape `(n, 1)`. + given : dict, optional + Can take as key value pairs: `X`, `y`, + and `gp`. See the section in the documentation on additive GP models in PyMC for more information. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -260,7 +262,7 @@ class TP(Latent): The usage is nearly identical to that of `gp.Latent`. The differences are that it must be initialized with a degrees of freedom parameter, and - TP is not additive. Given a mean and covariance function, and a degrees of + TP is not additive. Given a mean and covariance function, and a degrees of freedom parameter, the function :math:`f(x)` is modeled as, .. math:: @@ -270,10 +272,10 @@ class TP(Latent): Parameters ---------- - scale_func : None, 2D array, or instance of Covariance - The scale function. Defaults to zero. - mean_func : None, instance of Mean - The mean function. Defaults to zero. + scale_func : 2D array, or instance of Covariance, default Zero + The scale function. + mean_func : instance of Mean, default Zero + The mean function. nu : float The degrees of freedom @@ -320,15 +322,19 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - X: array-like - Function input values. - reparameterize: bool + X : array-like + Function input values. If one-dimensional, must be a column + vector with shape `(n, 1)`. + reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. + jitter : scalar, default 1e-6 + A small correction added to the diagonal of positive semi-definite + covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to distribution constructor. + Extra keyword arguments that are passed to 'MvStudentT' distribution constructor. """ f = self._build_prior(name, X, reparameterize, jitter, **kwargs) @@ -361,15 +367,16 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like - Function input values. - jitter: scalar + Xnew : array-like + Function input values. If one-dimensional, must be a column + vector with shape `(n, 1)`. + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to `MvNormal` distribution + Extra keyword arguments that are passed to `MvStudentT` distribution constructor. """ @@ -388,14 +395,15 @@ class Marginal(Base): prior and additive noise. It has `marginal_likelihood`, `conditional` and `predict` methods. This GP implementation can be used to implement regression on data that is normally distributed. For more - information on the `prior` and `conditional` methods, see their docstrings. + information on the `marginal_likelihood`, `conditional` + and `predict` methods, see their docstrings. Parameters ---------- - cov_func: None, 2D array, or instance of Covariance - The covariance function. Defaults to zero. - mean_func: None, instance of Mean - The mean function. Defaults to zero. + cov_func : 2D array, or instance of Covariance, default Zero + The covariance function. + mean_func: instance of Mean, default Zero + The mean function. Examples -------- @@ -439,7 +447,7 @@ def marginal_likelihood( Returns the marginal likelihood distribution, given the input locations `X` and the data `y`. - This is integral over the product of the GP prior and a normal likelihood. + This is the integral over the product of the GP prior and a normal likelihood. .. math:: @@ -447,20 +455,20 @@ def marginal_likelihood( Parameters ---------- - name: string + name : str Name of the random variable - X: array-like + X : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - y: array-like + y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma: scalar, Variable, or Covariance + sigma : scalar, Variable, or Covariance Standard deviation of the Gaussian noise. Can also be a Covariance for non-white noise. - noise: scalar, Variable, or Covariance + noise : scalar, Variable, or Covariance, optional Previous parameterization of `sigma`. - jitter: scalar + jitter : scalar, 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -548,19 +556,18 @@ def conditional( Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - pred_noise: bool + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. - given: dict - Can optionally take as key value pairs: `X`, `y`, `sigma`, + given : dict, optional + Can take key value pairs: `X`, `y`, `sigma`, and `gp`. See the section in the documentation on additive GP models in PyMC for more information. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -589,20 +596,21 @@ def predict( Parameters ---------- - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - point: pymc.model.Point + point : pymc.model.Point, optional A specific point to condition on. - diag: bool + diag : bool, default False If `True`, return the diagonal instead of the full covariance - matrix. Default is `False`. - pred_noise: bool + matrix. + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. - given: dict - Same as `conditional` method. - jitter: scalar + given : dict, optional + Can take key value pairs: `X`, `y`, `sigma`, + and `gp`. See the section in the documentation on additive GP + models in PyMC for more information. + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. """ @@ -618,17 +626,18 @@ def _predict_at(self, Xnew, diag=False, pred_noise=False, given=None, jitter=JIT Parameters ---------- - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - diag: bool + diag : bool, default False If `True`, return the diagonal instead of the full covariance - matrix. Default is `False`. - pred_noise: bool + matrix. + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. - given: dict - Same as `conditional` method. + given : dict, optional + Can take key value pairs: `X`, `y`, `sigma`, + and `gp`. See the section in the documentation on additive GP + models in PyMC for more information. """ givens = self._get_given_vals(given) mu, cov = self._build_conditional(Xnew, pred_noise, diag, *givens, jitter) @@ -652,13 +661,12 @@ class MarginalApprox(Marginal): Parameters ---------- - cov_func: None, 2D array, or instance of Covariance - The covariance function. Defaults to zero. - mean_func: None, instance of Mean - The mean function. Defaults to zero. - approx: string + cov_func : 2D array, or instance of Covariance, default Zero + The covariance function. + mean_func : instance of Mean, default Zero + The mean function. + approx : str, default 'VFE' The approximation to use. Must be one of `VFE`, `FITC` or `DTC`. - Default is VFE. Examples -------- @@ -756,21 +764,21 @@ def marginal_likelihood( Parameters ---------- - name: string + name : str Name of the random variable - X: array-like + X : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - Xu: array-like + Xu : array-like The inducing points. Must have the same number of columns as `X`. - y: array-like + y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma: scalar, Variable + sigma : scalar, Variable Standard deviation of the Gaussian noise. - noise: scalar, Variable - Previous parameterization of `sigma` - jitter: scalar + noise : scalar, Variable, optional + Previous parameterization of `sigma`. + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -848,19 +856,18 @@ def conditional( Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - pred_noise: bool + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. - given: dict - Can optionally take as key value pairs: `X`, `Xu`, `y`, `sigma`, + given : dict, optional + Can take key value pairs: `X`, `Xu`, `y`, `sigma`, and `gp`. See the section in the documentation on additive GP models in PyMC for more information. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -892,20 +899,19 @@ class LatentKron(Base): Kronecker structured covariance, without reference to any noise or specific likelihood. The GP is constructed with the `prior` method, and the conditional GP over new input locations is constructed with - the `conditional` method. `conditional` and method. For more + the `conditional` method. For more information on these methods, see their docstrings. This GP implementation can be used to model a Gaussian process whose inputs cover evenly spaced grids on more than one dimension. `LatentKron` - is relies on the `KroneckerNormal` distribution, see its docstring + relies on the `KroneckerNormal` distribution, see its docstring for more information. Parameters ---------- - cov_funcs: list of Covariance objects + cov_funcs : list of Covariance objects, default [Zero] The covariance functions that compose the tensor (Kronecker) product. - Defaults to [zero]. - mean_func: None, instance of Mean - The mean function. Defaults to zero. + mean_func : instance of Mean, default Zero. + The mean function. Examples -------- @@ -963,14 +969,14 @@ def prior(self, name, Xs, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xs: list of array-like + Xs : list of array-like Function input values for each covariance function. Each entry must be passable to its respective covariance without error. The total covariance function is measured on the full grid `cartesian(*Xs)`. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -1024,12 +1030,12 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - jitter: scalar + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -1053,15 +1059,15 @@ class MarginalKron(Base): are measured on a full grid of inputs: `cartesian(*Xs)`. `MarginalKron` is based on the `KroneckerNormal` distribution, see its docstring for more information. For more information on the - `prior` and `conditional` methods, see their docstrings. + `marginal_likelihood`, `conditional` and `predict` methods, + see their docstrings. Parameters ---------- - cov_funcs: list of Covariance objects + cov_funcs : list of Covariance objects, default [Zero] The covariance functions that compose the tensor (Kronecker) product. - Defaults to [zero]. - mean_func: None, instance of Mean - The mean function. Defaults to zero. + mean_func : instance of Mean, default Zero + The mean function. Examples -------- @@ -1131,21 +1137,20 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xs: list of array-like + Xs : list of array-like Function input values for each covariance function. Each entry must be passable to its respective covariance without error. The total covariance function is measured on the full grid `cartesian(*Xs)`. - y: array-like + y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma: scalar, Variable + sigma : scalar, Variable Standard deviation of the white Gaussian noise. - is_observed: bool + is_observed : bool, default True Whether to set `y` as an `observed` variable in the `model`. - Default is `True`. **kwargs Extra keyword arguments that are passed to `KroneckerNormal` distribution constructor. @@ -1226,14 +1231,13 @@ def conditional(self, name, Xnew, pred_noise=False, diag=False, **kwargs): Parameters ---------- - name: string + name : str Name of the random variable - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - pred_noise: bool + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. **kwargs Extra keyword arguments that are passed to `MvNormal` distribution constructor. @@ -1249,17 +1253,16 @@ def predict(self, Xnew, point=None, diag=False, pred_noise=False, model=None): Parameters ---------- - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - point: pymc.model.Point + point : pymc.model.Point, optional A specific point to condition on. - diag: bool + diag : bool, default False If `True`, return the diagonal instead of the full covariance - matrix. Default is `False`. - pred_noise: bool + matrix. + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. """ mu, cov = self._predict_at(Xnew, diag, pred_noise) return replace_with_values([mu, cov], replacements=point, model=model) @@ -1271,15 +1274,14 @@ def _predict_at(self, Xnew, diag=False, pred_noise=False): Parameters ---------- - Xnew: array-like + Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - diag: bool + diag : bool, default False If `True`, return the diagonal instead of the full covariance - matrix. Default is `False`. - pred_noise: bool + matrix. + pred_noise : bool, default False Whether or not observation noise is included in the conditional. - Default is `False`. """ mu, cov = self._build_conditional(Xnew, diag, pred_noise) return mu, cov From 40d4c30f15f039bf30b0926c0a429f3182d22cdf Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Fri, 24 Mar 2023 11:02:34 -0700 Subject: [PATCH 07/16] revised updates to gp docstrings --- pymc/gp/gp.py | 73 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index b149cbd431..7a69576855 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -111,10 +111,10 @@ class Latent(Base): Parameters ---------- - cov_func : 2D array, or instance of Covariance, default Zero - The covariance function. - mean_func : instance of Mean, default Zero + mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. + cov_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + The covariance function. Examples -------- @@ -247,7 +247,7 @@ def conditional(self, name, Xnew, given=None, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to `MvNormal` distribution + Extra keyword arguments that are passed to :class:`~pymc.MvNormal` distribution constructor. """ givens = self._get_given_vals(given) @@ -272,10 +272,12 @@ class TP(Latent): Parameters ---------- - scale_func : 2D array, or instance of Covariance, default Zero - The scale function. - mean_func : instance of Mean, default Zero + mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. + scale_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + The covariance function. + cov_func : 2D array-like, or instance of Covariance, default None + Deprecated, previous version of "scale_func" nu : float The degrees of freedom @@ -334,7 +336,8 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to 'MvStudentT' distribution constructor. + Extra keyword arguments that are passed to :class:`~pymc.MvStudentT' + distribution constructor. """ f = self._build_prior(name, X, reparameterize, jitter, **kwargs) @@ -376,7 +379,7 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to `MvStudentT` distribution + Extra keyword arguments that are passed to :class:`~pymc.MvStudentT` distribution constructor. """ @@ -400,10 +403,10 @@ class Marginal(Base): Parameters ---------- - cov_func : 2D array, or instance of Covariance, default Zero - The covariance function. - mean_func: instance of Mean, default Zero + mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. + cov_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + The covariance function. Examples -------- @@ -471,8 +474,10 @@ def marginal_likelihood( jitter : scalar, 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. + is_observed : bool, default True + Deprecated. Whether to set `y` as an `observed` variable in the `model`. **kwargs - Extra keyword arguments that are passed to `MvNormal` distribution + Extra keyword arguments that are passed to :class:`~pymc.MvNormal` distribution constructor. """ sigma = _handle_sigma_noise_parameters(sigma=sigma, noise=noise) @@ -571,7 +576,7 @@ def conditional( A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to `MvNormal` distribution + Extra keyword arguments that are passed to :class:`~pymc.MvNormal` distribution constructor. """ @@ -599,7 +604,7 @@ def predict( Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - point : pymc.model.Point, optional + point : pymc.Point, optional A specific point to condition on. diag : bool, default False If `True`, return the diagonal instead of the full covariance @@ -613,6 +618,10 @@ def predict( jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. + model : Model, optional + Model with the Gaussian Process component for which predictions will + be generated. It is optional when inside a with context, otherwise + it is required. """ if given is None: given = {} @@ -661,10 +670,10 @@ class MarginalApprox(Marginal): Parameters ---------- - cov_func : 2D array, or instance of Covariance, default Zero - The covariance function. - mean_func : instance of Mean, default Zero + mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. + cov_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + The covariance function. approx : str, default 'VFE' The approximation to use. Must be one of `VFE`, `FITC` or `DTC`. @@ -782,7 +791,7 @@ def marginal_likelihood( A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to `MvNormal` distribution + Extra keyword arguments that are passed to :class:`~pymc.MvNormal` distribution constructor. """ @@ -871,7 +880,7 @@ def conditional( A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to `MvNormal` distribution + Extra keyword arguments that are passed to :class:`~pymc.MvNormal` distribution constructor. """ @@ -908,10 +917,10 @@ class LatentKron(Base): Parameters ---------- - cov_funcs : list of Covariance objects, default [Zero] - The covariance functions that compose the tensor (Kronecker) product. - mean_func : instance of Mean, default Zero. + mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. + cov_funcs : list of Covariance objects, default [~pymc.gp.cov.Constant] + The covariance functions that compose the tensor (Kronecker) product. Examples -------- @@ -1039,7 +1048,7 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to `MvNormal` distribution + Extra keyword arguments that are passed to :class:`~pymc.MvNormal` distribution constructor. """ mu, cov = self._build_conditional(Xnew, jitter) @@ -1064,10 +1073,10 @@ class MarginalKron(Base): Parameters ---------- - cov_funcs : list of Covariance objects, default [Zero] - The covariance functions that compose the tensor (Kronecker) product. - mean_func : instance of Mean, default Zero + mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. + cov_funcs : list of Covariance objects, default [~pymc.gp.cov.Constant] + The covariance functions that compose the tensor (Kronecker) product. Examples -------- @@ -1150,7 +1159,7 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): sigma : scalar, Variable Standard deviation of the white Gaussian noise. is_observed : bool, default True - Whether to set `y` as an `observed` variable in the `model`. + Deprecated. Whether to set `y` as an `observed` variable in the `model`. **kwargs Extra keyword arguments that are passed to `KroneckerNormal` distribution constructor. @@ -1239,7 +1248,7 @@ def conditional(self, name, Xnew, pred_noise=False, diag=False, **kwargs): pred_noise : bool, default False Whether or not observation noise is included in the conditional. **kwargs - Extra keyword arguments that are passed to `MvNormal` distribution + Extra keyword arguments that are passed to :class:`~pymc.MvNormal` distribution constructor. """ mu, cov = self._build_conditional(Xnew, diag, pred_noise) @@ -1256,13 +1265,17 @@ def predict(self, Xnew, point=None, diag=False, pred_noise=False, model=None): Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - point : pymc.model.Point, optional + point : pymc.Point, optional A specific point to condition on. diag : bool, default False If `True`, return the diagonal instead of the full covariance matrix. pred_noise : bool, default False Whether or not observation noise is included in the conditional. + model : Model, optional + Model with the Gaussian Process component for which predictions will + be generated. It is optional when inside a with context, otherwise + it is required. """ mu, cov = self._predict_at(Xnew, diag, pred_noise) return replace_with_values([mu, cov], replacements=point, model=model) From 2a62c0e47e53ed4d713321a15fede0578c1e2eae Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Fri, 24 Mar 2023 14:24:50 -0700 Subject: [PATCH 08/16] correcting errors introduced in last push --- pymc/gp/gp.py | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index d20365f08a..641ce7ddc1 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -171,7 +171,6 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name : str name : str Name of the random variable X : array-like @@ -236,7 +235,6 @@ def conditional(self, name, Xnew, given=None, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name : str name : str Name of the random variable Xnew : array-like @@ -334,7 +332,6 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name : str name : str Name of the random variable X : array-like @@ -385,7 +382,6 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): Parameters ---------- - name : str name : str Name of the random variable Xnew : array-like @@ -478,25 +474,19 @@ def marginal_likelihood( Parameters ---------- - name : str name : str Name of the random variable - X : array-like X : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - y : array-like y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable, or Covariance sigma : scalar, Variable, or Covariance Standard deviation of the Gaussian noise. Can also be a Covariance for non-white noise. - noise : scalar, Variable, or Covariance, optional noise : scalar, Variable, or Covariance, optional Previous parameterization of `sigma`. - jitter : scalar, 1e-6 jitter : scalar, 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. @@ -587,23 +577,17 @@ def conditional( Parameters ---------- - name : str name : str Name of the random variable - Xnew : array-like Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - pred_noise : bool, default False pred_noise : bool, default False Whether or not observation noise is included in the conditional. - given : dict, optional - Can take key value pairs: `X`, `y`, `sigma`, given : dict, optional Can take key value pairs: `X`, `y`, `sigma`, and `gp`. See the section in the documentation on additive GP models in PyMC for more information. - jitter : scalar, default 1e-6 jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. @@ -633,25 +617,16 @@ def predict( Parameters ---------- - Xnew : array-like Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. point : pymc.Point, optional A specific point to condition on. - diag : bool, default False diag : bool, default False If `True`, return the diagonal instead of the full covariance matrix. - pred_noise : bool, default False - matrix. pred_noise : bool, default False Whether or not observation noise is included in the conditional. - given : dict, optional - Can take key value pairs: `X`, `y`, `sigma`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. - jitter : scalar, default 1e-6 given : dict, optional Can take key value pairs: `X`, `y`, `sigma`, and `gp`. See the section in the documentation on additive GP @@ -676,7 +651,6 @@ def _predict_at(self, Xnew, diag=False, pred_noise=False, given=None, jitter=JIT Parameters ---------- - Xnew : array-like Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. @@ -1198,7 +1172,6 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable sigma : scalar, Variable Standard deviation of the white Gaussian noise. is_observed : bool, default True @@ -1305,18 +1278,14 @@ def predict(self, Xnew, point=None, diag=False, pred_noise=False, model=None): Parameters ---------- - Xnew : array-like Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. point : pymc.Point, optional A specific point to condition on. - diag : bool, default False diag : bool, default False If `True`, return the diagonal instead of the full covariance matrix. - pred_noise : bool, default False - matrix. pred_noise : bool, default False Whether or not observation noise is included in the conditional. model : Model, optional @@ -1334,16 +1303,12 @@ def _predict_at(self, Xnew, diag=False, pred_noise=False): Parameters ---------- - Xnew : array-like Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - diag : bool, default False diag : bool, default False If `True`, return the diagonal instead of the full covariance matrix. - pred_noise : bool, default False - matrix. pred_noise : bool, default False Whether or not observation noise is included in the conditional. """ From b94ba08d8d2ce459c5429be40d01d3ee178dbe7f Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Sat, 25 Mar 2023 09:58:56 -0700 Subject: [PATCH 09/16] second attempt to fix duplication errors --- pymc/gp/gp.py | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index 641ce7ddc1..19d0ddcf3d 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -173,14 +173,13 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): ---------- name : str Name of the random variable - X : array-like + X : array-like Function input values. If one-dimensional, must be a column - vector with shape `(n, 1)`. If one-dimensional, must be a column vector with shape `(n, 1)`. - reparameterize : bool, default True, default True + reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. - jitter : scalar, default 1e-6, default 1e-6 + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -240,17 +239,11 @@ def conditional(self, name, Xnew, given=None, jitter=JITTER_DEFAULT, **kwargs): Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - given : dict, optional - Can take as key value pairs: `X`, `y`, - and `gp`. See the section in the documentation on additive GP - Xnew : array-like - Function input values. If one-dimensional, must be a column - vector with shape `(n, 1)`. given : dict, optional Can take as key value pairs: `X`, `y`, and `gp`. See the section in the documentation on additive GP models in PyMC for more information. - jitter : scalar, default 1e-6, default 1e-6 + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -334,19 +327,15 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): ---------- name : str Name of the random variable - X : array-like + X : array-like Function input values. If one-dimensional, must be a column - vector with shape `(n, 1)`. If one-dimensional, must be a column vector with shape `(n, 1)`. - reparameterize : bool, default True, default True + reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. - jitter : scalar, default 1e-6 - A small correction added to the diagonal of positive semi-definite - covariance matrices to ensure numerical stability. **kwargs Extra keyword arguments that are passed to :class:`~pymc.MvStudentT' distribution constructor. @@ -384,11 +373,10 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): ---------- name : str Name of the random variable - Xnew : array-like + Xnew : array-like Function input values. If one-dimensional, must be a column - vector with shape `(n, 1)`. If one-dimensional, must be a column vector with shape `(n, 1)`. - jitter : scalar, default 1e-6, default 1e-6 + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -487,7 +475,7 @@ def marginal_likelihood( non-white noise. noise : scalar, Variable, or Covariance, optional Previous parameterization of `sigma`. - jitter : scalar, 1e-6 + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. is_observed : bool, default True @@ -1005,7 +993,7 @@ def prior(self, name, Xs, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to the `KroneckerNormal` + Extra keyword arguments that are passed to the :class:'~pymc.KroneckerNormal` distribution constructor. """ if len(Xs) != len(self.cov_funcs): @@ -1177,7 +1165,7 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): is_observed : bool, default True Deprecated. Whether to set `y` as an `observed` variable in the `model`. **kwargs - Extra keyword arguments that are passed to `KroneckerNormal` + Extra keyword arguments that are passed to :class:'~pymc.KroneckerNormal` distribution constructor. """ self._check_inputs(Xs, y) From 48a0292d4729074aa61d14f4a70c23f44a308c3a Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Sat, 25 Mar 2023 11:30:30 -0700 Subject: [PATCH 10/16] references to pymc.mvstudentt and similar weren't rendering correctly, fixed --- pymc/gp/gp.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index 19d0ddcf3d..9cfb1baf67 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -183,7 +183,8 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to distribution constructor. + Extra keyword arguments that are passed to :class:`~pymc.MvNormal` + distribution constructor. """ f = self._build_prior(name, X, reparameterize, jitter, **kwargs) @@ -337,7 +338,7 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to :class:`~pymc.MvStudentT' + Extra keyword arguments that are passed to :class:`~pymc.MvStudentT` distribution constructor. """ @@ -453,7 +454,6 @@ def marginal_likelihood( Returns the marginal likelihood distribution, given the input locations `X` and the data `y`. - This is the integral over the product of the GP prior and a normal likelihood. This is the integral over the product of the GP prior and a normal likelihood. .. math:: @@ -470,11 +470,11 @@ def marginal_likelihood( y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable, or Covariance + sigma : scalar, Variable, or Covariance, default ~pymc.gp.cov.WhiteNoise Standard deviation of the Gaussian noise. Can also be a Covariance for non-white noise. noise : scalar, Variable, or Covariance, optional - Previous parameterization of `sigma`. + Deprecated. Previous parameterization of `sigma`. jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. @@ -923,7 +923,7 @@ class LatentKron(Base): ---------- mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. - cov_funcs : list of Covariance objects, default [~pymc.gp.cov.Constant] + cov_funcs : list of Covariance, default [~pymc.gp.cov.Constant] The covariance functions that compose the tensor (Kronecker) product. Examples @@ -993,7 +993,7 @@ def prior(self, name, Xs, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to the :class:'~pymc.KroneckerNormal` + Extra keyword arguments that are passed to the :class:`~pymc.KroneckerNormal` distribution constructor. """ if len(Xs) != len(self.cov_funcs): @@ -1079,7 +1079,7 @@ class MarginalKron(Base): ---------- mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. - cov_funcs : list of Covariance objects, default [~pymc.gp.cov.Constant] + cov_funcs : list of Covariance, default [~pymc.gp.cov.Constant] The covariance functions that compose the tensor (Kronecker) product. Examples @@ -1165,7 +1165,7 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): is_observed : bool, default True Deprecated. Whether to set `y` as an `observed` variable in the `model`. **kwargs - Extra keyword arguments that are passed to :class:'~pymc.KroneckerNormal` + Extra keyword arguments that are passed to :class:`~pymc.KroneckerNormal` distribution constructor. """ self._check_inputs(Xs, y) From 955d4a9f8b23092b03fe8533a881476c58ec118d Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Wed, 29 Mar 2023 09:34:32 -0700 Subject: [PATCH 11/16] implementing Oriol's suggestions --- pymc/gp/gp.py | 77 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index 9cfb1baf67..e8a695787a 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -111,9 +111,9 @@ class Latent(Base): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. - cov_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + cov_func : 2D array-like, or Covariance, default ~pymc.gp.cov.Constant The covariance function. Examples @@ -179,7 +179,7 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -242,9 +242,9 @@ def conditional(self, name, Xnew, given=None, jitter=JITTER_DEFAULT, **kwargs): vector with shape `(n, 1)`. given : dict, optional Can take as key value pairs: `X`, `y`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. - jitter : scalar, default 1e-6 + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -264,7 +264,6 @@ class TP(Latent): The usage is nearly identical to that of `gp.Latent`. The differences are that it must be initialized with a degrees of freedom parameter, and TP is not additive. Given a mean and covariance function, and a degrees of - TP is not additive. Given a mean and covariance function, and a degrees of freedom parameter, the function :math:`f(x)` is modeled as, .. math:: @@ -274,11 +273,11 @@ class TP(Latent): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. - scale_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + scale_func : 2D array-like, or Covariance, default ~pymc.gp.cov.Constant The covariance function. - cov_func : 2D array-like, or instance of Covariance, default None + cov_func : 2D array-like, or Covariance, default None Deprecated, previous version of "scale_func" nu : float The degrees of freedom @@ -334,7 +333,7 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -377,7 +376,7 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -402,14 +401,12 @@ class Marginal(Base): implement regression on data that is normally distributed. For more information on the `marginal_likelihood`, `conditional` and `predict` methods, see their docstrings. - information on the `marginal_likelihood`, `conditional` - and `predict` methods, see their docstrings. Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. - cov_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + cov_func : 2D array-like, or Covariance, default ~pymc.gp.cov.Constant The covariance function. Examples @@ -470,12 +467,12 @@ def marginal_likelihood( y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable, or Covariance, default ~pymc.gp.cov.WhiteNoise + sigma : float, Variable, or Covariance, default ~pymc.gp.cov.WhiteNoise Standard deviation of the Gaussian noise. Can also be a Covariance for non-white noise. - noise : scalar, Variable, or Covariance, optional + noise : float, Variable, or Covariance, optional Deprecated. Previous parameterization of `sigma`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. is_observed : bool, default True @@ -574,9 +571,9 @@ def conditional( Whether or not observation noise is included in the conditional. given : dict, optional Can take key value pairs: `X`, `y`, `sigma`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. - jitter : scalar, default 1e-6 + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -617,9 +614,9 @@ def predict( Whether or not observation noise is included in the conditional. given : dict, optional Can take key value pairs: `X`, `y`, `sigma`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. - jitter : scalar, default 1e-6 + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. model : Model, optional @@ -649,8 +646,8 @@ def _predict_at(self, Xnew, diag=False, pred_noise=False, given=None, jitter=JIT Whether or not observation noise is included in the conditional. given : dict, optional Can take key value pairs: `X`, `y`, `sigma`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. """ givens = self._get_given_vals(given) mu, cov = self._build_conditional(Xnew, pred_noise, diag, *givens, jitter) @@ -674,9 +671,9 @@ class MarginalApprox(Marginal): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. - cov_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + cov_func : 2D array-like, or Covariance, default ~pymc.gp.cov.Constant The covariance function. approx : str, default 'VFE' The approximation to use. Must be one of `VFE`, `FITC` or `DTC`. @@ -787,11 +784,11 @@ def marginal_likelihood( y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable + sigma : float, Variable Standard deviation of the Gaussian noise. - noise : scalar, Variable, optional + noise : float, Variable, optional Previous parameterization of `sigma`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -878,9 +875,9 @@ def conditional( Whether or not observation noise is included in the conditional. given : dict, optional Can take key value pairs: `X`, `Xu`, `y`, `sigma`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. - jitter : scalar, default 1e-6 + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -921,7 +918,7 @@ class LatentKron(Base): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. cov_funcs : list of Covariance, default [~pymc.gp.cov.Constant] The covariance functions that compose the tensor (Kronecker) product. @@ -989,7 +986,7 @@ def prior(self, name, Xs, jitter=JITTER_DEFAULT, **kwargs): must be passable to its respective covariance without error. The total covariance function is measured on the full grid `cartesian(*Xs)`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -1048,7 +1045,7 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -1077,7 +1074,7 @@ class MarginalKron(Base): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. cov_funcs : list of Covariance, default [~pymc.gp.cov.Constant] The covariance functions that compose the tensor (Kronecker) product. @@ -1160,7 +1157,7 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable + sigma : float, Variable Standard deviation of the white Gaussian noise. is_observed : bool, default True Deprecated. Whether to set `y` as an `observed` variable in the `model`. From e09c17a8f58d4d57b658d5c1bab54a9127c61be0 Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Sat, 25 Mar 2023 09:58:56 -0700 Subject: [PATCH 12/16] second attempt to fix duplication errors --- pymc/gp/gp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index 7a69576855..b93ccde935 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -471,7 +471,7 @@ def marginal_likelihood( non-white noise. noise : scalar, Variable, or Covariance, optional Previous parameterization of `sigma`. - jitter : scalar, 1e-6 + jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. is_observed : bool, default True @@ -989,7 +989,7 @@ def prior(self, name, Xs, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to the `KroneckerNormal` + Extra keyword arguments that are passed to the :class:'~pymc.KroneckerNormal` distribution constructor. """ if len(Xs) != len(self.cov_funcs): @@ -1161,7 +1161,7 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): is_observed : bool, default True Deprecated. Whether to set `y` as an `observed` variable in the `model`. **kwargs - Extra keyword arguments that are passed to `KroneckerNormal` + Extra keyword arguments that are passed to :class:'~pymc.KroneckerNormal` distribution constructor. """ self._check_inputs(Xs, y) From 031ee71de4bb11d3dc3351c35ac5d62c828dc384 Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Sat, 25 Mar 2023 11:30:30 -0700 Subject: [PATCH 13/16] references to pymc.mvstudentt and similar weren't rendering correctly, fixed --- pymc/gp/gp.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index b93ccde935..b3e5ff969e 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -183,7 +183,8 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to distribution constructor. + Extra keyword arguments that are passed to :class:`~pymc.MvNormal` + distribution constructor. """ f = self._build_prior(name, X, reparameterize, jitter, **kwargs) @@ -336,7 +337,7 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to :class:`~pymc.MvStudentT' + Extra keyword arguments that are passed to :class:`~pymc.MvStudentT` distribution constructor. """ @@ -466,11 +467,11 @@ def marginal_likelihood( y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable, or Covariance + sigma : scalar, Variable, or Covariance, default ~pymc.gp.cov.WhiteNoise Standard deviation of the Gaussian noise. Can also be a Covariance for non-white noise. noise : scalar, Variable, or Covariance, optional - Previous parameterization of `sigma`. + Deprecated. Previous parameterization of `sigma`. jitter : scalar, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. @@ -919,7 +920,7 @@ class LatentKron(Base): ---------- mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. - cov_funcs : list of Covariance objects, default [~pymc.gp.cov.Constant] + cov_funcs : list of Covariance, default [~pymc.gp.cov.Constant] The covariance functions that compose the tensor (Kronecker) product. Examples @@ -989,7 +990,7 @@ def prior(self, name, Xs, jitter=JITTER_DEFAULT, **kwargs): A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs - Extra keyword arguments that are passed to the :class:'~pymc.KroneckerNormal` + Extra keyword arguments that are passed to the :class:`~pymc.KroneckerNormal` distribution constructor. """ if len(Xs) != len(self.cov_funcs): @@ -1075,7 +1076,7 @@ class MarginalKron(Base): ---------- mean_func : instance of Mean, default ~pymc.gp.mean.Zero The mean function. - cov_funcs : list of Covariance objects, default [~pymc.gp.cov.Constant] + cov_funcs : list of Covariance, default [~pymc.gp.cov.Constant] The covariance functions that compose the tensor (Kronecker) product. Examples @@ -1161,7 +1162,7 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): is_observed : bool, default True Deprecated. Whether to set `y` as an `observed` variable in the `model`. **kwargs - Extra keyword arguments that are passed to :class:'~pymc.KroneckerNormal` + Extra keyword arguments that are passed to :class:`~pymc.KroneckerNormal` distribution constructor. """ self._check_inputs(Xs, y) From b5061711992de3cae11f6b5ebca3fe39adc7460a Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Wed, 29 Mar 2023 09:34:32 -0700 Subject: [PATCH 14/16] implementing Oriol's suggestions --- pymc/gp/gp.py | 74 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/pymc/gp/gp.py b/pymc/gp/gp.py index b3e5ff969e..e8a695787a 100644 --- a/pymc/gp/gp.py +++ b/pymc/gp/gp.py @@ -111,9 +111,9 @@ class Latent(Base): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. - cov_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + cov_func : 2D array-like, or Covariance, default ~pymc.gp.cov.Constant The covariance function. Examples @@ -179,7 +179,7 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -242,9 +242,9 @@ def conditional(self, name, Xnew, given=None, jitter=JITTER_DEFAULT, **kwargs): vector with shape `(n, 1)`. given : dict, optional Can take as key value pairs: `X`, `y`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. - jitter : scalar, default 1e-6 + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -273,11 +273,11 @@ class TP(Latent): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. - scale_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + scale_func : 2D array-like, or Covariance, default ~pymc.gp.cov.Constant The covariance function. - cov_func : 2D array-like, or instance of Covariance, default None + cov_func : 2D array-like, or Covariance, default None Deprecated, previous version of "scale_func" nu : float The degrees of freedom @@ -333,7 +333,7 @@ def prior(self, name, X, reparameterize=True, jitter=JITTER_DEFAULT, **kwargs): reparameterize : bool, default True Reparameterize the distribution by rotating the random variable by the Cholesky factor of the covariance matrix. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -376,7 +376,7 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -404,9 +404,9 @@ class Marginal(Base): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. - cov_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + cov_func : 2D array-like, or Covariance, default ~pymc.gp.cov.Constant The covariance function. Examples @@ -467,12 +467,12 @@ def marginal_likelihood( y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable, or Covariance, default ~pymc.gp.cov.WhiteNoise + sigma : float, Variable, or Covariance, default ~pymc.gp.cov.WhiteNoise Standard deviation of the Gaussian noise. Can also be a Covariance for non-white noise. - noise : scalar, Variable, or Covariance, optional + noise : float, Variable, or Covariance, optional Deprecated. Previous parameterization of `sigma`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. is_observed : bool, default True @@ -571,9 +571,9 @@ def conditional( Whether or not observation noise is included in the conditional. given : dict, optional Can take key value pairs: `X`, `y`, `sigma`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. - jitter : scalar, default 1e-6 + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -614,9 +614,9 @@ def predict( Whether or not observation noise is included in the conditional. given : dict, optional Can take key value pairs: `X`, `y`, `sigma`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. - jitter : scalar, default 1e-6 + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. model : Model, optional @@ -646,8 +646,8 @@ def _predict_at(self, Xnew, diag=False, pred_noise=False, given=None, jitter=JIT Whether or not observation noise is included in the conditional. given : dict, optional Can take key value pairs: `X`, `y`, `sigma`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. """ givens = self._get_given_vals(given) mu, cov = self._build_conditional(Xnew, pred_noise, diag, *givens, jitter) @@ -671,9 +671,9 @@ class MarginalApprox(Marginal): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. - cov_func : 2D array-like, or instance of Covariance, default ~pymc.gp.cov.Constant + cov_func : 2D array-like, or Covariance, default ~pymc.gp.cov.Constant The covariance function. approx : str, default 'VFE' The approximation to use. Must be one of `VFE`, `FITC` or `DTC`. @@ -784,11 +784,11 @@ def marginal_likelihood( y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable + sigma : float, Variable Standard deviation of the Gaussian noise. - noise : scalar, Variable, optional + noise : float, Variable, optional Previous parameterization of `sigma`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -875,9 +875,9 @@ def conditional( Whether or not observation noise is included in the conditional. given : dict, optional Can take key value pairs: `X`, `Xu`, `y`, `sigma`, - and `gp`. See the section in the documentation on additive GP - models in PyMC for more information. - jitter : scalar, default 1e-6 + and `gp`. See the :ref:`section ` in the documentation + on additive GP models in pymc for more information. + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -918,7 +918,7 @@ class LatentKron(Base): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. cov_funcs : list of Covariance, default [~pymc.gp.cov.Constant] The covariance functions that compose the tensor (Kronecker) product. @@ -986,7 +986,7 @@ def prior(self, name, Xs, jitter=JITTER_DEFAULT, **kwargs): must be passable to its respective covariance without error. The total covariance function is measured on the full grid `cartesian(*Xs)`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -1045,7 +1045,7 @@ def conditional(self, name, Xnew, jitter=JITTER_DEFAULT, **kwargs): Xnew : array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. - jitter : scalar, default 1e-6 + jitter : float, default 1e-6 A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. **kwargs @@ -1074,7 +1074,7 @@ class MarginalKron(Base): Parameters ---------- - mean_func : instance of Mean, default ~pymc.gp.mean.Zero + mean_func : Mean, default ~pymc.gp.mean.Zero The mean function. cov_funcs : list of Covariance, default [~pymc.gp.cov.Constant] The covariance functions that compose the tensor (Kronecker) product. @@ -1157,7 +1157,7 @@ def marginal_likelihood(self, name, Xs, y, sigma, is_observed=True, **kwargs): y : array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. - sigma : scalar, Variable + sigma : float, Variable Standard deviation of the white Gaussian noise. is_observed : bool, default True Deprecated. Whether to set `y` as an `observed` variable in the `model`. From b528822293f2fbef1a158b651ab1f1c801b018d2 Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Sat, 1 Apr 2023 22:28:46 -0700 Subject: [PATCH 15/16] Revert "Implement icdf for Univariate distribution (#6528)" This reverts commit 473c9528e56fc291e323e30082c8f4295dbd6149. --- pymc/distributions/continuous.py | 5 ----- pymc/testing.py | 31 +++++++++++--------------- tests/distributions/test_continuous.py | 12 ++-------- 3 files changed, 15 insertions(+), 33 deletions(-) diff --git a/pymc/distributions/continuous.py b/pymc/distributions/continuous.py index b45eaeb96f..9cffa3c111 100644 --- a/pymc/distributions/continuous.py +++ b/pymc/distributions/continuous.py @@ -345,11 +345,6 @@ def logcdf(value, lower, upper): msg="lower <= upper", ) - def icdf(value, lower, upper): - res = lower + (upper - lower) * value - res = check_icdf_value(res, value) - return check_icdf_parameters(res, lower < upper) - @_default_transform.register(Uniform) def uniform_default_transform(op, rv): diff --git a/pymc/testing.py b/pymc/testing.py index 3bb222222f..ea3ccfc46f 100644 --- a/pymc/testing.py +++ b/pymc/testing.py @@ -526,7 +526,6 @@ def check_icdf( pymc_dist: Distribution, paramdomains: Dict[str, Domain], scipy_icdf: Callable, - skip_paramdomain_outside_edge_test=False, decimal: Optional[int] = None, n_samples: int = 100, ) -> None: @@ -549,7 +548,7 @@ def check_icdf( paramdomains : Dictionary of Parameter : Domain pairs Supported domains of distribution parameters scipy_icdf : Scipy icdf method - Scipy icdf (ppf) method of equivalent pymc_dist distribution + Scipy icdf (ppp) method of equivalent pymc_dist distribution decimal : int, optional Level of precision with which pymc_dist and scipy_icdf are compared. Defaults to 6 for float64 and 3 for float32 @@ -558,9 +557,6 @@ def check_icdf( are compared between pymc and scipy methods. If n_samples is below the total number of combinations, a random subset is evaluated. Setting n_samples = -1, will return all possible combinations. Defaults to 100 - skip_paradomain_outside_edge_test : Bool - Whether to run test 2., which checks that pymc distribution icdf - returns nan for invalid parameter values outside the supported domain edge """ if decimal is None: @@ -590,20 +586,19 @@ def check_icdf( valid_params = {param: paramdomain.vals[0] for param, paramdomain in paramdomains.items()} valid_params["q"] = valid_value - if not skip_paramdomain_outside_edge_test: - # Test pymc distribution raises ParameterValueError for parameters outside the - # supported domain edges (excluding edges) - invalid_params = find_invalid_scalar_params(paramdomains) - for invalid_param, invalid_edges in invalid_params.items(): - for invalid_edge in invalid_edges: - if invalid_edge is None: - continue + # Test pymc distribution raises ParameterValueError for parameters outside the + # supported domain edges (excluding edges) + invalid_params = find_invalid_scalar_params(paramdomains) + for invalid_param, invalid_edges in invalid_params.items(): + for invalid_edge in invalid_edges: + if invalid_edge is None: + continue - point = valid_params.copy() - point[invalid_param] = invalid_edge - with pytest.raises(ParameterValueError): - pymc_icdf(**point) - pytest.fail(f"test_params={point}") + point = valid_params.copy() + point[invalid_param] = invalid_edge + with pytest.raises(ParameterValueError): + pymc_icdf(**point) + pytest.fail(f"test_params={point}") # Test that values below 0 or above 1 evaluate to nan invalid_values = find_invalid_scalar_params({"q": domain})["q"] diff --git a/tests/distributions/test_continuous.py b/tests/distributions/test_continuous.py index 8b4484a66c..8b4d2ef2b0 100644 --- a/tests/distributions/test_continuous.py +++ b/tests/distributions/test_continuous.py @@ -26,9 +26,9 @@ import pymc as pm -from pymc.distributions.continuous import Normal, Uniform, get_tau_sigma, interpolated +from pymc.distributions.continuous import Normal, get_tau_sigma, interpolated from pymc.distributions.dist_math import clipped_beta_rvs -from pymc.logprob.abstract import icdf, logcdf +from pymc.logprob.abstract import logcdf from pymc.logprob.joint_logprob import logp from pymc.logprob.utils import ParameterValueError from pymc.pytensorf import floatX @@ -176,12 +176,6 @@ def test_uniform(self): lambda value, lower, upper: st.uniform.logcdf(value, lower, upper - lower), skip_paramdomain_outside_edge_test=True, ) - check_icdf( - pm.Uniform, - {"lower": -Rplusunif, "upper": Rplusunif}, - lambda q, lower, upper: st.uniform.ppf(q=q, loc=lower, scale=upper - lower), - skip_paramdomain_outside_edge_test=True, - ) # Custom logp / logcdf check for invalid parameters invalid_dist = pm.Uniform.dist(lower=1, upper=0) with pytensor.config.change_flags(mode=Mode("py")): @@ -189,8 +183,6 @@ def test_uniform(self): logp(invalid_dist, np.array(0.5)).eval() with pytest.raises(ParameterValueError): logcdf(invalid_dist, np.array(0.5)).eval() - with pytest.raises(ParameterValueError): - icdf(invalid_dist, np.array(0.5)).eval() def test_triangular(self): check_logp( From efa315cc264ba840fd2a3623a0ba2cb6fcd5549a Mon Sep 17 00:00:00 2001 From: Daniel Saunders Date: Sat, 1 Apr 2023 22:32:53 -0700 Subject: [PATCH 16/16] Revert "Revert "Implement icdf for Univariate distribution (#6528)"" This reverts commit 86f36031759620a124ba5b46faf9305d2b160b71. --- pymc/distributions/continuous.py | 5 +++++ pymc/testing.py | 31 +++++++++++++++----------- tests/distributions/test_continuous.py | 12 ++++++++-- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/pymc/distributions/continuous.py b/pymc/distributions/continuous.py index 9cffa3c111..b45eaeb96f 100644 --- a/pymc/distributions/continuous.py +++ b/pymc/distributions/continuous.py @@ -345,6 +345,11 @@ def logcdf(value, lower, upper): msg="lower <= upper", ) + def icdf(value, lower, upper): + res = lower + (upper - lower) * value + res = check_icdf_value(res, value) + return check_icdf_parameters(res, lower < upper) + @_default_transform.register(Uniform) def uniform_default_transform(op, rv): diff --git a/pymc/testing.py b/pymc/testing.py index ea3ccfc46f..3bb222222f 100644 --- a/pymc/testing.py +++ b/pymc/testing.py @@ -526,6 +526,7 @@ def check_icdf( pymc_dist: Distribution, paramdomains: Dict[str, Domain], scipy_icdf: Callable, + skip_paramdomain_outside_edge_test=False, decimal: Optional[int] = None, n_samples: int = 100, ) -> None: @@ -548,7 +549,7 @@ def check_icdf( paramdomains : Dictionary of Parameter : Domain pairs Supported domains of distribution parameters scipy_icdf : Scipy icdf method - Scipy icdf (ppp) method of equivalent pymc_dist distribution + Scipy icdf (ppf) method of equivalent pymc_dist distribution decimal : int, optional Level of precision with which pymc_dist and scipy_icdf are compared. Defaults to 6 for float64 and 3 for float32 @@ -557,6 +558,9 @@ def check_icdf( are compared between pymc and scipy methods. If n_samples is below the total number of combinations, a random subset is evaluated. Setting n_samples = -1, will return all possible combinations. Defaults to 100 + skip_paradomain_outside_edge_test : Bool + Whether to run test 2., which checks that pymc distribution icdf + returns nan for invalid parameter values outside the supported domain edge """ if decimal is None: @@ -586,19 +590,20 @@ def check_icdf( valid_params = {param: paramdomain.vals[0] for param, paramdomain in paramdomains.items()} valid_params["q"] = valid_value - # Test pymc distribution raises ParameterValueError for parameters outside the - # supported domain edges (excluding edges) - invalid_params = find_invalid_scalar_params(paramdomains) - for invalid_param, invalid_edges in invalid_params.items(): - for invalid_edge in invalid_edges: - if invalid_edge is None: - continue + if not skip_paramdomain_outside_edge_test: + # Test pymc distribution raises ParameterValueError for parameters outside the + # supported domain edges (excluding edges) + invalid_params = find_invalid_scalar_params(paramdomains) + for invalid_param, invalid_edges in invalid_params.items(): + for invalid_edge in invalid_edges: + if invalid_edge is None: + continue - point = valid_params.copy() - point[invalid_param] = invalid_edge - with pytest.raises(ParameterValueError): - pymc_icdf(**point) - pytest.fail(f"test_params={point}") + point = valid_params.copy() + point[invalid_param] = invalid_edge + with pytest.raises(ParameterValueError): + pymc_icdf(**point) + pytest.fail(f"test_params={point}") # Test that values below 0 or above 1 evaluate to nan invalid_values = find_invalid_scalar_params({"q": domain})["q"] diff --git a/tests/distributions/test_continuous.py b/tests/distributions/test_continuous.py index 8b4d2ef2b0..8b4484a66c 100644 --- a/tests/distributions/test_continuous.py +++ b/tests/distributions/test_continuous.py @@ -26,9 +26,9 @@ import pymc as pm -from pymc.distributions.continuous import Normal, get_tau_sigma, interpolated +from pymc.distributions.continuous import Normal, Uniform, get_tau_sigma, interpolated from pymc.distributions.dist_math import clipped_beta_rvs -from pymc.logprob.abstract import logcdf +from pymc.logprob.abstract import icdf, logcdf from pymc.logprob.joint_logprob import logp from pymc.logprob.utils import ParameterValueError from pymc.pytensorf import floatX @@ -176,6 +176,12 @@ def test_uniform(self): lambda value, lower, upper: st.uniform.logcdf(value, lower, upper - lower), skip_paramdomain_outside_edge_test=True, ) + check_icdf( + pm.Uniform, + {"lower": -Rplusunif, "upper": Rplusunif}, + lambda q, lower, upper: st.uniform.ppf(q=q, loc=lower, scale=upper - lower), + skip_paramdomain_outside_edge_test=True, + ) # Custom logp / logcdf check for invalid parameters invalid_dist = pm.Uniform.dist(lower=1, upper=0) with pytensor.config.change_flags(mode=Mode("py")): @@ -183,6 +189,8 @@ def test_uniform(self): logp(invalid_dist, np.array(0.5)).eval() with pytest.raises(ParameterValueError): logcdf(invalid_dist, np.array(0.5)).eval() + with pytest.raises(ParameterValueError): + icdf(invalid_dist, np.array(0.5)).eval() def test_triangular(self): check_logp(