def test_density_dist_default_moment_multivariate(with_random, size): def _random(mu, rng=None, size=None): return rng.normal(mu, scale=1, size=to_tuple(size) + mu.shape) if with_random: random = _random else: random = None mu_val = np.random.normal(loc=2, scale=1, size=5).astype(aesara.config.floatX) with pm.Model(): mu = pm.Normal("mu", size=5) a = pm.DensityDist("a", mu, random=random, ndims_params=[1], ndim_supp=1, size=size) if with_random: evaled_moment = get_moment(a).eval({mu: mu_val}) assert evaled_moment.shape == to_tuple(size) + (5, ) assert np.all(evaled_moment == 0) else: with pytest.raises( TypeError, match= "Cannot safely infer the size of a multivariate random variable's moment.", ): evaled_moment = get_moment(a).eval({mu: mu_val})
def test_spawn_densitydist_function(): with pm.Model() as model: mu = pm.Normal("mu", 0, 1) def func(x): return -2 * (x ** 2).sum() obs = pm.DensityDist("density_dist", logp=func, observed=np.random.randn(100)) pm.sample(draws=10, tune=10, step=pm.Metropolis(), cores=2, mp_ctx="spawn")
def test_density_dist_custom_moment_multivariate(size): def moment(rv, size, mu): return (at.ones(size)[..., None] * mu).astype(rv.dtype) mu_val = np.random.normal(loc=2, scale=1, size=5).astype(aesara.config.floatX) with pm.Model(): mu = pm.Normal("mu", size=5) a = pm.DensityDist("a", mu, get_moment=moment, ndims_params=[1], ndim_supp=1, size=size) evaled_moment = get_moment(a).eval({mu: mu_val}) assert evaled_moment.shape == to_tuple(size) + (5,) assert np.all(evaled_moment == mu_val)
def test_density_dist_custom_moment_univariate(size): def moment(rv, size, mu): return (at.ones(size) * mu).astype(rv.dtype) mu_val = np.array(np.random.normal(loc=2, scale=1)).astype(aesara.config.floatX) with pm.Model(): mu = pm.Normal("mu") a = pm.DensityDist("a", mu, get_moment=moment, size=size) evaled_moment = get_moment(a).eval({mu: mu_val}) assert evaled_moment.shape == to_tuple(size) assert np.all(evaled_moment == mu_val)
def test_spawn_densitydist_bound_method(): N = 100 with pm.Model() as model: mu = pm.Normal("mu", 0, 1) normal_dist = pm.Normal.dist(mu, 1, size=N) def logp(x): out = pm.logp(normal_dist, x) return out obs = pm.DensityDist("density_dist", logp=logp, observed=np.random.randn(N), size=N) pm.sample(draws=10, tune=10, step=pm.Metropolis(), cores=2, mp_ctx="spawn")
def test_multiple_observed_rv(): "Test previously buggy multi-observed RV comparison code." y1_data = np.random.randn(10) y2_data = np.random.randn(100) with pm.Model() as model: mu = pm.Normal("mu") x = pm.DensityDist( # pylint: disable=unused-variable "x", mu, logp=lambda value, mu: pm.Normal.logp(value, mu, 1.0), observed=0.1 ) assert not model["x"] == model["mu"] assert model["x"] == model["x"] assert model["x"] in model.observed_RVs assert not model["x"] in model.value_vars
def test_density_dist(self): obs = np.random.normal(-1, 0.1, size=10) with pm.Model(): mu = pm.Normal("mu", 0, 1) sd = pm.HalfNormal("sd", 1e-6) a = pm.DensityDist( "a", mu, sd, random=lambda mu, sd, rng=None, size=None: rng.normal(loc=mu, scale=sd, size=size), observed=obs, ) prior = pm.sample_prior_predictive(return_inferencedata=False) npt.assert_almost_equal((prior["a"] - prior["mu"][..., None]).mean(), 0, decimal=3)
def test_multiple_observed_rv_without_observations(self): with pm.Model(): mu = pm.Normal("mu") x = pm.DensityDist( # pylint: disable=unused-variable "x", mu, logp=lambda value, mu: pm.Normal.logp(value, mu, 1), observed=0.1 ) inference_data = pm.sample(100, chains=2, return_inferencedata=True) test_dict = { "posterior": ["mu"], "sample_stats": ["lp"], "log_likelihood": ["x"], "observed_data": ["value", "~x"], } fails = check_multiple_attrs(test_dict, inference_data) assert not fails assert inference_data.observed_data.value.dtype.kind == "f"
def test_multiobservedrv_to_observed_data(self, multiobs): # fake regression data, with weights (W) np.random.seed(2019) N = 100 X = np.random.uniform(size=N) W = 1 + np.random.poisson(size=N) a, b = 5, 17 Y = a + np.random.normal(b * X) with pm.Model(): a = pm.Normal("a", 0, 10) b = pm.Normal("b", 0, 10) mu = a + b * X sigma = pm.HalfNormal("sigma", 1) w = W def weighted_normal(value, mu, sigma, w): return w * pm.Normal.logp(value, mu, sigma) y_logp = pm.DensityDist( # pylint: disable=unused-variable "y_logp", mu, sigma, w, logp=weighted_normal, observed=Y, size=N) idata = pm.sample(20, tune=20, return_inferencedata=True, idata_kwargs={"density_dist_obs": multiobs}) multiobs_str = "" if multiobs else "~" test_dict = { "posterior": ["a", "b", "sigma"], "sample_stats": ["lp"], "log_likelihood": ["y_logp"], f"{multiobs_str}observed_data": ["y", "w"], } fails = check_multiple_attrs(test_dict, idata) assert not fails if multiobs: assert idata.observed_data.y.dtype.kind == "f"
def marginal_likelihood(self, name, X, Xu, y, noise=None, is_observed=True, jitter=0.0, **kwargs): R""" Returns the approximate marginal likelihood distribution, given the input locations `X`, inducing point locations `Xu`, data `y`, and white noise standard deviations `sigma`. Parameters ---------- name: string Name of the random variable X: array-like Function input values. If one-dimensional, must be a column vector with shape `(n, 1)`. Xu: array-like The inducing points. Must have the same number of columns as `X`. y: array-like Data that is the sum of the function with the GP prior and Gaussian noise. Must have shape `(n, )`. noise: scalar, Variable Standard deviation of the Gaussian noise. is_observed: bool Whether to set `y` as an `observed` variable in the `model`. Default is `True`. jitter: scalar A small correction added to the diagonal of positive semi-definite covariance matrices to ensure numerical stability. Default value is 0.0. **kwargs Extra keyword arguments that are passed to `MvNormal` distribution constructor. """ self.X = X self.Xu = Xu self.y = y if noise is None: raise ValueError("noise argument must be specified") else: self.sigma = noise if is_observed: return pm.DensityDist( name, X, Xu, self.sigma, jitter, logp=self._build_marginal_likelihood_logp, observed=y, ndims_params=[2, 2, 0], size=X.shape[0], **kwargs, ) else: warnings.warn( "The 'is_observed' argument has been deprecated. If the GP is " "unobserved use gp.Latent instead.", FutureWarning, ) return pm.DensityDist( name, X, Xu, self.sigma, jitter, logp=self._build_marginal_likelihood_logp, observed=y, ndims_params=[2, 2, 0], # ndim_supp=1, size=X.shape[0], **kwargs, )
import theano.tensor as T np.random.seed(42) theta_true = (25, 0.5) xdata = 100 * np.random.random(20) ydata = theta_true[0] + theta_true[1] * xdata # add scatter to points xdata = np.random.normal(xdata, 10) ydata = np.random.normal(ydata, 10) data = {'x': xdata, 'y': ydata} with pymc.Model() as model: alpha = pymc.Uniform('intercept', -100, 100) # Create custom densities beta = pymc.DensityDist('slope', lambda value: -1.5 * T.log(1 + value**2), testval=0) sigma = pymc.DensityDist('sigma', lambda value: -T.log(T.abs_(value)), testval=1) # Create likelihood like = pymc.Normal('y_est', mu=alpha + beta * xdata, sd=sigma, observed=ydata) start = pymc.find_MAP() step = pymc.NUTS(scaling=start) # Instantiate sampler trace = pymc.sample(10000, step, start=start) ################################################# # Create some convenience routines for plotting # All functions below written by Jake Vanderplas def compute_sigma_level(trace1, trace2, nbins=20): """From a set of traces, bin by number of standard deviations"""