'''
Probability of Improvement acquisition function.
'''
import numpy as np
from scipy.stats import norm
from autooed.utils.operand import safe_divide, expand
from autooed.mobo.acquisition.base import Acquisition
[docs]class ProbabilityOfImprovement(Acquisition):
'''
Probability of Improvement.
'''
[docs] def __init__(self, surrogate_model, **kwargs):
super().__init__(surrogate_model)
self.y_min = None
[docs] def _fit(self, X, Y):
self.y_min = np.min(Y, axis=0)
[docs] def _evaluate(self, X, gradient, hessian):
val = self.surrogate_model.evaluate(X, dtype='continuous', std=True, gradient=gradient, hessian=hessian)
y_mean, y_std = val['F'], val['S']
z = safe_divide(self.y_min - y_mean, y_std)
cdf_z = norm.cdf(z)
F = -cdf_z
dF, hF = None, None
dy_mean, hy_mean, dy_std, hy_std = val['dF'], val['hF'], val['dS'], val['hS']
if gradient or hessian:
dz_y_mean = -safe_divide(1, y_std)
dz_y_std = -safe_divide(self.y_min - y_mean, y_std ** 2)
pdf_z = norm.pdf(z)
dF_y_mean = -pdf_z * dz_y_mean
dF_y_std = -pdf_z * dz_y_std
dF_y_mean, dF_y_std = expand(dF_y_mean), expand(dF_y_std)
if gradient:
dF = dF_y_mean * dy_mean + dF_y_std * dy_std
if hessian:
dpdf_z_z = -z * pdf_z
dpdf_z_y_mean = dpdf_z_z * dz_y_mean
dpdf_z_y_std = dpdf_z_z * dz_y_std
hz_y_std = safe_divide(self.y_min - y_mean, y_std ** 3)
hF_y_mean = -dpdf_z_y_mean * dz_y_mean
hF_y_std = -dpdf_z_y_std * dz_y_std - pdf_z * hz_y_std
dy_mean, dy_std = expand(dy_mean), expand(dy_std)
dy_mean_T, dy_std_T = dy_mean.transpose(0, 1, 3, 2), dy_std.transpose(0, 1, 3, 2)
dF_y_mean, dF_y_std = expand(dF_y_mean), expand(dF_y_std)
hF_y_mean, hF_y_std = expand(hF_y_mean, (-1, -2)), expand(hF_y_std, (-1, -2))
hF = dF_y_mean * hy_mean + dF_y_std * hy_std + \
hF_y_mean * dy_mean * dy_mean_T + hF_y_std * dy_std * dy_std_T
return F, dF, hF