Skip to content

Expected improvement

smac.acquisition.function.expected_improvement #

EI #

EI(xi: float = 0.0, log: bool = False)

Bases: AbstractAcquisitionFunction

The Expected Improvement (EI) criterion is used to decide where to evaluate a function f(x) next. The goal is to balance exploration and exploitation. Expected Improvement (with or without function values in log space) acquisition function

$$ EI(X) := \mathbb{E}\left[ \max{0, f(\mathbf{X^+}) - f_{t+1}(\mathbf{X}) - \xi } \right] $$ with \(f(X^+)\) as the best location.

Reference for EI: Jones, D.R. and Schonlau, M. and Welch, W.J. (1998). Efficient Global Optimization of Expensive Black-Box Functions. Journal of Global Optimization 13, 455–492

Reference for logEI: Hutter, F. and Hoos, H. and Leyton-Brown, K. and Murphy, K. (2009). An experimental investigation of model-based parameter optimisation: SPO and beyond. In: Conference on Genetic and Evolutionary Computation

The logEI implemententation is based on the derivation of the orginal equation by: Watanabe, S. (2024). Derivation of Closed Form of Expected Improvement for Gaussian Process Trained on Log-Transformed Objective. arxiv.org/abs/2411.18095

PARAMETER DESCRIPTION
xi

Controls the balance between exploration and exploitation of the acquisition function.

TYPE: float, defaults to 0.0 DEFAULT: 0.0

log

Whether the function values are in log-space.

TYPE: bool, defaults to False DEFAULT: False

ATTRIBUTE DESCRIPTION
_xi

Exploration-exloitation trade-off parameter.

TYPE: float

_log

Function values in log-space or not.

TYPE: bool

_eta

Current incumbent function value (best value observed so far).

TYPE: float

Source code in smac/acquisition/function/expected_improvement.py
def __init__(
    self,
    xi: float = 0.0,
    log: bool = False,
) -> None:
    super(EI, self).__init__()

    self._xi: float = xi
    self._log: bool = log
    self._eta: float | None = None

model property writable #

model: AbstractModel | None

Return the used surrogate model in the acquisition function.

__call__ #

__call__(configurations: list[Configuration]) -> ndarray

Compute the acquisition value for a given configuration.

PARAMETER DESCRIPTION
configurations

The configurations where the acquisition function should be evaluated.

TYPE: list[Configuration]

RETURNS DESCRIPTION
ndarray[N, 1]

Acquisition values for X

Source code in smac/acquisition/function/abstract_acquisition_function.py
def __call__(self, configurations: list[Configuration]) -> np.ndarray:
    """Compute the acquisition value for a given configuration.

    Parameters
    ----------
    configurations : list[Configuration]
        The configurations where the acquisition function should be evaluated.

    Returns
    -------
    np.ndarray [N, 1]
        Acquisition values for X
    """
    X = convert_configurations_to_array(configurations)
    if len(X.shape) == 1:
        X = X[np.newaxis, :]

    acq = self._compute(X)
    if np.any(np.isnan(acq)):
        idx = np.where(np.isnan(acq))[0]
        acq[idx, :] = -np.finfo(float).max

    return acq

update #

update(model: AbstractModel, **kwargs: Any) -> None

Update the acquisition function attributes required for calculation.

This method will be called after fitting the model, but before maximizing the acquisition function. As an examples, EI uses it to update the current fmin. The default implementation only updates the attributes of the acquisition function which are already present.

Calls _update to update the acquisition function attributes.

PARAMETER DESCRIPTION
model

The model which was used to fit the data.

TYPE: AbstractModel

kwargs

Additional arguments to update the specific acquisition function.

TYPE: Any DEFAULT: {}

Source code in smac/acquisition/function/abstract_acquisition_function.py
def update(self, model: AbstractModel, **kwargs: Any) -> None:
    """Update the acquisition function attributes required for calculation.

    This method will be called after fitting the model, but before maximizing the acquisition
    function. As an examples, EI uses it to update the current fmin. The default implementation only updates the
    attributes of the acquisition function which are already present.

    Calls `_update` to update the acquisition function attributes.

    Parameters
    ----------
    model : AbstractModel
        The model which was used to fit the data.
    kwargs : Any
        Additional arguments to update the specific acquisition function.
    """
    self.model = model
    self._update(**kwargs)

EIPS #

EIPS(xi: float = 0.0)

Bases: EI

Expected Improvement per Second acquisition function

$$ EI(X) := \frac{\mathbb{E}\left[\max{0,f(\mathbf{X^+})-f_{t+1}(\mathbf{X})-\xi\right]}]}{np.log(r(x))} $$ with \(f(X^+)\) as the best location and \(r(x)\) as runtime.

PARAMETER DESCRIPTION
xi

Controls the balance between exploration and exploitation of the acquisition function.

TYPE: float, defaults to 0.0 DEFAULT: 0.0

Source code in smac/acquisition/function/expected_improvement.py
def __init__(self, xi: float = 0.0) -> None:
    super(EIPS, self).__init__(xi=xi)

model property writable #

model: AbstractModel | None

Return the used surrogate model in the acquisition function.

__call__ #

__call__(configurations: list[Configuration]) -> ndarray

Compute the acquisition value for a given configuration.

PARAMETER DESCRIPTION
configurations

The configurations where the acquisition function should be evaluated.

TYPE: list[Configuration]

RETURNS DESCRIPTION
ndarray[N, 1]

Acquisition values for X

Source code in smac/acquisition/function/abstract_acquisition_function.py
def __call__(self, configurations: list[Configuration]) -> np.ndarray:
    """Compute the acquisition value for a given configuration.

    Parameters
    ----------
    configurations : list[Configuration]
        The configurations where the acquisition function should be evaluated.

    Returns
    -------
    np.ndarray [N, 1]
        Acquisition values for X
    """
    X = convert_configurations_to_array(configurations)
    if len(X.shape) == 1:
        X = X[np.newaxis, :]

    acq = self._compute(X)
    if np.any(np.isnan(acq)):
        idx = np.where(np.isnan(acq))[0]
        acq[idx, :] = -np.finfo(float).max

    return acq

update #

update(model: AbstractModel, **kwargs: Any) -> None

Update the acquisition function attributes required for calculation.

This method will be called after fitting the model, but before maximizing the acquisition function. As an examples, EI uses it to update the current fmin. The default implementation only updates the attributes of the acquisition function which are already present.

Calls _update to update the acquisition function attributes.

PARAMETER DESCRIPTION
model

The model which was used to fit the data.

TYPE: AbstractModel

kwargs

Additional arguments to update the specific acquisition function.

TYPE: Any DEFAULT: {}

Source code in smac/acquisition/function/abstract_acquisition_function.py
def update(self, model: AbstractModel, **kwargs: Any) -> None:
    """Update the acquisition function attributes required for calculation.

    This method will be called after fitting the model, but before maximizing the acquisition
    function. As an examples, EI uses it to update the current fmin. The default implementation only updates the
    attributes of the acquisition function which are already present.

    Calls `_update` to update the acquisition function attributes.

    Parameters
    ----------
    model : AbstractModel
        The model which was used to fit the data.
    kwargs : Any
        Additional arguments to update the specific acquisition function.
    """
    self.model = model
    self._update(**kwargs)