Source code for smac.model.gaussian_process.priors.log_normal_prior

from __future__ import annotations

from typing import Any

import math

import numpy as np

from smac.model.gaussian_process.priors.abstract_prior import AbstractPrior

__copyright__ = "Copyright 2022, automl.org"
__license__ = "3-clause BSD"


[docs] class LogNormalPrior(AbstractPrior): """Implements the log normal prior. Parameters ---------- sigma : float Specifies the standard deviation of the normal distribution. mean : float Specifies the mean of the normal distribution. seed : int, defaults to 0 """ def __init__( self, sigma: float, mean: float = 0, seed: int = 0, ): super().__init__(seed=seed) if mean != 0: raise NotImplementedError(mean) self._sigma = sigma self._sigma_square = sigma**2 self._mean = mean self._sqrt_2_pi = np.sqrt(2 * np.pi) @property def meta(self) -> dict[str, Any]: # noqa: D102 meta = super().meta meta.update({"sigma": self._sigma, "mean": self._mean}) return meta def _sample_from_prior(self, n_samples: int) -> np.ndarray: return self._rng.lognormal(mean=self._mean, sigma=self._sigma, size=n_samples) def _get_log_probability(self, theta: float) -> float: if theta <= self._mean: return -1e25 else: rval = -((math.log(theta) - self._mean) ** 2) / (2 * self._sigma_square) - math.log( self._sqrt_2_pi * self._sigma * theta ) return rval def _get_gradient(self, theta: float) -> float: if theta <= 0: return 0 else: # Derivative of log(1 / (x * s^2 * sqrt(2 pi)) * exp( - 0.5 * (log(x ) / s^2))^2)) # This is without the mean! return -(self._sigma_square + math.log(theta)) / (self._sigma_square * (theta)) * theta