library(tidyverse)
library(patchwork)
library(lhs)
library(plotly)
set.seed(123)
<- sqrt(.Machine$double.eps)
eps
# Our target function
# x is an N x 2 matrix
<- function(x) {
f 1] * exp(-x[, 1]^2 - x[, 2]^2)
x[,
}
# x_i and x_j can be vectors or scalars
<- function(xi, xj, alpha = 1, rho = 1) {
rbf ^2 * exp(-norm(xi - xj, type = "2") / (2 * rho^2))
alpha
}
<- function(X, err = eps) {
k_XX <- nrow(X)
N <- matrix(0, N, N)
K for (i in 1:N) {
for (j in 1:N) {
<- rbf(X[i, ], X[j, ])
K[i, j]
}
}
if (!is.null(err)) {
<- K + diag(err, ncol(K))
K
}
K
}
<- function(x, X) {
k_xX <- nrow(x)
N <- nrow(X)
M
<- matrix(0, N, M)
K for (i in 1:N) {
for (j in 1:M) {
<- rbf(x[i, ], X[j, ])
K[i, j]
}
}
K
}
# Training dataset: D = (X, Y)
<- randomLHS(100, 2)
X 1] <- -4 + 8*X[, 1]
X[, 2] <- -4 + 8*X[, 2]
X[, <- f(X)
Y
# Test points: Z
<- seq(-4, 4, length.out = 20)
x <- expand.grid(x, x) |> as.matrix()
Z
<- k_XX(X) + diag(eps, nrow(X))
K_XX <- k_xX(Z, X)
K_ZX <- k_XX(Z)
K_ZZ
<- K_ZX %*% solve(K_XX) %*% Y
m_post <- K_ZZ - K_ZX %*% solve(K_XX) %*% t(K_ZX) s_post
Modelling two variables using GPR
Dr. Gramacy’s textbook, Surrogates (Gramacy 2020), particularly chapter 5, was very helpful in putting together the code for this simulation.
<- as_tibble(Z) |>
results rename(x = Var1, y = Var2) |>
mutate(z_m = as.vector(m_post), z_sd = sqrt(diag(s_post)))
<- ggplot(results, aes(x, y, fill = z_m)) +
p1 geom_tile() +
scale_fill_viridis_c(name = expression(mu)) +
labs(title = "Posterior mean")
<- ggplot(results, aes(x, y, fill = z_sd)) +
p2 geom_tile() +
scale_fill_viridis_c(name = expression(sigma)) +
labs(title = "Posterior standard deviation")
| p2 p1
plot_ly(z = ~matrix(f(Z), ncol = 20)) |> add_surface()
plot_ly(z = matrix(results$z_m, ncol = 20)) |> add_surface()
References
Gramacy, Robert B. 2020. Surrogates: Gaussian Process Modeling, Design and Optimization for the Applied Sciences. Boca Raton, Florida: Chapman Hall/CRC. https://bookdown.org/rbg/surrogates/.