--- title: "Covariance Kernels and Composition" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Covariance Kernels and Composition} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(gaussianprocesses) ``` # Covariance as model structure A Gaussian-process kernel specifies how values of the latent function co-vary. For any finite input set \(X\), the matrix \[ K_{ij} = k(x_i,x_j) \] must be positive semidefinite. This package keeps the numerical kernel functions and reusable kernel specifications separate. For example: ```{r} x <- seq(-2, 2, length.out = 5) kernel_rbf( x, variance = 2, length_scale = 0.8 ) specification <- rbf_kernel( variance = 2, length_scale = 0.8 ) evaluate_kernel(specification, x) ``` # Squared-exponential kernel The squared-exponential kernel is \[ k(x,x') = \sigma_f^2 \exp\left( -\frac{1}{2} \sum_{d=1}^D \frac{(x_d-x_d')^2}{\ell_d^2} \right). \] A single \(\ell\) gives an isotropic kernel. A vector \((\ell_1,\ldots,\ell_D)\) gives ARD. In code: ```{r} rbf_kernel( variance = 1.5, length_scale = 0.7 ) ``` # Matérn family The package supplies \(\nu=1/2\), \(3/2\), and \(5/2\). Let the scaled distance be \[ r = \sqrt{ \sum_{d=1}^D \frac{(x_d-x_d')^2}{\ell_d^2} }. \] Then \[ k_{1/2}(r)= \sigma_f^2 e^{-r}, \] \[ k_{3/2}(r)= \sigma_f^2(1+\sqrt{3}r)e^{-\sqrt{3}r}, \] and \[ k_{5/2}(r)= \sigma_f^2 \left( 1+\sqrt{5}r+\frac{5r^2}{3} \right) e^{-\sqrt{5}r}. \] The smoothness assumption is therefore visible in the kernel choice rather than hidden inside the fitting function. # Rational quadratic The rational-quadratic kernel is \[ k(r) = \sigma_f^2 \left( 1+\frac{r^2}{2\alpha} \right)^{-\alpha}. \] It can be interpreted as a scale mixture of squared-exponential kernels. ```{r} rational_quadratic_kernel( variance = 1, length_scale = 0.5, alpha = 1.2 ) ``` # Periodic structure For one input dimension, \[ k(x,x') = \sigma_f^2 \exp\left( -\frac{ 2\sin^2\left(\pi(x-x')/p\right) }{\ell^2} \right). \] `period` is \(p\), while `length_scale` controls smoothness within the cycle. ```{r} periodic_kernel( variance = 1, length_scale = 0.8, period = 12 ) ``` # Sums and products If \(k_1\) and \(k_2\) are valid kernels, then so are \[ k(x,x') = k_1(x,x') + k_2(x,x') \] and \[ k(x,x') = k_1(x,x')k_2(x,x'). \] The package mirrors this directly: ```{r} trend <- linear_kernel(variance = 0.05) seasonal <- periodic_kernel( variance = 1, length_scale = 0.8, period = 12 ) local <- matern32_kernel( variance = 0.3, length_scale = 2 ) combined <- sum_kernel( trend, product_kernel(seasonal, local) ) combined ``` The corresponding covariance matrix is exactly the element-wise algebra: ```{r} time <- 0:6 K_combined <- evaluate_kernel(combined, time) K_manual <- evaluate_kernel(trend, time) + evaluate_kernel(seasonal, time) * evaluate_kernel(local, time) max(abs(K_combined - K_manual)) ``` # Parameter paths Composite kernels retain explicit parameter paths: ```{r} kernel_parameters( combined, flatten = TRUE ) ``` These paths are used directly by the hyperparameter optimizer. Partial updates preserve the rest of the structure: ```{r} updated <- update_kernel_parameters( combined, c("kernel2.kernel1.period" = 24) ) kernel_parameters( updated, flatten = TRUE ) ``` Kernel composition is therefore both mathematical and operational: the expression defining the covariance remains inspectable after fitting.