Gaussian process (kriging) smooth basis.
GaussianProcess(
k=10,
cov="matern32",
)
Equivalent to mgcv’s bs="gp" basis. This basis treats the unknown smooth function as a realization of a zero-mean Gaussian process with a chosen covariance (kernel) function, in the spirit of kriging/spatial statistics. Rather than working with the full n x n covariance matrix (which does not scale well and has no natural low-rank truncation-by-penalty like TPRS), this implementation builds a rank-k basis from the leading eigenfunctions of the covariance matrix evaluated at the training points, with the inverse eigenvalues serving directly as the penalty. Because the covariance function is stationary and isotropic (depends only on distance between points), GaussianProcess is naturally suited to spatial covariates or any setting where you want smoothness governed by a physically or statistically motivated correlation structure — e.g. exponential decay of spatial correlation — rather than a derivative-based bending-energy penalty like TPRS.
Parameters
k: int = 10
-
Number of basis functions, i.e. the number of leading eigenfunctions of the covariance matrix retained. Larger k captures more of the covariance structure at the cost of more computation; if k exceeds the number of training points n, it is silently reduced to n. The default is 10.
cov: str = "matern32"
-
Name of the covariance (kernel) function used to build the Gram matrix. One of:
"exp" — exponential covariance (Matern with nu=1/2): sigma^2 exp(-r / rho). Produces rough, non-differentiable sample paths; use when the underlying process is expected to be continuous but not smooth.
"matern32" — Matern with nu=3/2: once-differentiable sample paths. A reasonable general-purpose default, balancing smoothness and local flexibility. This is the default.
"matern52" — Matern with nu=5/2: twice-differentiable sample paths, smoother than "matern32".
"sqexp" — squared exponential (RBF): sigma^2 exp(-r^2 / (2 rho^2)). Produces infinitely differentiable, very smooth sample paths; can over-smooth sharp local features.
Notes
Given training covariates x with pairwise distances r = ||x_i - x_j||, the covariance (Gram) matrix C has entries C_{ij} = k(r_{ij}; rho) for the chosen kernel k. The range parameter rho is not user-specified; it is set automatically during fit() to one quarter of the mean range of the covariates, a simple heuristic that keeps the effective correlation length commensurate with the spread of the data. C is eigendecomposed and the k eigenvectors U with the largest eigenvalues d_1, ..., d_k are retained:
\mathbf{C} \approx \mathbf{U} \operatorname{diag}(d_1, \ldots, d_k) \mathbf{U}^\top .
The basis functions evaluated at new points x* are
\mathbf{B}(x^*) = \mathbf{C}(x^*, x_{\text{train}}) \, \mathbf{U} \,
\operatorname{diag}(d_1, \ldots, d_k)^{-1},
i.e. the covariance between x* and the training points, projected onto the retained eigenvectors and rescaled by the inverse eigenvalues (a Nystrom-style low-rank Karhunen-Loeve approximation to the process). The penalty matrix is diagonal in the inverse eigenvalues,
\mathbf{S} = \operatorname{diag}(d_1^{-1}, \ldots, d_k^{-1}),
which corresponds to the negative log-density of the Gaussian process prior on the coefficients: directions with small eigenvalue (little prior variance) are penalized heavily, and directions with large eigenvalue are penalized lightly. Because every eigenvalue is penalized, null_space_dimension() is 0 — there is no unpenalized null space, unlike thin plate or cubic regression splines, so even the “constant” and “linear” trends across the domain are (lightly) shrunk under this basis. Eigenvalues are clamped away from zero (to machine epsilon) for numerical stability when inverting; using a very small k or a badly-scaled covariate range can still lead to an ill-conditioned Gram matrix.
Examples
import numpy as np
from whittaker.smooths import GaussianProcess
rng = np.random.default_rng(0)
x = rng.uniform(0, 1, 100)
basis = GaussianProcess(k=10, cov="matern32").fit(x)
B = basis.basis_matrix(x)
S = basis.penalty_matrix()
B.shape, S.shape
Attributes
|
Name
|
Description
|
|
n_basis
|
Number of basis functions retained by this Gaussian process basis.
|
n_basis
Number of basis functions retained by this Gaussian process basis.
Equal to the number of leading eigenfunctions of the covariance matrix kept during fit(). This is the requested k unless fit() was called with fewer training points than k, in which case it is silently reduced to n.
Methods
basis_matrix()
Evaluate the Gaussian process basis at x.
Parameters
x: NDArray
-
Covariate values. Shape
(n,) or (n, d) where d must match the training dimension.
Returns
NDArray
-
Design matrix of shape
(n, k), equal to the covariance between x and the training points projected onto the retained eigenvectors and rescaled by the inverse eigenvalues.
Raises
ValueError
-
If the covariate dimension of
x does not match the training dimension.
fit()
Fit the Gaussian process basis to training data x.
Builds the covariance matrix at the training points, sets the range parameter rho automatically from the spread of the covariates, and eigendecomposes the covariance matrix to obtain the leading k eigenfunctions.
Parameters
x: NDArray
-
Training covariates. Shape
(n,) for univariate or (n, d) for multivariate.
Returns
GaussianProcess
-
Returns
self for method chaining.
Raises
ValueError
-
If the number of observations
n is smaller than k.
identifiability_constraints()
Return the sum-to-zero constraint row for the intercept.
identifiability_constraints()
Returns
NDArray
-
A
(1, k) matrix whose product with the coefficient vector is zero when the smooth has mean zero over the training data.
null_space_dimension()
Return 0: the Gaussian process penalty has no unpenalized null space.
Returns
int
-
Always
0, since every basis direction carries a (finite) penalty under the GP prior.
penalty_matrix()
Return the k x k penalty matrix S = diag(1 / eigenvalues).
Returns
NDArray
-
Diagonal matrix of shape
(k, k) whose entries are the inverse eigenvalues of the covariance matrix retained during fit(). There is no unpenalized block: this matrix is strictly positive definite.