Rescale predictive_gradients when normalizer=True
See original GitHub issueHello,
I was expecting model.predictive_gradients
to return the gradients of model.predict
, but it looks like it actually returns the gradients of model._raw_predict
. When normalizer=True
, the user has to correct the results of model.predictive_gradients
manually. (See code below.)
This is problematic when model.predictive_gradients
is used in an acquisition function in the context of Bayesian Optimization or Experimental Design, as in GPyOpt or Emukit.
The easy solution is to edit the docstring of model.predictive_gradients
to make clear that normalization is not included. A more durable solution is to rescale the output of model.predictive_gradients
, similar to model.predict
or model.predict_quantiles
. (I suspect that model.predict_jacobian
has the same problem but I haven’t checked.)
If I am missing anything, please let me know.
Thanks, Antoine
import numpy as np
import GPy
np.random.seed(2)
X = np.random.rand(15,3)
Y = np.random.rand(15,1)
normalize_Y = True
ker = GPy.kern.RBF(input_dim=X.shape[1])
model = GPy.models.GPRegression(X=X, Y=Y, kernel=ker,
normalizer=normalize_Y)
x = np.array([[-0.3, 0.1, 0.5]])
mu, var = model.predict(x)
mu_jac, var_jac = model.predictive_gradients(x)
# Finite-difference approximation
eps = 1e-8
mu_jac_num = np.zeros(x.shape[1])
var_jac_num = np.zeros(x.shape[1])
for ii in range(x.shape[1]):
x_eps = x + eps*np.eye(1, x.shape[1], ii)
mu_eps, var_eps = model.predict(x_eps)
mu_jac_num[ii] = (mu_eps-mu)/eps
var_jac_num[ii] = (var_eps-var)/eps
print('MU')
print(mu_jac.ravel())
print(mu_jac_num.ravel())
if normalize_Y:
print(mu_jac.ravel() * model.normalizer.std)
print('VAR')
print(var_jac.ravel())
print(var_jac_num.ravel())
if normalize_Y:
print(model.normalizer.inverse_variance(var_jac).ravel())
Issue Analytics
- State:
- Created 4 years ago
- Comments:5
Top GitHub Comments
Not that I know of. I’ll see if I can make a pull request in the next few days.
Along the same lines, I think most people would expect that evaluating
posterior_covariance_between_points
between a pointx
and itself should return the same thing asmodel.predict(x)[1]
. Currently this is not the case becauseposterior_covariance_between_points
does not account for likelihood noise or normalization.Amir, the posterior mean and variance are fine when
normalizer=True
. The only problem was with the gradients of the posterior mean and variance whennormalizer=True
, in that the gradients did not match those computed by finite differences ofmodel.predict
. Before the fix, the following snippet would raise an error, which it shouldn’t. (Again, the culprit in the below ismodel.predictive_gradients
, notmodel.predict
.)Let me know if this helps.