Gestión de alta autocorrelación en MCMC

10

Estoy construyendo un modelo bayesiano jerárquico bastante complejo para un metanálisis usando R y JAGS. Simplificando un poco, los dos niveles clave del modelo tienen donde es la ésima observación del punto final (en este caso, rendimientos de cultivos modificados genéticamente vs. no modificados genéticamente) en el estudio , es el efecto para el estudio , los s son efectos para varias variables a nivel de estudio (el estado de desarrollo económico del país donde estudio realizado, especies de cultivo, método de estudio, etc.) indexado por una familia de funciones , y elα j = h γ h ( j ) + ϵ j y i j i j α j j γ h ϵ γ γ

yij=αj+ϵi
αj=hγh(j)+ϵj
yijijαjjγhϵs son términos de error. Tenga en cuenta que los s no son coeficientes en variables ficticias. En cambio, hay distintas variables para diferentes valores de nivel de estudio. Por ejemplo, hay para países en desarrollo y para países desarrollados. γγ γ d e v e l o p e dγdevelopingγdeveloped

Estoy principalmente interesado en estimar los valores de s. Esto significa que eliminar variables a nivel de estudio del modelo no es una buena opción. γ

Hay una alta correlación entre varias de las variables a nivel de estudio, y creo que esto está produciendo grandes autocorrelaciones en mis cadenas MCMC. Este diagrama de diagnóstico ilustra las trayectorias de la cadena (izquierda) y la autocorrelación resultante (derecha):
alta autocorrelación en salida MCMC

Como consecuencia de la autocorrelación, obtengo tamaños de muestra efectivos de 60-120 de 4 cadenas de 10,000 muestras cada una.

Tengo dos preguntas, una claramente objetiva y la otra más subjetiva.

  1. Además de adelgazar, agregar más cadenas y ejecutar el muestreador durante más tiempo, ¿qué técnicas puedo usar para manejar este problema de autocorrelación? Por "administrar" quiero decir "producir estimaciones razonablemente buenas en un período de tiempo razonable". En términos de potencia informática, estoy ejecutando estos modelos en una MacBook Pro.

  2. ¿Qué tan grave es este grado de autocorrelación? Las discusiones tanto aquí como en el blog de John Kruschke sugieren que, si solo ejecutamos el modelo lo suficiente, "la autocorrelación agrupada probablemente se ha promediado" (Kruschke) y, por lo tanto, no es realmente un gran problema.

Aquí está el código JAGS para el modelo que produjo la trama anterior, en caso de que alguien esté lo suficientemente interesado como para leer los detalles:

model {
for (i in 1:n) {
    # Study finding = study effect + noise
    # tau = precision (1/variance)
    # nu = normality parameter (higher = more Gaussian)
    y[i] ~ dt(alpha[study[i]], tau[study[i]], nu)
}

nu <- nu_minus_one + 1
nu_minus_one ~ dexp(1/lambda)
lambda <- 30

# Hyperparameters above study effect
for (j in 1:n_study) {
    # Study effect = country-type effect + noise
    alpha_hat[j] <- gamma_countr[countr[j]] + 
                    gamma_studytype[studytype[j]] +
                    gamma_jour[jourtype[j]] +
                    gamma_industry[industrytype[j]]
    alpha[j] ~ dnorm(alpha_hat[j], tau_alpha)
    # Study-level variance
    tau[j] <- 1/sigmasq[j]
    sigmasq[j] ~ dunif(sigmasq_hat[j], sigmasq_hat[j] + pow(sigma_bound, 2))
    sigmasq_hat[j] <- eta_countr[countr[j]] + 
                        eta_studytype[studytype[j]] + 
                        eta_jour[jourtype[j]] +
                        eta_industry[industrytype[j]]
    sigma_hat[j] <- sqrt(sigmasq_hat[j])
}
tau_alpha <- 1/pow(sigma_alpha, 2)
sigma_alpha ~ dunif(0, sigma_alpha_bound)

# Priors for country-type effects
# Developing = 1, developed = 2
for (k in 1:2) {
    gamma_countr[k] ~ dnorm(gamma_prior_exp, tau_countr[k])
    tau_countr[k] <- 1/pow(sigma_countr[k], 2)
    sigma_countr[k] ~ dunif(0, gamma_sigma_bound)
    eta_countr[k] ~ dunif(0, eta_bound)
}

# Priors for study-type effects
# Farmer survey = 1, field trial = 2
for (k in 1:2) {
    gamma_studytype[k] ~ dnorm(gamma_prior_exp, tau_studytype[k])
    tau_studytype[k] <- 1/pow(sigma_studytype[k], 2)
    sigma_studytype[k] ~ dunif(0, gamma_sigma_bound)
    eta_studytype[k] ~ dunif(0, eta_bound)
}

# Priors for journal effects
# Note journal published = 1, journal published = 2
for (k in 1:2) {
    gamma_jour[k] ~ dnorm(gamma_prior_exp, tau_jourtype[k])
    tau_jourtype[k] <- 1/pow(sigma_jourtype[k], 2)
    sigma_jourtype[k] ~ dunif(0, gamma_sigma_bound)
    eta_jour[k] ~ dunif(0, eta_bound)
}

# Priors for industry funding effects
for (k in 1:2) {
    gamma_industry[k] ~ dnorm(gamma_prior_exp, tau_industrytype[k])
    tau_industrytype[k] <- 1/pow(sigma_industrytype[k], 2)
    sigma_industrytype[k] ~ dunif(0, gamma_sigma_bound)
    eta_industry[k] ~ dunif(0, eta_bound)
}
}
Dan Hicks
fuente
1
Por lo que vale, los modelos complejos de varios niveles son más o menos la razón por la que Stan existe, exactamente por las razones que identifica.
Sycorax dice Reinstate Monica
Inicialmente intenté construir esto en Stan, hace varios meses. Los estudios involucran diferentes números de hallazgos, que (al menos en ese momento; no he verificado si las cosas han cambiado) requirieron agregar otra capa de complejidad al código y significaron que Stan no podía aprovechar los cálculos de la matriz que lo hacen tan rápido
Dan Hicks
1
No estaba pensando tanto en la velocidad como en la eficiencia con la que HMC explora la parte posterior. Entiendo que debido a que HMC puede cubrir mucho más terreno, cada iteración tiene una menor autocorrelación.
Sycorax dice Reinstate Monica
Oh, sí, ese es un punto interesante. Lo pondré en mi lista de cosas para probar.
Dan Hicks

