Files
mikoto10032--deeplearning/books/PRML/PRML-master-Python/prml/kernel/gaussian_process_regressor.py
T
2026-07-13 13:30:25 +08:00

106 lines
3.3 KiB
Python
Executable File

import numpy as np
class GaussianProcessRegressor(object):
def __init__(self, kernel, beta=1.):
"""
construct gaussian process regressor
Parameters
----------
kernel
kernel function
beta : float
precision parameter of observation noise
"""
self.kernel = kernel
self.beta = beta
def fit(self, X, t, iter_max=0, learning_rate=0.1):
"""
maximum likelihood estimation of parameters in kernel function
Parameters
----------
X : ndarray (sample_size, n_features)
input
t : ndarray (sample_size,)
corresponding target
iter_max : int
maximum number of iterations updating hyperparameters
learning_rate : float
updation coefficient
Attributes
----------
covariance : ndarray (sample_size, sample_size)
variance covariance matrix of gaussian process
precision : ndarray (sample_size, sample_size)
precision matrix of gaussian process
Returns
-------
log_likelihood_list : list
list of log likelihood value at each iteration
"""
if X.ndim == 1:
X = X[:, None]
log_likelihood_list = [-np.Inf]
self.X = X
self.t = t
I = np.eye(len(X))
Gram = self.kernel(X, X)
self.covariance = Gram + I / self.beta
self.precision = np.linalg.inv(self.covariance)
for i in range(iter_max):
gradients = self.kernel.derivatives(X, X)
updates = np.array(
[-np.trace(self.precision.dot(grad)) + t.dot(self.precision.dot(grad).dot(self.precision).dot(t)) for grad in gradients])
for j in range(iter_max):
self.kernel.update_parameters(learning_rate * updates)
Gram = self.kernel(X, X)
self.covariance = Gram + I / self.beta
self.precision = np.linalg.inv(self.covariance)
log_like = self.log_likelihood()
if log_like > log_likelihood_list[-1]:
log_likelihood_list.append(log_like)
break
else:
self.kernel.update_parameters(-learning_rate * updates)
learning_rate *= 0.9
log_likelihood_list.pop(0)
return log_likelihood_list
def log_likelihood(self):
return -0.5 * (
np.linalg.slogdet(self.covariance)[1]
+ self.t @ self.precision @ self.t
+ len(self.t) * np.log(2 * np.pi))
def predict(self, X, with_error=False):
"""
mean of the gaussian process
Parameters
----------
X : ndarray (sample_size, n_features)
input
Returns
-------
mean : ndarray (sample_size,)
predictions of corresponding inputs
"""
if X.ndim == 1:
X = X[:, None]
K = self.kernel(X, self.X)
mean = K @ self.precision @ self.t
if with_error:
var = (
self.kernel(X, X, False)
+ 1 / self.beta
- np.sum(K @ self.precision * K, axis=1))
return mean.ravel(), np.sqrt(var.ravel())
return mean