The Integrated Nested Laplace Approximation, or INLA, approach is a recently developed, computationally simpler method for fitting Bayesian models [(Rue et al., 2009, compared to traditional Markov Chain Monte Carlo (MCMC) approaches. INLA fits models that are classified as latent Gaussian models, which are applicable in many settings (Martino & Rue, 2010. In general, INLA fits a general form of additive models such as:
\(\eta = \alpha + \sum_{j=1}^{nf} f^{(j)}(u_{ij}) + \sum_{k=1}^{n\beta}\beta_k z_{ki} + \epsilon_i\)
where \(\eta\) is the linear predictor for a generalized linear model formula, and is composed of a linear function of some variables u, \(\beta\) are the effects of covariates, z, and \(\epsilon\) is an unstructured residual (Rue et al., 2009). As this model is often parameterized as a Bayesian one, we are interested in the posterior marginal distributions of all the model parameters. Rue and Martino (2007) show that the posterior marginal for the random effects (x) in such models can be approximated as:
\(\tilde{p}(x_i|y) = \sum_k \tilde{p}(x_i|\theta_k, y) \tilde{p}(\theta_k|y) \Delta_k\)
via numerical integration (Rue & Martino, 2007; Schrodle & Held, 2011a, 2011b). The posterior distribution of the hyperparameters (\(\theta\)) of the model can also be approximated as:
\(\tilde{p}(\theta | y)) \propto \frac{p(x, \theta, y)}{\tilde{p}G(x| \theta,y)} \mid _{x} = x^*(\theta)\)
, where G is a Gaussian approximation of the posterior and \(x^*(\theta)\) is the mode of the conditional distribution of \(p(x|\theta,y)\). Thus, instead of using MCMC to find an iterative, sampling-based estimate of the posterior, it is arrived at numerically. This method of fitting the spatial models specified above has been presented by numerous authors (Blangiardo & Cameletti, 2015; Blangiardo et al., 2013; Lindgren & Rue, 2015; Martins et al., 2013; Schrodle & Held, 2011a, 2011b), with comparable results to MCMC.
Below, I show examples of using INLA to fit Bayesian regression models for data from US counties. One example will be a relatively small data set from Texas, while the other example will be all US counties. The US county example basically emulates the paper by Sparks et al 2012.
library(rgdal)
## Loading required package: sp
## rgdal: version: 1.2-5, (SVN revision 648)
## Geospatial Data Abstraction Library extensions to R successfully loaded
## Loaded GDAL runtime: GDAL 2.0.1, released 2015/09/15
## Path to GDAL shared files: C:/Users/Corey Sparks/Documents/R/win-library/3.3/rgdal/gdal
## Loaded PROJ.4 runtime: Rel. 4.9.2, 08 September 2015, [PJ_VERSION: 492]
## Path to PROJ.4 shared files: C:/Users/Corey Sparks/Documents/R/win-library/3.3/rgdal/proj
## Linking to sp version: 1.2-4
library(spdep)
## Loading required package: Matrix
library(RColorBrewer)
library(lattice)
library(INLA)
## Loading required package: splines
## This is INLA 0.0-1468872408, dated 2016-07-18 (14:43:05+0100).
## See www.r-inla.org/contact-us for how to get help.
#read in big US shapefile with lots of stuff in it
usdat<-readOGR(dsn = "D:/GoogleDrive/classes/dem7263/data",layer = "output12711")
## OGR data source with driver: ESRI Shapefile
## Source: "D:/GoogleDrive/classes/dem7263/data", layer: "output12711"
## with 3064 features
## It has 328 fields
## Integer64 fields read as strings: f1198408 f1198407 f1198406 f1198405 f1198404 f1198403 f1198402 f1198401_1 f0453000_1 f1198499_1 f1198498 f1198497 f1198496 f1198495 f1198494 f1198493 f1198492 f1198491 pubassist SSI socsec
#get outcome, which are the numbers of infant deaths
usdat$infd03<-usdat$f1194803
#get denominator, which are the number of births
usdat$births03<-usdat$f1254603
usdat$e<-usdat$births03*(sum(usdat$infd03)/sum(usdat$births03))
#form spatial neighbors
#In INLA, we don't need FIPS codes, we need a simple numeric index for our counties
usdat$struct<-1:nrow(usdat@data)
#!!Be sure to set the row names of the neighbor list to the struct variable we just made!!
us.nb<-poly2nb(usdat, row.names=usdat$struct)
#Save the neighbor list to an external file, INLA needs the list this way!!
nb2INLA(us.nb, file="D:/GoogleDrive/classes/dem7263/class17//usa.gra")
We can fit the OLS model using the bayesian framework as:
#US Data
fit.us2<-inla(I(infd03/births03)~metro+giniz+hispz+blackz+povz+ne_bad+isowbz, family = "gaussian",control.predictor = list(link=1), data=usdat@data, control.compute = list(dic=T))
summary(fit.us2)
##
## Call:
## c("inla(formula = I(infd03/births03) ~ metro + giniz + hispz + blackz + ", " povz + ne_bad + isowbz, family = \"gaussian\", data = usdat@data, ", " control.compute = list(dic = T), control.predictor = list(link = 1))" )
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 0.3043 1.9773 0.4622 2.7438
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) 0.0066 1e-04 0.0063 0.0066 0.0068 0.0066 0
## metro 0.0007 2e-04 0.0003 0.0007 0.0011 0.0007 0
## giniz -0.0001 1e-04 -0.0003 -0.0001 0.0001 -0.0001 0
## hispz -0.0004 1e-04 -0.0006 -0.0004 -0.0002 -0.0004 0
## blackz 0.0016 1e-04 0.0014 0.0016 0.0018 0.0016 0
## povz 0.0010 1e-04 0.0007 0.0010 0.0013 0.0010 0
## ne_bad 0.0000 3e-04 -0.0005 0.0000 0.0006 0.0000 0
## isowbz 0.0006 1e-04 0.0004 0.0006 0.0008 0.0006 0
##
## The model has no random effects
##
## Model hyperparameters:
## mean sd 0.025quant
## Precision for the Gaussian observations 193269.11 18800.75 160773.79
## 0.5quant 0.975quant mode
## Precision for the Gaussian observations 191776.57 234431.01 188810.97
##
## Expected number of effective parameters(std dev): 2336.38(55.63)
## Number of equivalent replicates : 1.311
##
## Deviance Information Criterion (DIC) ...: -26281.16
## Effective number of parameters .........: 2311.74
##
## Marginal log-Likelihood: 12017.41
## Posterior marginals for linear predictor and fitted values computed
inla.hpdmarginal(p = .95, fit.us2$marginals.fixed$giniz)
## low high
## level:0.95 -0.000325973 0.0001271985
inla.hpdmarginal(p = .95, fit.us2$marginals.fixed$ne_bad)
## low high
## level:0.95 -0.0004679239 0.0005539363
inla.hpdmarginal(p = .95, fit.us2$marginals.fixed$isowbz)
## low high
## level:0.95 0.0003971225 0.0008073215
OR, as a poisson model:
#US data
fit.p_us<-inla(infd03~metro+giniz+hispz+blackz+povz+ne_bad+isowbz, family = "poisson",E=e+.0001, data=usdat@data, control.compute = list(dic=T))
summary(fit.p_us)
##
## Call:
## c("inla(formula = infd03 ~ metro + giniz + hispz + blackz + povz + ", " ne_bad + isowbz, family = \"poisson\", data = usdat@data, E = e + ", " 1e-04, control.compute = list(dic = T))")
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 0.1684 1.1952 0.4688 1.8324
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) 0.0348 0.0151 0.0050 0.0348 0.0643 0.0349 0
## metro 0.0649 0.0208 0.0241 0.0649 0.1058 0.0649 0
## giniz -0.0016 0.0055 -0.0123 -0.0017 0.0092 -0.0018 0
## hispz -0.0747 0.0075 -0.0893 -0.0747 -0.0600 -0.0747 0
## blackz 0.1389 0.0114 0.1165 0.1389 0.1614 0.1389 0
## povz 0.1448 0.0108 0.1237 0.1448 0.1659 0.1449 0
## ne_bad -0.2301 0.0189 -0.2672 -0.2301 -0.1931 -0.2300 0
## isowbz -0.0461 0.0126 -0.0708 -0.0461 -0.0213 -0.0461 0
##
## The model has no random effects
##
## The model has no hyperparameters
##
## Expected number of effective parameters(std dev): 8.445(0.00)
## Number of equivalent replicates : 362.83
##
## Deviance Information Criterion (DIC) ...: 10303.27
## Effective number of parameters .........: 8.444
##
## Marginal log-Likelihood: -5205.15
## Posterior marginals for linear predictor and fitted values computed
#or negative binonmial on the us data
fit.nb_us<-inla(infd03~metro+giniz+hispz+blackz+povz+ne_bad+isowbz, family = "nbinomial",E=e+.0001, data=usdat@data, control.compute = list(dic=T))
summary(fit.nb_us)
##
## Call:
## c("inla(formula = infd03 ~ metro + giniz + hispz + blackz + povz + ", " ne_bad + isowbz, family = \"nbinomial\", data = usdat@data, ", " E = e + 1e-04, control.compute = list(dic = T))")
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 0.1624 2.4732 0.4462 3.0818
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) 0.0333 0.0159 0.0020 0.0334 0.0644 0.0334 0
## metro 0.0601 0.0232 0.0146 0.0600 0.1055 0.0600 0
## giniz -0.0046 0.0100 -0.0243 -0.0045 0.0149 -0.0044 0
## hispz -0.0757 0.0101 -0.0955 -0.0757 -0.0559 -0.0757 0
## blackz 0.1178 0.0143 0.0896 0.1178 0.1460 0.1177 0
## povz 0.1574 0.0138 0.1303 0.1574 0.1844 0.1574 0
## ne_bad -0.1969 0.0247 -0.2453 -0.1969 -0.1485 -0.1969 0
## isowbz -0.0585 0.0164 -0.0907 -0.0585 -0.0262 -0.0586 0
##
## The model has no random effects
##
## Model hyperparameters:
## mean sd
## size for the nbinomial observations (overdispersion) 52.41 4.189
## 0.025quant 0.5quant
## size for the nbinomial observations (overdispersion) 44.75 52.24
## 0.975quant mode
## size for the nbinomial observations (overdispersion) 60.98 51.85
##
## Expected number of effective parameters(std dev): 8.252(0.0063)
## Number of equivalent replicates : 371.32
##
## Deviance Information Criterion (DIC) ...: 10269.18
## Effective number of parameters .........: 8.815
##
## Marginal log-Likelihood: -5234.51
## Posterior marginals for linear predictor and fitted values computed
Or a simple, unstructured random county intercept model:
#US model
fit.pre_u<-inla(infd03~metro+giniz+hispz+blackz+povz+ne_bad+isowbz + f(struct, model = "iid"), family = "poisson",E=e+.0001, data=usdat@data, control.compute = list(dic=T))
summary(fit.pre_u)
##
## Call:
## c("inla(formula = infd03 ~ metro + giniz + hispz + blackz + povz + ", " ne_bad + isowbz + f(struct, model = \"iid\"), family = \"poisson\", ", " data = usdat@data, E = e + 1e-04, control.compute = list(dic = T))" )
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 0.2045 7.0177 1.0587 8.2809
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) 0.0304 0.0155 -0.0001 0.0304 0.0606 0.0305 0
## metro 0.0623 0.0219 0.0193 0.0623 0.1054 0.0623 0
## giniz -0.0034 0.0078 -0.0187 -0.0034 0.0119 -0.0034 0
## hispz -0.0753 0.0089 -0.0929 -0.0753 -0.0578 -0.0753 0
## blackz 0.1241 0.0130 0.0985 0.1241 0.1496 0.1241 0
## povz 0.1546 0.0123 0.1304 0.1546 0.1788 0.1546 0
## ne_bad -0.2094 0.0220 -0.2525 -0.2095 -0.1663 -0.2095 0
## isowbz -0.0554 0.0147 -0.0842 -0.0554 -0.0265 -0.0554 0
##
## Random effects:
## Name Model
## struct IID model
##
## Model hyperparameters:
## mean sd 0.025quant 0.5quant 0.975quant mode
## Precision for struct 141.12 25.40 100.45 137.94 200.23 131.76
##
## Expected number of effective parameters(std dev): 147.40(20.21)
## Number of equivalent replicates : 20.79
##
## Deviance Information Criterion (DIC) ...: 10201.89
## Effective number of parameters .........: 148.05
##
## Marginal log-Likelihood: -5170.65
## Posterior marginals for linear predictor and fitted values computed
A more complicated, Besag ICAR model:
#US Models
fit.psp1_u<-inla(infd03~metro+giniz+hispz+blackz+povz+ne_bad+isowbz + f(struct, model = "besag", graph = "D:/GoogleDrive/classes/dem7263/usa.gra"), family = "poisson",E=e+.0001, data=usdat@data, control.compute = list(dic=T))
summary(fit.psp1_u)
##
## Call:
## c("inla(formula = infd03 ~ metro + giniz + hispz + blackz + povz + ", " ne_bad + isowbz + f(struct, model = \"besag\", graph = \"D:/GoogleDrive/classes/dem7263/usa.gra\"), ", " family = \"poisson\", data = usdat@data, E = e + 1e-04, control.compute = list(dic = T))" )
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 0.7133 13.2682 0.5886 14.5701
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) 0.0279 0.0156 -0.0028 0.0280 0.0584 0.0281 0
## metro 0.0581 0.0221 0.0148 0.0581 0.1015 0.0581 0
## giniz 0.0008 0.0080 -0.0148 0.0007 0.0164 0.0007 0
## hispz -0.0566 0.0117 -0.0794 -0.0566 -0.0335 -0.0568 0
## blackz 0.1073 0.0148 0.0783 0.1074 0.1364 0.1074 0
## povz 0.1476 0.0131 0.1217 0.1476 0.1733 0.1476 0
## ne_bad -0.1635 0.0243 -0.2112 -0.1635 -0.1158 -0.1636 0
## isowbz -0.0658 0.0155 -0.0961 -0.0658 -0.0354 -0.0658 0
##
## Random effects:
## Name Model
## struct Besags ICAR model
##
## Model hyperparameters:
## mean sd 0.025quant 0.5quant 0.975quant mode
## Precision for struct 70.66 14.28 47.98 68.84 103.92 65.24
##
## Expected number of effective parameters(std dev): 110.14(14.64)
## Number of equivalent replicates : 27.82
##
## Deviance Information Criterion (DIC) ...: 10100.03
## Effective number of parameters .........: 110.75
##
## Marginal log-Likelihood: -7506.17
## Posterior marginals for linear predictor and fitted values computed
1/fit.psp1_u$summary.hyperpar$mean
## [1] 0.01415256
#Change the default prior on the spatial variance:
fit.psp2_u<-inla(infd03~metro+giniz+hispz+blackz+povz+ne_bad+isowbz + f(struct, model = "besag", graph = "D:/GoogleDrive/classes/dem7263/usa.gra", hyper = list(theta=list(prior="loggamma", param=c(.5, .005)))), family = "poisson",E=e+.0001, data=usdat@data, control.compute = list(dic=T))
summary(fit.psp2_u)
##
## Call:
## c("inla(formula = infd03 ~ metro + giniz + hispz + blackz + povz + ", " ne_bad + isowbz + f(struct, model = \"besag\", graph = \"D:/GoogleDrive/classes/dem7263/usa.gra\", ", " hyper = list(theta = list(prior = \"loggamma\", param = c(0.5, ", " 0.005)))), family = \"poisson\", data = usdat@data, E = e + ", " 1e-04, control.compute = list(dic = T))")
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 0.6748 13.5814 0.6258 14.8820
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) 0.0278 0.0156 -0.0029 0.0278 0.0583 0.0279 0
## metro 0.0580 0.0221 0.0146 0.0580 0.1015 0.0580 0
## giniz 0.0008 0.0080 -0.0149 0.0008 0.0165 0.0007 0
## hispz -0.0563 0.0118 -0.0793 -0.0564 -0.0331 -0.0565 0
## blackz 0.1072 0.0149 0.0781 0.1072 0.1364 0.1072 0
## povz 0.1475 0.0132 0.1216 0.1475 0.1733 0.1476 0
## ne_bad -0.1631 0.0244 -0.2110 -0.1631 -0.1153 -0.1632 0
## isowbz -0.0659 0.0155 -0.0963 -0.0659 -0.0354 -0.0659 0
##
## Random effects:
## Name Model
## struct Besags ICAR model
##
## Model hyperparameters:
## mean sd 0.025quant 0.5quant 0.975quant mode
## Precision for struct 68.18 13.47 46.69 66.50 99.42 63.23
##
## Expected number of effective parameters(std dev): 112.63(14.65)
## Number of equivalent replicates : 27.20
##
## Deviance Information Criterion (DIC) ...: 10100.53
## Effective number of parameters .........: 113.20
##
## Marginal log-Likelihood: -7501.95
## Posterior marginals for linear predictor and fitted values computed
1/fit.psp2_u$summary.hyperpar$mean
## [1] 0.01466758
1/fit.pre_u$summary.hyperpar$mean
## [1] 0.007086127
You notice less variation in the US hyperparameter than in the Texas hyperparameter, that’s becuase we have more data in the US example.
Compare the marginal distributions for the precision parameter from each model. The precision = 1/\(\sigma^2\), so we need to transform it to a variance scale so we can interpret it as we normally would!
#US example
1/fit.psp1_u$summary.hyperpar$mean
## [1] 0.01415256
um<- inla.tmarginal(
function(x) 1/x,
fit.psp1_u$marginals.hyperpar$'Precision for struct')
plot(um, type="l", main="Posterior distibution for model hyperparameter - US data")
1/fit.psp2_u$summary.hyperpar$mean
## [1] 0.01466758
um2<- inla.tmarginal(
function(x) 1/x,
fit.psp2_u$marginals.hyperpar$'Precision for struct')
lines(um2,lty=3, lwd=3 )
The two different priors show very similar results in terms of the posterior distribution of the county level variance.
Let’s have a look at the raw vs fitted SMR for infant mortality:
##US example
usdat$smr<-usdat$infd03/usdat$e
usdat$fittedsmr<-fit.psp2_u$summary.fitted.values$mean
plot(usdat$smr, usdat$fittedsmr)
brks<-quantile(c(usdat$smr, usdat$fittedsmr), p=seq(0, 1,length.out = 9), na.rm=T)
brks
## 0% 12.5% 25% 37.5% 50% 62.5% 75%
## 0.0000000 0.6108946 0.8173996 0.9131458 0.9998666 1.1018662 1.2424329
## 87.5% 100%
## 1.5389389 8.6480283
spplot(usdat, c("smr", "fittedsmr"), col.regions=brewer.pal(n=9, "RdBu"), at=brks , main="Raw and Fitted SMR")
spplot(usdat, "fittedsmr", col.regions=brewer.pal(n=9, "RdBu"), at=brks, main="US County Fitted SMR")
usdat$spre<-fit.psp2_u$summary.random$struct$mean
spplot(usdat, "spre", col.regions=brewer.pal(n=9, "RdBu"), at=quantile(usdat$spre, p=seq(0, 1,length.out = 9)), main="US County Fitted Spatial Random Effect")
The Besag, York and Mollie model. This model has two random effects, one which is spatially correlated, and the other which is iid normal. In INLA, and when using the BYM model, the first 1:n rows of the random effect are the combined spatial and “nonspatial” effects.
#US data
fit.us_bym<-inla(infd03~metro+giniz+hispz+blackz+povz+ne_bad+isowbz + f(struct, model = "bym", graph = "D:/GoogleDrive/classes/dem7263/usa.gra"), family = "poisson",E=e+.0001, data=usdat@data, control.compute = list(dic=T))
summary(fit.us_bym)
##
## Call:
## c("inla(formula = infd03 ~ metro + giniz + hispz + blackz + povz + ", " ne_bad + isowbz + f(struct, model = \"bym\", graph = \"D:/GoogleDrive/classes/dem7263/usa.gra\"), ", " family = \"poisson\", data = usdat@data, E = e + 1e-04, control.compute = list(dic = T))" )
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 0.8081 139.0280 0.7370 140.5732
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) 0.0279 0.0156 -0.0028 0.0279 0.0584 0.0280 0
## metro 0.0580 0.0221 0.0145 0.0580 0.1014 0.0580 0
## giniz 0.0008 0.0080 -0.0148 0.0008 0.0166 0.0008 0
## hispz -0.0571 0.0117 -0.0799 -0.0571 -0.0340 -0.0572 0
## blackz 0.1071 0.0148 0.0780 0.1071 0.1362 0.1071 0
## povz 0.1476 0.0132 0.1218 0.1476 0.1734 0.1477 0
## ne_bad -0.1638 0.0244 -0.2116 -0.1638 -0.1159 -0.1638 0
## isowbz -0.0659 0.0155 -0.0963 -0.0659 -0.0354 -0.0659 0
##
## Random effects:
## Name Model
## struct BYM model
##
## Model hyperparameters:
## mean sd 0.025quant
## Precision for struct (iid component) 3290.29 2277.54 694.13
## Precision for struct (spatial component) 73.54 15.71 47.99
## 0.5quant 0.975quant mode
## Precision for struct (iid component) 2733.16 9209.90 1758.34
## Precision for struct (spatial component) 71.70 109.42 68.07
##
## Expected number of effective parameters(std dev): 114.96(14.41)
## Number of equivalent replicates : 26.65
##
## Deviance Information Criterion (DIC) ...: 10102.76
## Effective number of parameters .........: 115.53
##
## Marginal log-Likelihood: -4689.67
## Posterior marginals for linear predictor and fitted values computed
1/fit.us_bym$summary.hyperpar$mean
## [1] 0.0003039242 0.0135980476
usdat$bym_est<-fit.us_bym$summary.fitted.values$mean
spplot(usdat, "bym_est", col.regions=brewer.pal(n=9, "RdBu"), at=quantile(usdat$bym_est, p=seq(0, 1,length.out = 9)), main="US County Fitted SMR from BYM model")
Here we calculate our exceedence probabilities, in this case, I calculate the probability that a county has a SMR greater than 1.25.
a2<-1.25
usdat$inlaprob<-unlist(lapply(fit.us_bym$marginals.fitted.values, function(X){
1-inla.pmarginal(a2, X)
}))
hist(usdat$inlaprob)
usdat$exceed.cut<-cut(usdat$inlaprob,breaks = c(0,0.2,0.5,0.8,.95,1), include.lowest = T)
spplot(usdat,"exceed.cut" , col.regions=brewer.pal(n=6, name="Blues"), key.space="bottom", main= expression(paste("Exceedence Probability Infant SMR ","Pr( ",theta," >1.25"," )") ))
## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 1919786 102.6 5684620 303.6 5684620 303.6
## Vcells 4887416 37.3 37663367 287.4 56575267 431.7
The Integrated Nested Laplace Approximation, or INLA, approach is a recently developed, computationally simpler method for fitting Bayesian models [(Rue et al., 2009, compared to traditional Markov Chain Monte Carlo (MCMC) approaches. INLA fits models that are classified as latent Gaussian models, which are applicable in many settings (Martino & Rue, 2010. In general, INLA fits a general form of additive models such as:
\(\eta = \alpha + \sum_{j=1}^{nf} f^{(j)}(u_{ij}) + \sum_{k=1}^{n\beta}\beta_k z_{ki} + \epsilon_i\)
where \(\eta\) is the linear predictor for a generalized linear model formula, and is composed of a linear function of some variables u, \(\beta\) are the effects of covariates, z, and \(\epsilon\) is an unstructured residual (Rue et al., 2009). As this model is often parameterized as a Bayesian one, we are interested in the posterior marginal distributions of all the model parameters. Rue and Martino (2007) show that the posterior marginal for the random effects (x) in such models can be approximated as:
\(\tilde{p}(x_i|y) = \sum_k \tilde{p}(x_i|\theta_k, y) \tilde{p}(\theta_k|y) \Delta_k\)
via numerical integration (Rue & Martino, 2007; Schrodle & Held, 2011a, 2011b). The posterior distribution of the hyperparameters (\(\theta\)) of the model can also be approximated as:
\(\tilde{p}(\theta | y)) \propto \frac{p(x, \theta, y)}{\tilde{p}G(x| \theta,y)} \mid _{x} = x^*(\theta)\)
, where G is a Gaussian approximation of the posterior and \(x^*(\theta)\) is the mode of the conditional distribution of \(p(x|\theta,y)\). Thus, instead of using MCMC to find an iterative, sampling-based estimate of the posterior, it is arrived at numerically. This method of fitting the spatial models specified above has been presented by numerous authors (Blangiardo & Cameletti, 2015; Blangiardo et al., 2013; Lindgren & Rue, 2015; Martins et al., 2013; Schrodle & Held, 2011a, 2011b), with comparable results to MCMC.
Above, we saw how to use INLA to fit a Bayesian regression model to areal data (US Counties). This example will focus on how to use INLA to fit a Bayesian multi-level model, where our outcome is observed at the individual level, and we may or may not have information avaialble at a higher level of aggregation.
In this example, we use data from the Integrated Health Interview Series to fit an Age-Period-Cohort model. Discussion of these models can be found in the recent text on the subject. In addition to the APC model, hierarchical models could consider county or city of residence, or some other geography.
Here, we load the IHIS data and do some recodes.
library(readstata13)
library(car)
library(INLA)
dat<- read.dta13("D:/GoogleDrive/classes/dem7903_App_Hier/data/ihis_00008.dta", convert.factors = F)
names(dat)
## [1] "year" "serial" "strata" "psu"
## [5] "nhishid" "hhweight" "nhispid" "hhx"
## [9] "fmx" "px" "perweight" "sampweight"
## [13] "fweight" "astatflg" "cstatflg" "pernum"
## [17] "age" "sex" "marstat" "marst"
## [21] "birthyr" "racea" "hispeth" "yrsinus"
## [25] "hispyn" "usborn" "citizen" "racenew"
## [29] "racebr" "educrec2" "educrec1" "educ"
## [33] "health" "bmicalc" "alcstat1" "smokestatus2"
## [37] "mod10fwk" "vig10fwk" "nhisiid"
names(dat)<-tolower(names(dat))
dat<-dat[dat$age>=18,]
dat$goodhealth<-recode(dat$health, recodes="1:3=0; 4:5=1; else=NA")
dat$bmi_clean<-ifelse(dat$bmicalc%in%c(0,996),NA, dat$bmicalc)
dat$obese<-ifelse(dat$bmi_clean>=30,1,0)
dat$hisp<-ifelse(dat$hispeth==10, 0, ifelse(dat$hispeth %in%c(90:93), NA, 1))
dat$race<-recode(dat$racea, recodes="100=1; 200=2; 300:340=3; 400:434=4; 500:600=5; else=NA")
dat$race_eth<-factor(ifelse(dat$hisp==1, "Hispanic",
ifelse(dat$hisp==0&dat$race==1, "NHWhite",
ifelse(dat$hisp==0&dat$race==2, "NHBlack",
ifelse(dat$hisp==0&dat$race==3, "NHNAHN",
ifelse(dat$hisp==0&dat$race==4, "NHAsian",
ifelse(dat$hisp==0&dat$race==5, "NHAsian", NA)))))))
dat$educ<-recode(dat$educrec2, recodes="10:41='lths'; 42='hs';50:53='somecoll'; 54:60='colledu'; else=NA", as.factor.result=T, levels = c("lths", "hs", "somecoll", "colledu"))
dat$male<-recode(dat$sex, recodes="1=1;2=0")
dat$agec<-cut(dat$age, breaks =seq(15, 100, 5))
dat$currsmoke<-recode(dat$smokestatus2, recodes="0=NA;90=NA; 10:13=1; else=0", as.factor.result = F)
dat$currdrink<-recode(dat$alcstat1, recodes="0='never'; 1:2='former'; 3='current'; else=NA", as.factor.result = T)
dat$birth_year<-ifelse(dat$birthyr>=9997, NA, dat$birthyr)
dat$age2<-dat$age^2
dat<-subset(dat, complete.cases(goodhealth,bmi_clean, educ, currsmoke, currdrink, birth_year))
dat$bmiz<- scale(dat$bmi_clean)
dat$cohort<- cut(dat$birth_year, breaks=seq(1915, 2000, 5))
set.seed(1115)
samps<-sample(1:nrow(dat), size = 75000, replace = F) #take a sample of subjects, because the NHIS is huge.
dat<- dat[samps,]
Below we fit the model using INLA. The APC model basically has three random effects, one for Age, one for period (year of survey) and a third random effect for cohort (birth year). If we have a continuous outcome, our model structure would be :
\(y_{ijkl} = \mu_{jkl} +\sum_c \beta_c x_{ik} + e_{ij}\) with \(\mu_{jkl} = \mu + u_j + v_k + \tau_l\)
\(u_j \sim N(0, \sigma^2_u)\)
\(v_k \sim N(0, \sigma^2_v)\)
\(\tau_l \sim N(0, \sigma^2_\tau)\)
library(lme4)
#user lmer to find good starting values for INLA
fit_in1.mer0<- lmer(bmiz~ race_eth+educ+male+currsmoke+currdrink+agec+(1|year)+(1|cohort), data=dat)
fit_in1.mer1<- lmer(bmiz~ race_eth+educ+male+currsmoke+currdrink+(1|agec)+(1|year)+(1|cohort), data=dat)
#INLA parameterizes variances on the log-precision scale, so if we take log(1/variance), we can get that number and feed it to INLA
vc0<-as.data.frame(VarCorr(fit_in1.mer0))
vc1<-as.data.frame(VarCorr(fit_in1.mer1))
vc0$init<-log(1/vc0$vcov); vc0
## grp var1 var2 vcov sdcor init
## 1 cohort (Intercept) <NA> 0.001480208 0.03847348 6.51557246
## 2 year (Intercept) <NA> 0.005698834 0.07549062 5.16749364
## 3 Residual <NA> <NA> 0.920389201 0.95936917 0.08295865
vc1$init<-log(1/vc1$vcov); vc1
## grp var1 var2 vcov sdcor init
## 1 cohort (Intercept) <NA> 0.00170954 0.04134659 6.37153073
## 2 year (Intercept) <NA> 0.00578871 0.07608357 5.15184586
## 3 agec (Intercept) <NA> 0.04411133 0.21002697 3.12103867
## 4 Residual <NA> <NA> 0.92036819 0.95935822 0.08298148
#Feed the init values to the hyperparameter inits in each f()
#Age as fixed
fit_in0<- inla(bmiz~ race_eth+educ+male+currsmoke+currdrink+agec+f(year, model="iid",hyper = list(prec=list(initial=vc0$init[2])) )+f(cohort, model="iid",hyper = list(prec=list(initial=vc0$init[1]))), family = "gaussian", data=dat, num.threads = 2, verbose = F, control.inla=list(strategy='gaussian'), control.family = list(hyper = list(prec=list(initial=vc0$init[3]))), control.compute = list(dic=T))
gc()
## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 3556074 190.0 6861544 366.5 6861544 366.5
## Vcells 36082862 275.3 97449684 743.5 90501012 690.5
#Age as unstructured random effect
fit_in1<- inla(bmiz~ race_eth+educ+male+currsmoke+currdrink+f(agec, model="iid",hyper = list(prec=list(initial=vc1$init[3])))+f(year, model="iid",hyper = list(prec=list(initial=vc1$init[2])) )+f(cohort, model="iid",hyper = list(prec=list(initial=vc1$init[1]))), family = "gaussian", data=dat, num.threads = 2, verbose = F, control.inla=list(strategy='gaussian'), control.family = list(hyper = list(prec=list(initial=vc1$init[4]))), control.compute = list(dic=T))
gc()
## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 4458502 238.2 6861544 366.5 6861544 366.5
## Vcells 51561884 393.4 117019620 892.8 95904325 731.7
#Age and year as smooth random effect
fit_in2<- inla(bmiz~ race_eth+educ+male+currsmoke+currdrink+f(agec, model="rw2",hyper = list(prec=list(initial=vc1$init[3])))+f(year, model="rw1",hyper = list(prec=list(initial=vc1$init[2])) )+f(cohort, model="iid",hyper = list(prec=list(initial=vc1$init[1]))), family = "gaussian", data=dat, num.threads = 2, verbose = F, control.inla=list(strategy='gaussian'), control.family = list(hyper = list(prec=list(initial=vc1$init[4]))), control.compute = list(dic=T))
gc()
## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 5360915 286.4 8273852 441.9 6861544 366.5
## Vcells 67041643 511.5 117019620 892.8 116997713 892.7
summary(fit_in0)
##
## Call:
## c("inla(formula = bmiz ~ race_eth + educ + male + currsmoke + currdrink + ", " agec + f(year, model = \"iid\", hyper = list(prec = list(initial = vc0$init[2]))) + ", " f(cohort, model = \"iid\", hyper = list(prec = list(initial = vc0$init[1]))), ", " family = \"gaussian\", data = dat, verbose = F, control.compute = list(dic = T), ", " control.family = list(hyper = list(prec = list(initial = vc0$init[3]))), ", " control.inla = list(strategy = \"gaussian\"), num.threads = 2)" )
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 2.6701 150.9579 6.6530 160.2810
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) -0.4245 0.0337 -0.4894 -0.4250 -0.3567 -0.4260 0
## race_ethNHAsian -0.4906 0.0189 -0.5278 -0.4906 -0.4535 -0.4906 0
## race_ethNHBlack 0.1762 0.0129 0.1509 0.1762 0.2015 0.1762 0
## race_ethNHNAHN 0.2001 0.0439 0.1138 0.2001 0.2862 0.2001 0
## race_ethNHWhite -0.0924 0.0104 -0.1129 -0.0924 -0.0719 -0.0924 0
## educhs -0.0360 0.0115 -0.0585 -0.0360 -0.0136 -0.0360 0
## educsomecoll -0.0512 0.0118 -0.0744 -0.0512 -0.0280 -0.0512 0
## educcolledu -0.2777 0.0127 -0.3025 -0.2777 -0.2528 -0.2777 0
## male 0.1252 0.0071 0.1112 0.1252 0.1392 0.1252 0
## currsmoke -0.1662 0.0091 -0.1840 -0.1662 -0.1483 -0.1662 0
## currdrinkformer 0.0658 0.0078 0.0505 0.0658 0.0811 0.0658 0
## currdrinknever 0.0000 31.6228 -62.0862 -0.0009 62.0344 0.0000 0
## agec(20,25 0.2460 0.0237 0.1994 0.2461 0.2923 0.2461 0
## agec(25,30 0.4144 0.0264 0.3622 0.4145 0.4657 0.4147 0
## agec(30,35 0.5038 0.0286 0.4468 0.5041 0.5590 0.5047 0
## agec(35,40 0.5824 0.0298 0.5226 0.5830 0.6394 0.5841 0
## agec(40,45 0.6157 0.0300 0.5549 0.6164 0.6726 0.6179 0
## agec(45,50 0.6442 0.0304 0.5823 0.6450 0.7017 0.6467 0
## agec(50,55 0.6862 0.0312 0.6225 0.6872 0.7449 0.6891 0
## agec(55,60 0.6912 0.0319 0.6259 0.6922 0.7511 0.6943 0
## agec(60,65 0.6895 0.0327 0.6224 0.6905 0.7509 0.6927 0
## agec(65,70 0.6375 0.0330 0.5699 0.6385 0.6999 0.6404 0
## agec(70,75 0.5437 0.0334 0.4760 0.5444 0.6075 0.5458 0
## agec(75,80 0.4378 0.0345 0.3685 0.4383 0.5045 0.4391 0
## agec(80,85 0.1653 0.0345 0.0964 0.1656 0.2326 0.1661 0
## agec(85,90 0.0000 31.6228 -62.0862 -0.0009 62.0344 0.0000 0
## agec(90,95 0.0000 31.6228 -62.0862 -0.0009 62.0344 0.0000 0
## agec(95,100 0.0000 31.6228 -62.0862 -0.0009 62.0344 0.0000 0
##
## Random effects:
## Name Model
## year IID model
## cohort IID model
##
## Model hyperparameters:
## mean sd 0.025quant
## Precision for the Gaussian observations 1.087 0.0057 1.075
## Precision for year 203.637 77.5473 90.254
## Precision for cohort 1242.376 896.5609 311.286
## 0.5quant 0.975quant mode
## Precision for the Gaussian observations 1.087 1.097 1.087
## Precision for year 191.121 389.766 168.000
## Precision for cohort 999.814 3606.933 676.177
##
## Expected number of effective parameters(std dev): 49.30(1.534)
## Number of equivalent replicates : 1521.25
##
## Deviance Information Criterion (DIC) ...: 206673.42
## Effective number of parameters .........: 51.35
##
## Marginal log-Likelihood: -103540.07
## Posterior marginals for linear predictor and fitted values computed
summary(fit_in1)
##
## Call:
## c("inla(formula = bmiz ~ race_eth + educ + male + currsmoke + currdrink + ", " f(agec, model = \"iid\", hyper = list(prec = list(initial = vc1$init[3]))) + ", " f(year, model = \"iid\", hyper = list(prec = list(initial = vc1$init[2]))) + ", " f(cohort, model = \"iid\", hyper = list(prec = list(initial = vc1$init[1]))), ", " family = \"gaussian\", data = dat, verbose = F, control.compute = list(dic = T), ", " control.family = list(hyper = list(prec = list(initial = vc1$init[4]))), ", " control.inla = list(strategy = \"gaussian\"), num.threads = 2)" )
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 2.6171 286.3867 8.0204 297.0242
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) 0.0645 0.0610 -0.0562 0.0644 0.1852 0.0644 0
## race_ethNHAsian -0.4905 0.0189 -0.5277 -0.4905 -0.4534 -0.4905 0
## race_ethNHBlack 0.1763 0.0129 0.1510 0.1763 0.2016 0.1763 0
## race_ethNHNAHN 0.2001 0.0439 0.1139 0.2001 0.2863 0.2001 0
## race_ethNHWhite -0.0923 0.0104 -0.1128 -0.0923 -0.0719 -0.0923 0
## educhs -0.0360 0.0115 -0.0585 -0.0360 -0.0135 -0.0360 0
## educsomecoll -0.0512 0.0118 -0.0744 -0.0512 -0.0280 -0.0512 0
## educcolledu -0.2774 0.0127 -0.3022 -0.2774 -0.2525 -0.2774 0
## male 0.1252 0.0071 0.1112 0.1252 0.1392 0.1252 0
## currsmoke -0.1660 0.0091 -0.1839 -0.1660 -0.1482 -0.1660 0
## currdrinkformer 0.0657 0.0078 0.0504 0.0657 0.0810 0.0657 0
## currdrinknever 0.0000 31.6228 -62.0862 -0.0009 62.0344 0.0000 0
##
## Random effects:
## Name Model
## agec IID model
## year IID model
## cohort IID model
##
## Model hyperparameters:
## mean sd 0.025quant
## Precision for the Gaussian observations 1.087 0.0056 1.075
## Precision for agec 26.037 9.8506 11.469
## Precision for year 201.452 77.1009 89.280
## Precision for cohort 1042.177 725.8413 262.906
## 0.5quant 0.975quant mode
## Precision for the Gaussian observations 1.087 1.098 1.087
## Precision for agec 24.519 49.596 21.660
## Precision for year 188.793 386.989 165.552
## Precision for cohort 851.250 2948.947 582.227
##
## Expected number of effective parameters(std dev): 49.58(1.433)
## Number of equivalent replicates : 1512.59
##
## Deviance Information Criterion (DIC) ...: 206671.66
## Effective number of parameters .........: 51.66
##
## Marginal log-Likelihood: -103489.79
## Posterior marginals for linear predictor and fitted values computed
summary(fit_in2)
##
## Call:
## c("inla(formula = bmiz ~ race_eth + educ + male + currsmoke + currdrink + ", " f(agec, model = \"rw2\", hyper = list(prec = list(initial = vc1$init[3]))) + ", " f(year, model = \"rw1\", hyper = list(prec = list(initial = vc1$init[2]))) + ", " f(cohort, model = \"iid\", hyper = list(prec = list(initial = vc1$init[1]))), ", " family = \"gaussian\", data = dat, verbose = F, control.compute = list(dic = T), ", " control.family = list(hyper = list(prec = list(initial = vc1$init[4]))), ", " control.inla = list(strategy = \"gaussian\"), num.threads = 2)" )
##
## Time used:
## Pre-processing Running inla Post-processing Total
## 2.4672 606.9693 8.2611 617.6976
##
## Fixed effects:
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) -0.0743 0.0265 -0.1266 -0.0742 -0.0225 -0.0740 0
## race_ethNHAsian -0.4910 0.0189 -0.5280 -0.4910 -0.4540 -0.4910 0
## race_ethNHBlack 0.1761 0.0128 0.1509 0.1761 0.2013 0.1761 0
## race_ethNHNAHN 0.1994 0.0438 0.1135 0.1994 0.2853 0.1994 0
## race_ethNHWhite -0.0924 0.0104 -0.1128 -0.0924 -0.0720 -0.0924 0
## educhs -0.0359 0.0114 -0.0583 -0.0359 -0.0135 -0.0359 0
## educsomecoll -0.0512 0.0118 -0.0743 -0.0512 -0.0281 -0.0512 0
## educcolledu -0.2773 0.0126 -0.3021 -0.2773 -0.2526 -0.2773 0
## male 0.1252 0.0071 0.1112 0.1252 0.1391 0.1252 0
## currsmoke -0.1657 0.0091 -0.1835 -0.1657 -0.1480 -0.1657 0
## currdrinkformer 0.0654 0.0078 0.0502 0.0654 0.0807 0.0654 0
## currdrinknever 0.0000 31.6228 -62.0862 -0.0009 62.0344 0.0000 0
##
## Random effects:
## Name Model
## agec RW2 model
## year RW1 model
## cohort IID model
##
## Model hyperparameters:
## mean sd 0.025quant
## Precision for the Gaussian observations 1.095 0.0012 1.092
## Precision for agec 521.098 137.4216 363.681
## Precision for year 1368.891 357.2214 668.643
## Precision for cohort 746.105 112.8574 509.518
## 0.5quant 0.975quant mode
## Precision for the Gaussian observations 1.095 1.097 1.095
## Precision for agec 484.517 878.026 415.435
## Precision for year 1389.006 2008.814 1574.899
## Precision for cohort 756.162 943.107 793.667
##
## Expected number of effective parameters(std dev): 42.27(0.8441)
## Number of equivalent replicates : 1774.16
##
## Deviance Information Criterion (DIC) ...: 206659.97
## Effective number of parameters .........: 42.16
##
## Marginal log-Likelihood: -103459.54
## Posterior marginals for linear predictor and fitted values computed
#Posterior summaries for our fixed effects
round(fit_in1$summary.fixed, 3)
## mean sd 0.025quant 0.5quant 0.975quant mode kld
## (Intercept) 0.064 0.061 -0.056 0.064 0.185 0.064 0
## race_ethNHAsian -0.491 0.019 -0.528 -0.491 -0.453 -0.491 0
## race_ethNHBlack 0.176 0.013 0.151 0.176 0.202 0.176 0
## race_ethNHNAHN 0.200 0.044 0.114 0.200 0.286 0.200 0
## race_ethNHWhite -0.092 0.010 -0.113 -0.092 -0.072 -0.092 0
## educhs -0.036 0.011 -0.058 -0.036 -0.013 -0.036 0
## educsomecoll -0.051 0.012 -0.074 -0.051 -0.028 -0.051 0
## educcolledu -0.277 0.013 -0.302 -0.277 -0.253 -0.277 0
## male 0.125 0.007 0.111 0.125 0.139 0.125 0
## currsmoke -0.166 0.009 -0.184 -0.166 -0.148 -0.166 0
## currdrinkformer 0.066 0.008 0.050 0.066 0.081 0.066 0
## currdrinknever 0.000 31.623 -62.086 -0.001 62.034 0.000 0
plot( fit_in1$summary.random$agec$mean, type="l",xaxt="n", ylab="Age Random Effect (IID)", main="Age random effect", ylim=c(-1,1))
axis(1, at=1:17, labels=levels(dat$agec))
lines(fit_in1$summary.random$agec$`0.025quant`, col=1, lty=5)
lines(fit_in1$summary.random$agec$`0.975quant`, col=1, lty=5)
abline(h=0, lwd=2)
legend("topright", legend = c("Posterior Mean", "95% Credible Interval"), lty=c(1,5))
plot(fit_in1$summary.random$year$mean, type="l",xaxt="n", ylab="Period Random Effect (IID)", main="Period random effect", ylim=c(-.3, .3))
yrs<-unique(dat$year); yrs<-yrs[order(yrs)]
axis(1, at=1:length(yrs), labels=yrs)
lines(fit_in1$summary.random$year$`0.025quant`, col=1, lty=5)
lines(fit_in1$summary.random$year$`0.975quant`, col=1, lty=5)
abline(h=0, lwd=2)
legend("topright", legend = c("Posterior Mean", "95% Credible Interval"), lty=c(1,5))
plot(fit_in1$summary.random$cohort$mean, type="l", xaxt="n", ylab="Cohort Random Effect (IID)", main="Cohort random effect", ylim=c(-.2, .2))
coh<-unique(dat$cohort); coh<-coh[order(coh)]
axis(1, at=1:length(coh), labels=coh)
lines(fit_in1$summary.random$cohort$`0.025quant`, col=1, lty=5)
lines(fit_in1$summary.random$cohort$`0.975quant`, col=1, lty=5)
abline(h=0, lwd=2)
legend("topright", legend = c("Posterior Mean", "95% Credible Interval"), lty=c(1,5))
Plot the marginals for the variance terms
m1<- inla.tmarginal(
function(x) 1/x,
fit_in1$marginals.hyperpar$`Precision for agec`)
m2<- inla.tmarginal(
function(x) 1/x,
fit_in1$marginals.hyperpar$`Precision for year`)
m3<- inla.tmarginal(
function(x) 1/x,
fit_in1$marginals.hyperpar$`Precision for cohort`)
plot(m1, type="l", main="Posterior distibution for age variance")
plot(m2, type="l", main="Posterior distibution for year variance")
plot(m3, type="l", main="Posterior distibution for cohort variance")