Source code for cuqi.distribution._normal

import numpy as np
import numbers
from scipy.special import erf
from cuqi.geometry import _get_identity_geometries
from cuqi.utilities import force_ndarray
from cuqi.distribution import Distribution

[docs] class Normal(Distribution): """ Normal probability distribution. Generates instance of cuqi.distribution.Normal. The variables of this distribution are iid. Parameters ------------ mean: mean of distribution std: standard deviation Example ----------- .. code-block:: python #Generate Normal with mean 2 and standard deviation 1 p = cuqi.distribution.Normal(mean=2, std=1) """
[docs] def __init__(self, mean=None, std=None, is_symmetric=True, **kwargs): # Init from abstract distribution class super().__init__(is_symmetric=is_symmetric, **kwargs) # Init specific to this distribution self.mean = mean self.std = std
@property def mean(self): """ Mean of the distribution """ return self._mean @mean.setter def mean(self, value): self._mean = force_ndarray(value, flatten=True) @property def std(self): """ Std of the distribution """ return self._std @std.setter def std(self, value): self._std = force_ndarray(value, flatten=True)
[docs] def pdf(self, x): return np.prod(1/(self.std*np.sqrt(2*np.pi))*np.exp(-0.5*((x-self.mean)/self.std)**2))
[docs] def logpdf(self, x): return np.sum(-np.log(self.std*np.sqrt(2*np.pi))-0.5*((x-self.mean)/self.std)**2)
[docs] def cdf(self, x): return np.prod(0.5*(1 + erf((x-self.mean)/(self.std*np.sqrt(2)))))
def _gradient(self, val, *args, **kwargs): if not type(self.geometry) in _get_identity_geometries(): raise NotImplementedError("Gradient not implemented for distribution {} with geometry {}".format(self,self.geometry)) if not callable(self.mean): return -(val-self.mean)/(self.std**2) elif hasattr(self.mean, "gradient"): # for likelihood model = self.mean dev = val - model.forward(*args, **kwargs) print(dev) return model.gradient(1.0/(np.array(self.std)) @ dev, *args, **kwargs) else: raise NotImplementedError("Gradient not implemented for distribution {} with location {}".format(self,self.mean)) def _sample(self,N=1, rng=None): """ Draw sample(s) from distribution Example ------- p = cuqi.distribution.Normal(mean=2, std=1) #Define distribution s = p.sample() #Sample from distribution Returns ------- Generated sample(s) """ if rng is not None: s = rng.normal(self.mean, self.std, (N,self.dim)).T else: s = np.random.normal(self.mean, self.std, (N,self.dim)).T return s