def predict(self, pred, full_cov=False, compute_grad=False):
inputs = self.inputs
values = self.values
# Special case if there is no data yet (everything from the prior)
if inputs is None:
return self.predict_from_prior(pred, full_cov, compute_grad)
if pred.shape[1] != self.num_dims:
raise Exception("Dimensionality of inputs must match dimensionality given at init time.")
# The primary covariances for prediction.
cand_cross = self.noiseless_kernel.cross_cov(inputs, pred)
chol, alpha = self._pull_from_cache_or_compute()
# Solve the linear systems.
# Note: if X = LL^T, cho_solve performs X\b whereas solve_triangular performs L\b
beta = spla.solve_triangular(chol, cand_cross, lower=True)
# Predict the marginal means at candidates.
func_m = np.dot(cand_cross.T, alpha) + self.mean.value
if full_cov:
# Return the covariance matrix of the pred inputs,
# rather than just the individual variances at each input
cand_cov = self.noiseless_kernel.cov(pred)
func_v = cand_cov - np.dot(beta.T, beta)
else:
cand_cov = self.noiseless_kernel.diag_cov(pred)
func_v = cand_cov - np.sum(beta**2, axis=0)
if not compute_grad:
return func_m, func_v
grad_cross = self.noiseless_kernel.cross_cov_grad_data(inputs, pred)
grad_xp_m = np.tensordot(np.transpose(grad_cross, (1,2,0)), alpha, 1)
# this should be faster than (and equivalent to) spla.cho_solve((chol, True),cand_cross))
gamma = spla.solve_triangular(chol.T, beta, lower=False)
# Using sum and multiplication and summing instead of matrix multiplication
# because I only want the diagonals of the gradient of the covariance matrix, not the whole thing
grad_xp_v = -2.0*np.sum(gamma[:,:,np.newaxis] * grad_cross, axis=0)
# Not very important -- just to make sure grad_xp_v.shape = grad_xp_m.shape
if values.ndim > 1:
grad_xp_v = grad_xp_v[:,:,np.newaxis]
# In case this is a function over a 1D input,
# return a numpy array rather than a float
if np.ndim(grad_xp_m) == 0:
grad_xp_m = np.array([grad_xp_m])
grad_xp_v = np.array([grad_xp_v])
return func_m, func_v, grad_xp_m, grad_xp_v
评论列表
文章目录