Thanks for your summary post and your blog article about the GPP implementation in Stan. I followed your code and compared the results with spBayes for a simple linear model. The spLM() is almost 8 times more efficient compared to my implementation, and I am interested in why this is the case.
data {
int<lower = 1> n; # number of sites
int<lower = 1> p; # number of coefficient
matrix[n, p] X; # design matrix
int<lower = 1, upper = n> m; # number of knots
vector[n] y; # response at sites
matrix[m, m] D_star; # distance matrix of knots
matrix[n, m] D_site_star; # distance matrix between site and knots
}
parameters {
vector[p] beta; # coefficients
real<lower = 0> sigma_sq; # variance component
real<lower = 0> tau_sq; # variance component
real<lower = 0> phi; # range/decay parameter
vector[m] w_z; # spatial latent process
}
transformed parameters {
vector[n] sigma_e_tilde; # bias corrected
vector[m] w_star;
vector[n] w;
cov_matrix[m] Cstar; # covariance matrix of sites
matrix[m, m] inv_Cstar; # inverse of C star
matrix[n, m] C_site_star; # covariance matrix of sites and knots
matrix[n, m] C_ss_inv_Cstar;
// latent gp at knots
for (i in 1:(m-1)) {
for (j in (i + 1):m) {
Cstar[i, j] = sigma_sq * exp(-D_star[i, j] * phi); # covariance matrix at knots
Cstar[j, i] = Cstar[i, j];
}
}
for (k in 1:m) Cstar[k, k] = sigma_sq + tau_sq; # C(s,s)
inv_Cstar = inverse(Cstar);
w_star = cholesky_decompose(Cstar) * w_z;
// latent gp at sample locations
C_site_star = sigma_sq * exp(-D_site_star * phi); # covariance matrix at sites and knots
C_ss_inv_Cstar = C_site_star * inv_Cstar;
w = C_site_star * inv_Cstar * w_star; # transformed latent process at sites
// bias adjustment from Finley et al. 2009
sigma_e_tilde = sigma_sq + tau_sq - rows_dot_product(C_ss_inv_Cstar, C_site_star); # bias corrected variance
}
model {
beta ~ normal(0, 10);
sigma_sq ~ inv_gamma(2, 1);
tau_sq ~ inv_gamma(2, 1);
phi ~ uniform(0.1, 10);
w_z ~ normal(0,1);
y ~ normal(X* beta + w, sqrt(sigma_e_tilde));
}
I'm simulating 500 locations with 30 knots for GPP, they provide very similar results for the latent w field (what I'm interested in) but not exactly the same. I've assigned the same priors.
The ESS is 328 running 4 chains, and takes 174s for each chain, while spBayes spLM() function result 139 ESS in 37s. Hence it is almost 8 times more efficient in spBayes.
Am I missing some tricks in the model implementation? In the attached is my simulation in R and stan file. Any suggestion is appreciated.