Download model/mollified_uniform.py from OneScience-Group/GP_for_TO: direct link, hf CLI and curl.
- Browser
- Download file 3 kB
-
https://huggingface.co/OneScience-Group/GP_for_TO/resolve/main/model/mollified_uniform.py
- Command line
-
hf download hf://OneScience-Group/GP_for_TO/model/mollified_uniform.py
-
curl -L -o mollified_uniform.py https://huggingface.co/OneScience-Group/GP_for_TO/resolve/main/model/mollified_uniform.py
3 kB
| import math | |
| import torch | |
| from gpytorch.priors import Prior | |
| from torch.distributions import constraints,Uniform,Normal | |
| from torch.distributions.utils import broadcast_all | |
| from numbers import Number | |
| class MollifiedUniformPrior(Prior): | |
| r"""Uniform distribution that is differentiable everywhere | |
| This is an approximation to the Uniform distribution which maintains differentiability by placing a | |
| Gaussian distribution over points away from the original support. The density for a single dimension is | |
| .. math:: | |
| p(x) &= \frac{M}{\sqrt{2\pi\sigma^2}}\exp\left[-\frac{d(x)^2}{2\sigma^2}\right], \\ | |
| d(x) &= \begin{cases} | |
| a-x & x < a \\ | |
| 0 & a\leq x < b\\ | |
| x-b & x \geq b | |
| \end{cases} | |
| :param a: lower range (inclusive) | |
| :type a: float or torch.Tensor | |
| :param b: upper range (exclusive) | |
| :type b: float or torch.Tensor | |
| :param tail_sigma: Standard deviation of the Gaussian distributions on the tails. Lower values make the | |
| approximation closer to Uniform, but may increase the optimization effort. Defaults to 0.1 | |
| :type tail_sigma: float or torch.Tensor, optional | |
| .. note:: | |
| The `rsample` method for this distribution returns uniformly distributed samples from the interval `[a,b)`, | |
| and **not** from the Mollified distribution. The `log_prob` method, however, returns the correct probability. | |
| The purpose of the priors in this package is to generate initial starting points for optimizing | |
| hyperparameters and for MAP estimation. | |
| """ | |
| arg_constraints = {'a':constraints.real,'b':constraints.real,'tail_sigma':constraints.positive} | |
| support = constraints.real | |
| def __init__(self,a,b,tail_sigma=0.1): | |
| self.a,self.b,self.tail_sigma = broadcast_all(a,b,tail_sigma) | |
| if isinstance(a,Number) or isinstance(b,Number): | |
| batch_shape = torch.Size() | |
| else: | |
| batch_shape = self.a.size() | |
| super().__init__(batch_shape) | |
| def mean(self): | |
| return (self.a+self.b)/2 | |
| def _half_range(self): | |
| return (self.b-self.a)/2 | |
| def _log_normalization_constant(self): | |
| return -torch.log(1+(self.b-self.a)/(math.sqrt(2*math.pi)*self.tail_sigma)) | |
| def log_prob(self,X): | |
| # expression preserving gradients under automatic differentiation | |
| tail_dist = ((X-self.mean).abs()-self._half_range).clamp(min=0) | |
| return Normal(loc=torch.zeros_like(self.a),scale=self.tail_sigma).log_prob(tail_dist)+self._log_normalization_constant | |
| def rsample(self,sample_shape=torch.Size([])): | |
| return Uniform(self.a,self.b).rsample(sample_shape).to(self.a) | |
| def expand(self,expand_shape): | |
| batch_shape = torch.Size(expand_shape) | |
| return MollifiedUniformPrior( | |
| self.a.expand(batch_shape), | |
| self.b.expand(batch_shape), | |
| self.tail_sigma.expand(batch_shape) | |
| ) | |