mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-06-17 15:35:20 +02:00
54 lines
1.8 KiB
Python
54 lines
1.8 KiB
Python
# Copyright (c) 2017, GPy authors (see AUTHORS.txt).
|
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
|
|
|
from . import LatentFunctionInference
|
|
from .posterior import StudentTPosterior
|
|
from ...util.linalg import pdinv, dpotrs, tdot
|
|
from ...util import diag
|
|
|
|
import numpy as np
|
|
from scipy.special import gammaln, digamma
|
|
|
|
|
|
class ExactStudentTInference(LatentFunctionInference):
|
|
"""
|
|
An object for inference of student-t processes (not for GP with student-t likelihood!).
|
|
|
|
The function self.inference returns a StudentTPosterior object, which summarizes
|
|
the posterior.
|
|
"""
|
|
|
|
def inference(self, kern, X, Y, nu, mean_function=None, K=None):
|
|
m = 0 if mean_function is None else mean_function.f(X)
|
|
K = kern.K(X) if K is None else K
|
|
|
|
YYT_factor = Y - m
|
|
Ky = K.copy()
|
|
diag.add(Ky, 1e-8)
|
|
|
|
# Posterior representation
|
|
Wi, LW, LWi, W_logdet = pdinv(Ky)
|
|
alpha, _ = dpotrs(LW, YYT_factor, lower=1)
|
|
beta = np.sum(alpha * YYT_factor)
|
|
posterior = StudentTPosterior(nu, woodbury_chol=LW, woodbury_vector=alpha, K=K)
|
|
|
|
# Log marginal
|
|
N = Y.shape[0]
|
|
D = Y.shape[1]
|
|
log_marginal = 0.5 * (
|
|
-N * np.log((nu - 2) * np.pi)
|
|
- W_logdet
|
|
- (nu + N) * np.log(1 + beta / (nu - 2))
|
|
)
|
|
log_marginal += gammaln((nu + N) / 2) - gammaln(nu / 2)
|
|
|
|
# Gradients
|
|
dL_dK = 0.5 * ((nu + N) / (nu + beta - 2) * tdot(alpha) - D * Wi)
|
|
dL_dnu = -N / (nu - 2.0) + digamma(0.5 * (nu + N)) - digamma(0.5 * nu)
|
|
dL_dnu -= np.log(1 + beta / (nu - 2.0))
|
|
dL_dnu += ((nu + N) * beta) / ((nu - 2) * (beta + nu - 2))
|
|
dL_dnu *= 0.5
|
|
dL_dm = (nu + N) / (nu + beta - 2) * alpha
|
|
gradients = {"dL_dK": dL_dK, "dL_dnu": dL_dnu, "dL_dm": dL_dm}
|
|
|
|
return posterior, log_marginal, gradients
|