Hi all,
I also ran the inlabru version of the model on the same data (the data is exactly the same as in the example provided in the link). The results produced by inlabru is way off. Below is my code in plain INLA (copied from the link example):
win <- owin(c(0, 3), c(0, 3))
npix <- 300
spatstat.options(npixel = npix)
beta0 <- 3
exp(beta0) * diff(range(win$x)) * diff(range(win$y))
sigma2x <- 0.2
range <- 1.2
set.seed(1)
lg.s <- rLGCP('matern', beta0, var = sigma2x,
scale = range / sqrt(8), nu = 1, win = win)
xy <- cbind(lg.s$x, lg.s$y)[, 2:1]
n <- nrow(xy)
Lam <- attr(lg.s, 'Lambda')
rf.s <- log(Lam$v)
summary(as.vector(rf.s))
loc.d <- 3 * cbind(c(0, 1, 1, 0, 0), c(0, 0, 1, 1, 0))
v_mesh <- inla.mesh.2d(loc.domain = loc.d, offset = c(0.3, 1),
max.edge = c(0.3, 0.7), cutoff = 0.05)
nv <- v_mesh$n
spv <- SpatialPoints(cbind(lg.s$x, lg.s$y))
dmesh <- inla.mesh.dual(v_mesh) # this function is the book.mesh.dual() function provided in the link for computing the dual mesh
plot(dmesh)
nv <- v_mesh$n
domain.polys <- Polygons(list(Polygon(loc.d)), '0')
domainSP <- SpatialPolygons(list(domain.polys))
plot(domainSP)
w <- sapply(1:length(dmesh), function(i) {
if (gIntersects(dmesh[i, ], domainSP))
return(gArea(gIntersection(dmesh[i, ], domainSP)))
else return(0)
})
y.pp <- rep(0:1, c(nv, nrow(spv@coords)))
e.pp <- c(w, rep(0, nrow(spv@coords)))
imat <- Diagonal(nv, rep(1, nv))
lmat <- inla.spde.make.A(v_mesh, loc = spv)
A.pp <- rbind(imat, lmat)
z <- log(t(Lam$v)[do.call('cbind',
nearest.pixel(xy[, 1], xy[, 2], Lam))])
beta0.y <- 10
beta <- -2
prec.y <- 16
set.seed(2)
resp <- beta0.y + (z - beta0) / beta +
rnorm(length(z), 0, sqrt(1 / prec.y))
summary(resp)
#plain INLA
spde <- inla.spde2.pcmatern(mesh = v_mesh,
# PC-prior on range: P(practic.range < 0.05) = 0.01
prior.range = c(0.05, 0.01),
# PC-prior on sigma: P(sigma > 1) = 0.01
prior.sigma = c(1, 0.01))
stk.u <- inla.stack(
data = list(y = resp),
A = list(lmat, 1),
effects = list(i = 1:nv, b0 = rep(1, length(resp))))
u.res <- inla(y ~ 0 + b0 + f(i, model = spde),
data = inla.stack.data(stk.u),
control.predictor = list(A = inla.stack.A(stk.u)))
stk2.y <- inla.stack(
data = list(y = cbind(resp, NA), e = rep(0, n)),
A = list(lmat, 1),
effects = list(i = 1:nv, b0.y = rep(1, n)),
tag = 'resp2')
stk2.pp <- inla.stack(data = list(y = cbind(NA, y.pp), e = e.pp),
A = list(A.pp, 1),
effects = list(j = 1:nv, b0.pp = rep(1, nv + n)),
tag = 'pp2')
j.stk <- inla.stack(stk2.y, stk2.pp)
gaus.prior <- list(prior = 'gaussian', param = c(0, 2))
# Model formula
jform <- y ~ 0 + b0.pp + b0.y + f(i, model = spde) +
f(j, copy = 'i', fixed = FALSE,
hyper = list(beta = gaus.prior))
# Fit model
j.res <- inla(jform, family = c('gaussian', 'poisson'),
data = inla.stack.data(j.stk),
E = inla.stack.data(j.stk)$e,
control.predictor = list(A = inla.stack.A(j.stk)))
summary(j.res)
Below is the results produced by plain INLA:
Call:
c("inla(formula = jform, family = c(\"gaussian\", \"poisson\"), data = inla.stack.data(j.stk), ", " E =
inla.stack.data(j.stk)$e, control.predictor = list(A = inla.stack.A(j.stk)))" )
Time used:
Pre = 1.45, Running = 4.06, Post = 0.558, Total = 6.07
Fixed effects:
mean sd 0.025quant 0.5quant 0.975quant mode kld
b0.pp 3.203 0.155 2.912 3.198 3.542 3.194 0
b0.y 9.885 0.120 9.620 9.891 10.114 9.896 0
Random effects:
Name Model
i SPDE2 model
j Copy
Model hyperparameters:
mean sd 0.025quant 0.5quant 0.975quant mode
Precision for the Gaussian observations 12.759 1.358 10.250 12.706 15.577 12.623
Range for i 2.071 1.356 0.686 1.690 5.652 1.215
Stdev for i 0.184 0.047 0.112 0.176 0.296 0.162
Beta for j -1.113 0.421 -1.941 -1.112 -0.286 -1.109
Expected number of effective parameters(stdev): 23.83(8.09)
Number of equivalent replicates : 38.56
Marginal log-Likelihood: 404.09
As you can see, the results from plain INLA produced the correct results. But then I fitted the model using inlabru, the code is given below:
#inlabru
spv$resp <- resp
gaus.prior <- list(prior = 'gaussian', param = c(0, 2))
cmp <- ~ i(coordinates, model = spde) + j(coordinates, copy = 'i', fixed = F, hyper = list(beta = gaus.prior)) +
b0.y(1) + b0.pp(1) -1
form_lgcp <- coordinates ~ b0.pp + i
form_col <- resp ~ b0.y + j
lik_lgcp <- like(family = 'cp', data = spv,
domain = list(coordinates = v_mesh),
formula = form_lgcp)
lik_col <- like(family = 'gaussian', data = spv,
formula = form_col)
fit <- bru(components = cmp, lik_lgcp, lik_col,
options = list(control.inla=list(int.strategy = 'ccd'),
control.compute=list(config=TRUE),
control.results=list(return.marginals.random = TRUE,
return.marginals.predictor = TRUE),
control.predictor = list(compute = TRUE)))
summary(fit)
The results from inlabru is the following:
inlabru version: 2.4.0
INLA version: 21.02.23
Components:
i: Model types main='spde', group='exchangeable', replicate='iid'
j: Copy of 'i' (types main='spde', group='exchangeable', replicate='iid)
b0.y: Model types main='linear', group='exchangeable', replicate='iid'
b0.pp: Model types main='linear', group='exchangeable', replicate='iid'
Likelihoods:
Family: 'cp'
Data class: 'SpatialPointsDataFrame'
Predictor: coordinates ~ b0.pp + i
Family: 'gaussian'
Data class: 'SpatialPointsDataFrame'
Predictor: resp ~ b0.y + j
Time used:
Pre = 1.65, Running = 10.7, Post = 1, Total = 13.3
Fixed effects:
mean sd 0.025quant 0.5quant 0.975quant mode kld
b0.y 10.333 0.271 9.875 10.304 10.955 10.233 0
b0.pp 0.293 1.365 -2.553 0.316 3.014 0.361 0
Random effects:
Name Model
i SPDE2 model
j Copy
Model hyperparameters:
mean sd 0.025quant 0.5quant 0.975quant mode
Precision for the Gaussian observations[2] 11.48 1.221 9.254 11.42 14.037 11.317
Range for i 3.06 0.623 2.073 2.98 4.507 2.801
Stdev for i 1.82 0.324 1.294 1.78 2.560 1.697
Beta for j -0.17 0.049 -0.267 -0.17 -0.075 -0.169
Expected number of effective parameters(stdev): 60.52(7.47)
Number of equivalent replicates : 11.62
Deviance Information Criterion (DIC) ...............: 685.09
Deviance Information Criterion (DIC, saturated) ....: NaN
Effective number of parameters .....................: -204.00
Watanabe-Akaike information criterion (WAIC) ...: 1511.27
Effective number of parameters .................: 294.45
Marginal log-Likelihood: -658.83
Posterior marginals for the linear predictor and
the fitted values are computed
As you can see, the results from inlabru is way off. I have checked every single prior specification of all the parameters, they are exactly the same as the plain INLA model. What is going on here for inlabru? Thank you very much!
Best,
David