6 Spatiotemporal self-exciting models
For the spatiotemporal Hawkes processes fitted by stelfi
, temporal self-excitement follows an exponential decay function (see Reinhart (2018)). The self-excitement over space follows a Gaussian distribution centered at the triggering event. The default is that the Gaussian function has a fixed covariance matrix, independent of time. Alternatively, covariance can be directly proportional to time, meaning that the self-excitement radiates out from the center over time. This can be appropriate when the mechanism causing self-excitement travels at a finite speed, but is very memory-intensive.
The intensity function used by stelfi
is
\[\lambda(s,t) = \mu + \alpha \Sigma_{i:\tau_i<t}(\text{exp}(-\beta * (t-\tau_i)) G_i(s-x_i, t - \tau_i)).\]
Here \(\mu\) is the background rate, \(\beta\) is the rate of temporal decay, \(\alpha\) is the increase in intensity after an event, \(\tau_i\) are the event times, \(x_i\) are the event locations (in 2D Euclidean space) and \(G_i(s-x_i, t - \tau_i)\) is the spatial self-excitement kernel.
For the version with time-independent spatial excitement: \(G_i(s-x_i, t - \tau_i) = f_X(s - x_i)\) where \(f_X\) is the density function of \(X \sim \text{N}(0, \Sigma)\), (\(\Sigma = \begin{pmatrix} \sigma_x^2 & \rho \\ \rho & \sigma_y^2 \end{pmatrix}\)).
For the version with time-dependent spatial excitement: \(G_i(s-x_i, t - \tau_i) = f_X(s - x_i)\) where \(f_X\) is the density function of \(X \sim \text{N}(0, (t-\tau_i)\Sigma)\)
6.1 Fitting a spatiotemporal Hawkes process
data(xyt, package = "stelfi")
<- data.frame(x = xyt$x, y = xyt$y)
locs <- xyt$t
times <- sf::st_as_sf(xyt$window) domain
ggplot(data = locs, aes(x = x, y = y, size = times)) +
geom_point() +
geom_sf(data = domain, fill = NA, inherit.aes = FALSE) +
theme_void()
<- fmesher::fm_as_segm(as.matrix(sf::st_coordinates(domain)[, 1:2]))
bnd <- fmesher::fm_mesh_2d(boundary = bnd,
smesh max.edge = 0.75, cutoff = 0.3)
<- list(mu = 1, alpha = 3, beta = 6, xsigma = 0.2,
param ysigma = 0.2, rho = 0)
<- fit_stelfi(times = times, locs = locs, sf = domain, smesh = smesh, parameters = param)
fit <- get_coefs(fit) pars
Note that the coefs
estimates are the vector of coefficients (on the log scale) of any supplied covariates, the first element related to the intercept (here the log of \(\mu\)). The estimate temporal self-excitement (ignoring and spatial influence) can be shown using show_hawkes()
as in Chapter 2.
show_hawkes(list(times = times, params = c(mu = pars[1, 1], alpha = pars[3,1], beta = pars[4, 1])))
The bivariate Gaussian component of the diffusion kernel
## bivariate Gaussian kernel
<- pars[5,1]
sigma_x <- pars[6,1]
sigma_y <- pars[7,1]
rho <- y <- seq(-2, 2, 0.1)
x <- matrix(c(sigma_x, rho, rho, sigma_y),
sigma ncol = 2)
<- function(x, y) mvtnorm::dmvnorm(cbind(x, y), c(0,0), sigma)
f <- outer(x,y,f)
z contour(x, y, z, nlevels = 10, asp = 1)
6.2 Simulating from a spatiotemporal Hawkes process
<- list(mu = 10, alpha = 30, beta = 60, xsigma = 1,
param ysigma = 0.2, rho = 0)
<- fit$simulate(par = param) sim
<- fit_stelfi(times = sim$times, locs = data.frame(x = sim$locs[,1], y = sim$locs[,2]),
fit sf = domain, smesh = smesh, parameters = param)
get_coefs(fit)
Estimate Std. Error
mu 2.135436e+04 1.193421e+03
coefs 9.969011e+00 5.588652e-02
alpha 4.223688e+02 3.774970e+02
beta 1.931561e+03 4.203334e+03
xsigma 1.570652e+00 7.592043e-01
ysigma 4.314199e-02 2.364518e-02
rho 9.661767e-01 5.215814e-02
6.3 Including a GMRF
Sensitive to starting values. TODO
<- list(mu = 1, alpha = 3, beta = 6, kappa = 0.9, tau = 1, xsigma = 0.2,
param ysigma = 0.2, rho = 0)
<- fit_stelfi(times = times, locs = locs, sf = domain, smesh = smesh, parameters = param,
fit GMRF = TRUE)
<- get_coefs(fit)
pars pars
Estimate Std. Error
mu 0.003432117 0.004005179
coefs -5.674577947 1.166970324
alpha 259.065220356 15.626889396
beta 259.065221549 15.626889258
xsigma 0.548451271 0.021614776
ysigma 0.296732653 0.014288624
rho 0.024276057 0.056616034
kappa 9.040797871 10.518462327
tau 0.004644464 0.009560527
The estimated GMRF can be plotted using the show_field()
function once the values have been extracted using get_fields()
(Chapter 5).
get_fields(fit, smesh) |>
show_field(smesh = smesh, sf = domain, clip = TRUE) +
::theme_classic() ggplot2