Title: | Latent Variable Model to Infer Food Intake from Multiple Biomarkers |
---|---|
Description: | A latent variable model based on factor analytic and mixture of experts models, designed to infer food intake from multiple biomarkers data. The model is framed within a Bayesian hierarchical framework, which provides flexibility to adapt to different biomarker distributions and facilitates inference on food intake from biomarker data alone, along with the associated uncertainty. Details are in D'Angelo, et al. (2020) <arXiv:2006.02995>. |
Authors: | Silvia D'Angelo [aut, cre], Claire Gormley [ctb], Lorraine Brennan [ctb] |
Maintainer: | Silvia D'Angelo <[email protected]> |
License: | GPL (>= 2) |
Version: | 1.0.1 |
Built: | 2025-02-19 02:57:17 UTC |
Source: | https://github.com/cran/multiMarker |
Implements the multiMarker model via an MCMC algorithm.
multiMarker(y, quantities, niter = 10000, burnIn = 3000, posteriors = FALSE, sigmaAlpha = 1, nuZ1 = NULL, nuZ2 = NULL, nuSigmaP1 = NULL, nuSigmaP2 = NULL, sigmaWprior = 0.000001, nuBeta1 = 2, nuBeta2 = 3, tauBeta = 0.1)
multiMarker(y, quantities, niter = 10000, burnIn = 3000, posteriors = FALSE, sigmaAlpha = 1, nuZ1 = NULL, nuZ2 = NULL, nuSigmaP1 = NULL, nuSigmaP2 = NULL, sigmaWprior = 0.000001, nuBeta1 = 2, nuBeta2 = 3, tauBeta = 0.1)
y |
A matrix of dimension |
quantities |
A vector of length |
niter |
The number of MCMC iterations. The default value is |
burnIn |
A numerical value, the number of iterations of the chain to be discarded when computing the posterior estimates. The default value is |
posteriors |
A logical value indicating if the full parameter chains should also be returned in output. The default value is |
sigmaAlpha |
Intercepts' hyperparameter ( |
nuZ1 , nuZ2
|
Are two vectors of length |
nuSigmaP1 , nuSigmaP2
|
Scalar hyperparameters for the error's variance parameters. The default values are |
sigmaWprior |
A scalar corresponding to the components' weights hyperparameter. The default value is |
nuBeta1 , nuBeta2
|
Scalar hyperparameters for the scaling coefficient's variance parameters. The default values are |
tauBeta |
A scalar factor for the scaling coefficient's variance parameters. The default value is |
The function facilitates inference of food intake from multiple biomarkers via MCMC, according to the multiMarker model (D'Angelo et al., 2020). The multiMarker model first learns the relationship between the multiple biomarkers and food quantity data from an intervention study and subsequently allows inference on the latent intake when only biomarker data are available.
Consider a biomarker matrix of dimension
, storing
different biomarker measurements on
independent observations.
The number of food quantities considered in the intervention study is denoted by
, with the corresponding set being
and
.
We assume that the biomarker measurements are related to an unobserved, continuous intake value, leading to the following factor analytic model:
where the latent variable denotes the latent intake of observation
, with
.
The
and
parameters characterize, respectively, the intercept and the scaling effect for biomarker
. We assume that these parameters are distributed a priori according to 0-truncated Gaussian distributions, with parameters
and
respectively. The error term
is the variability associated with biomarker
. We assume that these errors are normally distributed with 0 mean and variance
, which serves as a proxy for the precision of the biomarker.
A mixture of 0-truncated Gaussian distributions is assumed as prior distribution for the latent intakes. Components are centered around food quantity values
, and component-specific variances
model food quantity-specific intake variability, with lower values suggesting higher consumption-compliance. Mixture weights are observation-specific and denoted with
. Given the inherent ordering of the food quantities in the intervention study, an ordinal regression model with Cauchit link function is employed to model the observation-specific weights.
A Bayesian hierarchical framework is employed for the modelling process, allowing quantification of the uncertainty in intake estimation, and flexibility in adapting to different biomarker data distributions. The framework is implemented through a Metropolis within Gibbs Markov chain Monte Carlo (MCMC) algorithm. Hyperprior distributions are assumed on the prior parameters with the corresponding hyperparameter values fixed based on the data at hand, following an empirical Bayes approach.
For more details on the estimation of the multiMarker model, see D'Angelo et al. (2020).
An object of class 'multiMarker'
containing the following components:
estimates |
A list with 9 components, storing posterior estimates of medians, standard deviations and
|
constants |
A list with 11 components, storing constant model quantities:
|
chains |
If
|
D'Angelo, S. and Brennan, L. and Gormley, I.C. (2020). Inferring food intake from multiple biomarkers using a latent variable model. arxiv
library(truncnorm) oldpar <- par(no.readonly =TRUE) #-- Simulate intervention study biomarker and food quantity data --# P <- D <- 3; n <- 50 alpha <- rtruncnorm(P, 0, Inf, 4, 1) beta <- rtruncnorm(P, 0, Inf, 0.001, 0.1) x <- c(50, 100, 150) labels_z <- sample(c(1,2,3), n, replace = TRUE) quantities <- x[labels_z] sigma_d <- 8 z <- rtruncnorm(n, 0, Inf, x[labels_z], sigma_d) Y <- sapply( 1:P, function(p) sapply( 1:n, function(i) max(0, alpha[p] + beta[p]*z[i] + rnorm( 1, 0, 5) ) ) ) #-- Visualize the data --# par(mfrow= c(2,2)) boxplot(Y[,1] ~ quantities, xlab = "Food quantity", ylab = "Biomarker 1") boxplot(Y[,2] ~ quantities, xlab = "Food quantity", ylab = "Biomarker 2") boxplot(Y[,3] ~ quantities, xlab = "Food quantity", ylab = "Biomarker 3") #-- Fit the multiMarker model --# # Number of iterations (and burnIn) set small for example. modM <- multiMarker(y = Y, quantities = quantities, niter = 100, burnIn = 30, posteriors = TRUE) # niter and burnIn values are low only for example purposes #-- Extract summary statistics for model parameters --# modM$estimates$ALPHA_E[,3] #estimated median, standard deviation, # 0.025 and 0.975 quantiles for the third intercept parameter (alpha_3) modM$estimates$BETA_E[,2] #estimated median, standard deviation, # 0.025 and 0.975 quantiles for the second scaling parameter (beta_2) #-- Examine behaviour of MCMC chains --# par(mfrow= c(2,1)) plot(modM$chains$ALPHA_c[,3], type = "l", xlab = "Iteration (after burnin)", ylab = expression(alpha[3]) ) abline( h = mean(modM$chains$ALPHA_c[,3]), lwd = 2, col = "darkred") plot(modM$chains$BETA_c[,2], type = "l", xlab = "Iteration (after burnin)", ylab = expression(beta[2]) ) abline( h = mean(modM$chains$BETA_c[,2]), lwd = 2, col = "darkred") # compute Effective Sample Size # library(LaplacesDemon) # ESS(modM$chains$ALPHA_c[,3]) # effective sample size for alpha_3 MCMC chain # ESS(modM$chains$BETA_c[,2]) # effective sample size for beta_2 MCMC chain par(oldpar)
library(truncnorm) oldpar <- par(no.readonly =TRUE) #-- Simulate intervention study biomarker and food quantity data --# P <- D <- 3; n <- 50 alpha <- rtruncnorm(P, 0, Inf, 4, 1) beta <- rtruncnorm(P, 0, Inf, 0.001, 0.1) x <- c(50, 100, 150) labels_z <- sample(c(1,2,3), n, replace = TRUE) quantities <- x[labels_z] sigma_d <- 8 z <- rtruncnorm(n, 0, Inf, x[labels_z], sigma_d) Y <- sapply( 1:P, function(p) sapply( 1:n, function(i) max(0, alpha[p] + beta[p]*z[i] + rnorm( 1, 0, 5) ) ) ) #-- Visualize the data --# par(mfrow= c(2,2)) boxplot(Y[,1] ~ quantities, xlab = "Food quantity", ylab = "Biomarker 1") boxplot(Y[,2] ~ quantities, xlab = "Food quantity", ylab = "Biomarker 2") boxplot(Y[,3] ~ quantities, xlab = "Food quantity", ylab = "Biomarker 3") #-- Fit the multiMarker model --# # Number of iterations (and burnIn) set small for example. modM <- multiMarker(y = Y, quantities = quantities, niter = 100, burnIn = 30, posteriors = TRUE) # niter and burnIn values are low only for example purposes #-- Extract summary statistics for model parameters --# modM$estimates$ALPHA_E[,3] #estimated median, standard deviation, # 0.025 and 0.975 quantiles for the third intercept parameter (alpha_3) modM$estimates$BETA_E[,2] #estimated median, standard deviation, # 0.025 and 0.975 quantiles for the second scaling parameter (beta_2) #-- Examine behaviour of MCMC chains --# par(mfrow= c(2,1)) plot(modM$chains$ALPHA_c[,3], type = "l", xlab = "Iteration (after burnin)", ylab = expression(alpha[3]) ) abline( h = mean(modM$chains$ALPHA_c[,3]), lwd = 2, col = "darkred") plot(modM$chains$BETA_c[,2], type = "l", xlab = "Iteration (after burnin)", ylab = expression(beta[2]) ) abline( h = mean(modM$chains$BETA_c[,2]), lwd = 2, col = "darkred") # compute Effective Sample Size # library(LaplacesDemon) # ESS(modM$chains$ALPHA_c[,3]) # effective sample size for alpha_3 MCMC chain # ESS(modM$chains$BETA_c[,2]) # effective sample size for beta_2 MCMC chain par(oldpar)
Implements the multiMarker model via an MCMC algorithm.
## S3 method for class 'multiMarker' predict( object, y, niter = 10000, burnIn = 3000, posteriors = FALSE, ...)
## S3 method for class 'multiMarker' predict( object, y, niter = 10000, burnIn = 3000, posteriors = FALSE, ...)
object |
An object of class inheriting from |
y |
A matrix of dimension |
niter |
The number of MCMC iterations. The default value is |
burnIn |
A numerical value, the number of iterations of the chain to be discarded when computing the posterior estimates. The default value is |
posteriors |
A logical value indicating if the full parameter chains should also be returned in output. The default value is |
... |
Further arguments passed to or from other methods. |
The function facilitates inference on food intake from multiple biomarkers alone via MCMC, according to the multiMarker model (D'Angelo et al., 2020).
A Bayesian framework is employed for the modelling process, allowing quantification of the uncertainty associated with inferred intake. The framework is implemented through an MCMC algorithm.
For more details, see D'Angelo et al. (2020).
A list with 2 components:
inferred_E |
a list with 2 components, storing estimates of medians, standard deviations and
|
chains |
If
|
D'Angelo, S. and Brennan, L. and Gormley, I.C. (2020). Inferring food intake from multiple biomarkers using a latent variable model. arXiv.
library(truncnorm) oldpar <- par(no.readonly =TRUE) #-- Simulate intervention study biomarker and food quantity data --# P <- D <- 3; n <- 50 alpha <- rtruncnorm(P, 0, Inf, 4, 1) beta <- rtruncnorm(P, 0, Inf, 0.001, 0.1) x <- c(50, 100, 150) labels_z <- sample(c(1,2,3), n, replace = TRUE) quantities <- x[labels_z] sigma_d <- 8 z <- rtruncnorm(n, 0, Inf, x[labels_z], sigma_d) Y <- sapply( 1:P, function(p) sapply( 1:n, function(i) max(0, alpha[p] + beta[p]*z[i] + rnorm( 1, 0, 5) ) ) ) #-- Simulate Biomarker data only --# nNew <- 20 labels_zNew <- sample(c(1,2,3), nNew, replace = TRUE) zNew <- rtruncnorm(nNew, 0, Inf, x[labels_zNew], sigma_d) YNew <- sapply( 1:P, function(p) sapply( 1:nNew, function(i) max(0, alpha[p] + beta[p]*zNew[i] + rnorm( 1, 0, 5) ) ) ) #-- Fit the multiMarker model to the intervention study data --# # Number of iterations (and burnIn) set small for example. modM <- multiMarker(y = Y, quantities = quantities, niter = 100, burnIn = 30, posteriors = TRUE) # niter and burnIn values are low only for example purposes #-- Extract summary statistics for model parameters --# modM$estimates$ALPHA_E[,3] #estimated median, standard deviation, # 0.025 and 0.975 quantiles for the third intercept parameter (alpha_3) modM$estimates$BETA_E[,2] #estimated median, standard deviation, # 0.025 and 0.975 quantiles for the second scaling parameter (beta_2) #-- Examine behaviour of MCMC chains --# par(mfrow= c(2,1)) plot(modM$chains$ALPHA_c[,3], type = "l", xlab = "Iteration (after burnin)", ylab = expression(alpha[3]) ) abline( h = mean(modM$chains$ALPHA_c[,3]), lwd = 2, col = "darkred") plot(modM$chains$BETA_c[,2], type = "l", xlab = "Iteration (after burnin)", ylab = expression(beta[2]) ) abline( h = mean(modM$chains$BETA_c[,2]), lwd = 2, col = "darkred") # compute Effective Sample Size # library(LaplacesDemon) # ESS(modM$chains$ALPHA_c[,3]) # effective sample size for alpha_3 MCMC chain # ESS(modM$chains$BETA_c[,2]) # effective sample size for beta_2 MCMC chain #-- Infer intakes from biomarker only data --# # Number of iterations (and burnIn) set small for example. infM <- predict(modM, y = YNew, niter = 100, burnIn = 30, posteriors = TRUE) # niter and burnIn values are low only for example purpose #-- Extract summary statistics for a given intake --# obs_j <- 2 # choose which observation to look at infM$inferred_E$inferred_intakes[, obs_j] #inferred median, standard deviation, # 0.025 and 0.975 quantiles for the intake of observation obs_j #-- Example of plot --# par(mfrow = c(1,1)) hist(infM$chains$ZINF[obs_j, ], breaks = 50, ylab = "Density", xlab = "Intake", main = "Intake's conditional distribution", cex.main = 0.7, freq = FALSE) # Inferred condtional distribution of intake for observation obs_j abline( v = infM$inferred_E$inferred_intakes[1,obs_j], col = "darkred", lwd = 2 ) # median value abline( v = infM$inferred_E$inferred_intakes[3,obs_j], col = "grey", lwd = 2 ) abline( v = infM$inferred_E$inferred_intakes[4,obs_j], col = "grey", lwd = 2 ) legend( x = "topleft", fill = c("grey", "darkred"), title = "quantiles:", legend = c("(0.025, 0.975)", "0.5"), bty = "n", cex = 0.7) mtext(paste("Observation", obs_j, sep = " "), outer = TRUE, cex = 1.5) par(oldpar)
library(truncnorm) oldpar <- par(no.readonly =TRUE) #-- Simulate intervention study biomarker and food quantity data --# P <- D <- 3; n <- 50 alpha <- rtruncnorm(P, 0, Inf, 4, 1) beta <- rtruncnorm(P, 0, Inf, 0.001, 0.1) x <- c(50, 100, 150) labels_z <- sample(c(1,2,3), n, replace = TRUE) quantities <- x[labels_z] sigma_d <- 8 z <- rtruncnorm(n, 0, Inf, x[labels_z], sigma_d) Y <- sapply( 1:P, function(p) sapply( 1:n, function(i) max(0, alpha[p] + beta[p]*z[i] + rnorm( 1, 0, 5) ) ) ) #-- Simulate Biomarker data only --# nNew <- 20 labels_zNew <- sample(c(1,2,3), nNew, replace = TRUE) zNew <- rtruncnorm(nNew, 0, Inf, x[labels_zNew], sigma_d) YNew <- sapply( 1:P, function(p) sapply( 1:nNew, function(i) max(0, alpha[p] + beta[p]*zNew[i] + rnorm( 1, 0, 5) ) ) ) #-- Fit the multiMarker model to the intervention study data --# # Number of iterations (and burnIn) set small for example. modM <- multiMarker(y = Y, quantities = quantities, niter = 100, burnIn = 30, posteriors = TRUE) # niter and burnIn values are low only for example purposes #-- Extract summary statistics for model parameters --# modM$estimates$ALPHA_E[,3] #estimated median, standard deviation, # 0.025 and 0.975 quantiles for the third intercept parameter (alpha_3) modM$estimates$BETA_E[,2] #estimated median, standard deviation, # 0.025 and 0.975 quantiles for the second scaling parameter (beta_2) #-- Examine behaviour of MCMC chains --# par(mfrow= c(2,1)) plot(modM$chains$ALPHA_c[,3], type = "l", xlab = "Iteration (after burnin)", ylab = expression(alpha[3]) ) abline( h = mean(modM$chains$ALPHA_c[,3]), lwd = 2, col = "darkred") plot(modM$chains$BETA_c[,2], type = "l", xlab = "Iteration (after burnin)", ylab = expression(beta[2]) ) abline( h = mean(modM$chains$BETA_c[,2]), lwd = 2, col = "darkred") # compute Effective Sample Size # library(LaplacesDemon) # ESS(modM$chains$ALPHA_c[,3]) # effective sample size for alpha_3 MCMC chain # ESS(modM$chains$BETA_c[,2]) # effective sample size for beta_2 MCMC chain #-- Infer intakes from biomarker only data --# # Number of iterations (and burnIn) set small for example. infM <- predict(modM, y = YNew, niter = 100, burnIn = 30, posteriors = TRUE) # niter and burnIn values are low only for example purpose #-- Extract summary statistics for a given intake --# obs_j <- 2 # choose which observation to look at infM$inferred_E$inferred_intakes[, obs_j] #inferred median, standard deviation, # 0.025 and 0.975 quantiles for the intake of observation obs_j #-- Example of plot --# par(mfrow = c(1,1)) hist(infM$chains$ZINF[obs_j, ], breaks = 50, ylab = "Density", xlab = "Intake", main = "Intake's conditional distribution", cex.main = 0.7, freq = FALSE) # Inferred condtional distribution of intake for observation obs_j abline( v = infM$inferred_E$inferred_intakes[1,obs_j], col = "darkred", lwd = 2 ) # median value abline( v = infM$inferred_E$inferred_intakes[3,obs_j], col = "grey", lwd = 2 ) abline( v = infM$inferred_E$inferred_intakes[4,obs_j], col = "grey", lwd = 2 ) legend( x = "topleft", fill = c("grey", "darkred"), title = "quantiles:", legend = c("(0.025, 0.975)", "0.5"), bty = "n", cex = 0.7) mtext(paste("Observation", obs_j, sep = " "), outer = TRUE, cex = 1.5) par(oldpar)