7.2 Preparando los insumos para STAN
- Dividir la base de datos en dominios observados y no observados.
Dominios observados.
<- base_FH %>% filter(!is.na(pobreza)) data_dir
Dominios NO observados.
<-
data_syn %>% anti_join(data_dir %>% select(dam2))
base_FH tba(data_syn[1:10,1:8])
dam2 | nd | pobreza | vardir | hat_var | modificacion_humana | accesibilidad_hospitales | accesibilidad_hosp_caminado |
---|---|---|---|---|---|---|---|
00202 | NA | NA | NA | NA | -0.3758 | 0.0000 | 0.1482 |
00203 | NA | NA | NA | NA | -0.9259 | 0.5732 | -0.1402 |
00204 | NA | NA | NA | NA | -1.3166 | 1.1111 | 0.4438 |
00205 | NA | NA | NA | NA | -0.7474 | 2.1155 | 1.2271 |
00207 | NA | NA | NA | NA | 1.7368 | -0.7648 | -0.4861 |
00208 | NA | NA | NA | NA | -0.5942 | 0.3212 | -0.1697 |
00209 | NA | NA | NA | NA | -1.5280 | 3.0192 | 1.9428 |
00210 | NA | NA | NA | NA | -1.0038 | 0.5778 | 0.2678 |
00305 | NA | NA | NA | NA | -0.8480 | 1.5047 | 3.2004 |
00404 | NA | NA | NA | NA | -0.5678 | 1.0735 | 0.9856 |
- Definir matriz de efectos fijos.
Define un modelo lineal utilizando la función formula()
, que incluye varias variables predictoras, como la edad, la etnia, la tasa de desocupación, entre otras.
Utiliza la función model.matrix()
para generar matrices de diseño (Xdat
y Xs
) a partir de los datos observados (data_dir
) y no observados (data_syn
) para utilizar en la construcción de modelos de regresión. La función model.matrix()
convierte las variables categóricas en variables binarias (dummy), de manera que puedan ser utilizadas.
<- formula(~ sexo2 +
formula_mod +
anoest2 +
anoest3 +
anoest4 +
edad2 +
edad3 +
edad4 +
edad5 +
tasa_desocupacion +
luces_nocturnas +
cubrimiento_cultivo
alfabeta)## Dominios observados
<- model.matrix(formula_mod, data = data_dir)
Xdat
## Dominios no observados
<- model.matrix(formula_mod, data = data_syn) Xs
Ahora, se utiliza la función setdiff()
para identificar las columnas de Xdat
que no están presentes en \(X_s\), es decir, las variables que no se encuentran en los datos no observados. A continuación, se crea una matriz temporal (temp
) con ceros para las columnas faltantes de \(X_s\), y se agregan estas columnas a \(X_s\) utilizando cbind()
. El resultado final es una matriz Xs
con las mismas variables que Xdat
, lo que asegura que se puedan realizar comparaciones adecuadas entre los datos observados y no observados en la construcción de modelos de regresión. En general, este código es útil para preparar los datos para su posterior análisis y asegurar que los modelos de regresión sean adecuados para su uso.
<- setdiff(colnames(Xdat),colnames(Xs))
temp
<- matrix(
temp 0,
nrow = nrow(Xs),
ncol = length(temp),
dimnames = list(1:nrow(Xs), temp)
)
<- cbind(Xs,temp)[,colnames(Xdat)] Xs
- Creando lista de parámetros para
STAN
<- list(
sample_data N1 = nrow(Xdat), # Observados.
N2 = nrow(Xs), # NO Observados.
p = ncol(Xdat), # Número de regresores.
X = as.matrix(Xdat), # Covariables Observados.
Xs = as.matrix(Xs), # Covariables NO Observados
y = as.numeric(data_dir$pobreza), # Estimación directa
sigma_e = sqrt(data_dir$hat_var) # Error de estimación
)
Rutina implementada en STAN
data {<lower=0> N1; // number of data items
int<lower=0> N2; // number of data items for prediction
int<lower=0> p; // number of predictors
int// predictor matrix
matrix[N1, p] X; // predictor matrix
matrix[N2, p] Xs; // predictor matrix
vector[N1] y; // known variances
vector[N1] sigma_e;
}
parameters {// coefficients for predictors
vector[p] beta; <lower=0> sigma2_u;
real
vector[N1] u;
}
transformed parameters{
vector[N1] theta;
vector[N1] thetaSyn;
vector[N1] thetaFH;
vector[N1] gammaj;<lower=0> sigma_u;
real= X * beta;
thetaSyn = thetaSyn + u;
theta = sqrt(sigma2_u);
sigma_u = to_vector(sigma_u ./ (sigma_u + sigma_e));
gammaj = (gammaj) .* y + (1-gammaj).*thetaSyn;
thetaFH
}
model {// likelihood
~ normal(theta, sigma_e);
y // priors
~ normal(0, 100);
beta ~ normal(0, sigma_u);
u ~ inv_gamma(0.0001, 0.0001);
sigma2_u
}
generated quantities{
vector[N2] y_pred;for(j in 1:N2) {
= normal_rng(Xs[j] * beta, sigma_u);
y_pred[j]
} }
- Compilando el modelo en
STAN
. A continuación mostramos la forma de compilar el código deSTAN
desde R.
En este código se utiliza la librería rstan
para ajustar un modelo bayesiano utilizando el archivo 17FH_normal.stan
que contiene el modelo escrito en el lenguaje de modelado probabilístico Stan.
En primer lugar, se utiliza la función stan()
para ajustar el modelo a los datos de sample_data
. Los argumentos que se pasan a stan()
incluyen el archivo que contiene el modelo (fit_FH_normal
), los datos (sample_data
), y los argumentos para controlar el proceso de ajuste del modelo, como el número de iteraciones para el período de calentamiento (warmup
) y el período de muestreo (iter
), y el número de núcleos de la CPU para utilizar en el proceso de ajuste (cores
).
Además, se utiliza la función parallel::detectCores()
para detectar automáticamente el número de núcleos disponibles en la CPU, y se establece la opción mc.cores
para aprovechar el número máximo de núcleos disponibles para el ajuste del modelo.
El resultado del ajuste del modelo es almacenado en model_FH_normal
, que contiene una muestra de la distribución posterior del modelo, la cual puede ser utilizada para realizar inferencias sobre los parámetros del modelo y las predicciones. En general, este código es útil para ajustar modelos bayesianos utilizando Stan y realizar inferencias posteriores.
library(rstan)
<- "Recursos/Día2/Sesion3/Data/modelosStan/17FH_normal.stan"
fit_FH_normal options(mc.cores = parallel::detectCores())
<- stan(
model_FH_normal file = fit_FH_normal,
data = sample_data,
verbose = FALSE,
warmup = 500,
iter = 1000,
cores = 4
)saveRDS(object = model_FH_normal,
file = "Recursos/Día2/Sesion3/Data/model_FH_normal.rds")
Leer el modelo
<- readRDS("Recursos/Día2/Sesion3/Data/model_FH_normal.rds") model_FH_normal
7.2.1 Resultados del modelo para los dominios observados.
En este código, se cargan las librerías bayesplot
, posterior
y patchwork
, que se utilizan para realizar gráficos y visualizaciones de los resultados del modelo.
A continuación, se utiliza la función as.array()
y as_draws_matrix()
para extraer las muestras de la distribución posterior del parámetro theta
del modelo, y se seleccionan aleatoriamente 100 filas de estas muestras utilizando la función sample()
, lo que resulta en la matriz y_pred2.
Finalmente, se utiliza la función ppc_dens_overlay()
de bayesplot
para graficar una comparación entre la distribución empírica de la variable observada pobreza en los datos (data_dir$pobreza
) y las distribuciones predictivas posteriores simuladas para la misma variable (y_pred2
). La función ppc_dens_overlay()
produce un gráfico de densidad para ambas distribuciones, lo que permite visualizar cómo se comparan.
library(bayesplot)
library(posterior)
library(patchwork)
<- as.array(model_FH_normal, pars = "theta") %>%
y_pred_B as_draws_matrix()
<- sample(nrow(y_pred_B), 100)
rowsrandom <- y_pred_B[rowsrandom, ]
y_pred2 ppc_dens_overlay(y = as.numeric(data_dir$pobreza), y_pred2)
Análisis gráfico de la convergencia de las cadenas de \(\sigma^2_V\).
<- as.array(model_FH_normal, pars = "sigma2_u")
posterior_sigma2_u mcmc_dens_chains(posterior_sigma2_u) +
(mcmc_areas(posterior_sigma2_u) ) /
mcmc_trace(posterior_sigma2_u)
#traceplot(model_FH_normal, pars = "sigma2_u", inc_warmup = TRUE)
Como método de validación se comparan las diferentes elementos de la estimación del modelo de FH obtenidos en STAN
<- summary(model_FH_normal,pars = "theta")$summary %>%
theta data.frame()
<- summary(model_FH_normal,pars = "thetaSyn")$summary %>%
thetaSyn data.frame()
<- summary(model_FH_normal,pars = "thetaFH")$summary %>%
theta_FH data.frame()
%<>% mutate(
data_dir thetadir = pobreza,
theta_pred = theta$mean,
thetaSyn = thetaSyn$mean,
thetaFH = theta_FH$mean,
theta_pred_EE = theta$sd,
Cv_theta_pred = theta_pred_EE/theta_pred
) # saveRDS(data_dir,"Recursos/Día2/Sesion3/0Recursos/data_dir.rds")
# Estimación predicción del modelo vs ecuación ponderada de FH
<- ggplot(data_dir, aes(x = theta_pred, y = thetaFH)) +
p11 geom_point() +
geom_abline(slope = 1,intercept = 0, colour = "red") +
theme_bw(10)
# Estimación con la ecuación ponderada de FH Vs estimación sintética
<- ggplot(data_dir, aes(x = thetaSyn, y = thetaFH)) +
p12 geom_point() +
geom_abline(slope = 1,intercept = 0, colour = "red") +
theme_bw(10)
# Estimación con la ecuación ponderada de FH Vs estimación directa
<- ggplot(data_dir, aes(x = thetadir, y = thetaFH)) +
p21 geom_point() +
geom_abline(slope = 1,intercept = 0, colour = "red") +
theme_bw(10)
# Estimación directa Vs estimación sintética
<- ggplot(data_dir, aes(x = thetadir, y = thetaSyn)) +
p22 geom_point() +
geom_abline(slope = 1,intercept = 0, colour = "red") +
theme_bw(10)
+p12)/(p21+p22) (p11
Estimación del FH de la pobreza en los dominios NO observados.
<- summary(model_FH_normal,pars = "y_pred")$summary %>%
theta_syn_pred data.frame()
<- data_syn %>%
data_syn mutate(
theta_pred = theta_syn_pred$mean,
thetaSyn = theta_pred,
thetaFH = theta_pred,
theta_pred_EE = theta_syn_pred$sd,
Cv_theta_pred = theta_pred_EE/theta_pred)
#saveRDS(data_syn,"Recursos/Día2/Sesion3/0Recursos/data_syn.rds")
tba(data_syn %>% slice(1:10) %>%
select(dam2:hat_var,theta_pred:Cv_theta_pred))
dam2 | nd | pobreza | vardir | hat_var | theta_pred | thetaSyn | thetaFH | theta_pred_EE | Cv_theta_pred |
---|---|---|---|---|---|---|---|---|---|
00202 | NA | NA | NA | NA | 0.2939 | 0.2939 | 0.2939 | 0.0934 | 0.3177 |
00203 | NA | NA | NA | NA | 0.2816 | 0.2816 | 0.2816 | 0.0881 | 0.3131 |
00204 | NA | NA | NA | NA | 0.2930 | 0.2930 | 0.2930 | 0.0916 | 0.3128 |
00205 | NA | NA | NA | NA | 0.1812 | 0.1812 | 0.1812 | 0.0977 | 0.5392 |
00207 | NA | NA | NA | NA | 0.3500 | 0.3500 | 0.3500 | 0.0921 | 0.2632 |
00208 | NA | NA | NA | NA | 0.2330 | 0.2330 | 0.2330 | 0.1001 | 0.4294 |
00209 | NA | NA | NA | NA | 0.2275 | 0.2275 | 0.2275 | 0.1214 | 0.5338 |
00210 | NA | NA | NA | NA | 0.2784 | 0.2784 | 0.2784 | 0.1013 | 0.3639 |
00305 | NA | NA | NA | NA | 0.4831 | 0.4831 | 0.4831 | 0.0975 | 0.2019 |
00404 | NA | NA | NA | NA | 0.4305 | 0.4305 | 0.4305 | 0.1088 | 0.2527 |
consolidando las bases de estimaciones para dominios observados y NO observados.
<- bind_rows(data_dir, data_syn) %>%
estimacionesPre select(dam2, theta_pred)