Respuestas:

6

Siguiendo la sugerencia del usuario777, parece que la respuesta a mi primera pregunta es "usar Stan". Después de reescribir el modelo en Stan, aquí están las trayectorias (4 cadenas x 5000 iteraciones después del quemado):
ingrese la descripción de la imagen aquí y las gráficas de autocorrelación:
ingrese la descripción de la imagen aquí

¡Mucho mejor! Para completar, aquí está el código Stan:

data {                          // Data: Exogenously given information
// Data on totals
int n;                      // Number of distinct finding i
int n_study;                // Number of distinct studies j

// Finding-level data
vector[n] y;                // Endpoint for finding i
int study_n[n_study];       // # findings for study j

// Study-level data
int countr[n_study];        // Country type for study j
int studytype[n_study];     // Study type for study j
int jourtype[n_study];      // Was study j published in a journal?
int industrytype[n_study];  // Was study j funded by industry?

// Top-level constants set in R call
real sigma_alpha_bound;     // Upper bound for noise in alphas
real gamma_prior_exp;       // Prior expected value of gamma
real gamma_sigma_bound;     // Upper bound for noise in gammas
real eta_bound;             // Upper bound for etas
}

transformed data {
// Constants set here
int countr_levels;          // # levels for countr
int study_levels;           // # levels for studytype
int jour_levels;            // # levels for jourtype
int industry_levels;        // # levels for industrytype
countr_levels <- 2;
study_levels <- 2;
jour_levels <- 2;
industry_levels <- 2;
}

parameters {                    // Parameters:  Unobserved variables to be estimated
vector[n_study] alpha;      // Study-level mean
real<lower = 0, upper = sigma_alpha_bound> sigma_alpha;     // Noise in alphas

vector<lower = 0, upper = 100>[n_study] sigma;          // Study-level standard deviation

// Gammas:  contextual effects on study-level means
// Country-type effect and noise in its estimate
vector[countr_levels] gamma_countr;     
vector<lower = 0, upper = gamma_sigma_bound>[countr_levels] sigma_countr;
// Study-type effect and noise in its estimate
vector[study_levels] gamma_study;
vector<lower = 0, upper = gamma_sigma_bound>[study_levels] sigma_study;
vector[jour_levels] gamma_jour;
vector<lower = 0, upper = gamma_sigma_bound>[jour_levels] sigma_jour;
vector[industry_levels] gamma_industry;
vector<lower = 0, upper = gamma_sigma_bound>[industry_levels] sigma_industry;


// Etas:  contextual effects on study-level standard deviation
vector<lower = 0, upper = eta_bound>[countr_levels] eta_countr;
vector<lower = 0, upper = eta_bound>[study_levels] eta_study;
vector<lower = 0, upper = eta_bound>[jour_levels] eta_jour;
vector<lower = 0, upper = eta_bound>[industry_levels] eta_industry;
}

transformed parameters {
vector[n_study] alpha_hat;                  // Fitted alpha, based only on gammas
vector<lower = 0>[n_study] sigma_hat;       // Fitted sd, based only on sigmasq_hat

for (j in 1:n_study) {
    alpha_hat[j] <- gamma_countr[countr[j]] + gamma_study[studytype[j]] + 
                    gamma_jour[jourtype[j]] + gamma_industry[industrytype[j]];
    sigma_hat[j] <- sqrt(eta_countr[countr[j]]^2 + eta_study[studytype[j]]^2 +
                        eta_jour[jourtype[j]] + eta_industry[industrytype[j]]);
}
}

model {
// Technique for working w/ ragged data from Stan manual, page 135
int pos;
pos <- 1;
for (j in 1:n_study) {
    segment(y, pos, study_n[j]) ~ normal(alpha[j], sigma[j]);
    pos <- pos + study_n[j];
}

// Study-level mean = fitted alpha + Gaussian noise
alpha ~ normal(alpha_hat, sigma_alpha);

// Study-level variance = gamma distribution w/ mean sigma_hat
sigma ~ gamma(.1 * sigma_hat, .1);

// Priors for gammas
gamma_countr ~ normal(gamma_prior_exp, sigma_countr);
gamma_study ~ normal(gamma_prior_exp, sigma_study);
gamma_jour ~ normal(gamma_prior_exp, sigma_study);
gamma_industry ~ normal(gamma_prior_exp, sigma_study);
}
Dan Hicks
fuente