4.5 Modeling in STAN
The code presents the implementation of a multinomial logistic response area model using the programming language STAN. In this model, it is assumed that the response variable in each domain follows a multinomial distribution. The parameters governing the relationship between the predictor variables and the response variable are assumed to be different in each domain and are modeled as random effects.
The functions section defines an auxiliary function called pred_theta(), used to predict the values of the response variable in the unobserved domains. The data section contains the model’s input variables, including the number of domains, the number of response variable categories, direct estimates of the response variable in each domain, observed covariates in each domain, and covariates corresponding to the unobserved domains.
The parameters section defines the model’s unknown parameters, including the beta parameter matrix, containing coefficients relating covariates to the response variable in each category. Standard deviations of the random effects are also included.
The transformed parameters section defines the theta parameter vector, containing the probabilities of belonging to each category of the response variable in each domain. Random effects are used to adjust the values of theta in each domain.
The model section defines the model structure and includes prior distributions for the unknown parameters. Particularly, a normal distribution is used for the coefficients of the beta matrix. Finally, it calculates the likelihood function of the multinomial distribution for the direct estimates of the response variable in each domain.
The generated quantities section is used to compute predictions of the response variable in the unobserved domains using the previously defined auxiliary function.
functions {
matrix pred_theta(matrix Xp, int p, matrix beta){
int D1 = rows(Xp);
real num1[D1, p];
real den1[D1];
matrix[D1,p] theta_p;
matrix[D1,p] tasa_pred;
for(d in 1:D1){
num1[d, 1] = 1;
num1[d, 2] = exp(Xp[d, ] * beta[1, ]' ) ;
num1[d, 3] = exp(Xp[d, ] * beta[2, ]' ) ;
den1[d] = sum(num1[d, ]);
}
for(d in 1:D1){
for(i in 2:p){
theta_p[d, i] = num1[d, i]/den1[d];
}
theta_p[d, 1] = 1/den1[d];
}
for(d in 1:D1){
tasa_pred[d, 1] = theta_p[d,2]/(theta_p[d,1] + theta_p[d,2]);// TD
tasa_pred[d, 2] = theta_p[d,1]; // TO
tasa_pred[d, 3] = theta_p[d,1] + theta_p[d,2]; // TP
}
return tasa_pred ;
}
}
data {
int<lower=1> D; // número de dominios
int<lower=1> P; // categorías
int<lower=1> K; // cantidad de regresores
int hat_y[D, P]; // matriz de datos
matrix[D, K] X_obs; // matriz de covariables
int<lower=1> D1; // número de dominios
matrix[D1, K] X_pred; // matriz de covariables
}
parameters {
matrix[P-1, K] beta;// matriz de parámetros
vector<lower=0>[P-1] sigma_u; // random effects standard deviations
// declare L_u to be the Choleski factor of a 2x2 correlation matrix
cholesky_factor_corr[P-1] L_u;
matrix[P-1, D] z_u;
}
transformed parameters {
simplex[P] theta[D];// vector de parámetros;
real num[D, P];
real den[D];
matrix[D,P] tasa_obs;
// this transform random effects so that they have the correlation
// matrix specified by the correlation matrix above
matrix[P-1, D] u; // random effect matrix
u = diag_pre_multiply(sigma_u, L_u) * z_u;
for(d in 1:D){
num[d, 1] = 1;
num[d, 2] = exp(X_obs[d, ] * beta[1, ]' + u[1, d]) ;
num[d, 3] = exp(X_obs[d, ] * beta[2, ]' + u[2, d]) ;
den[d] = sum(num[d, ]);
}
for(d in 1:D){
for(p in 2:P){
theta[d, p] = num[d, p]/den[d];
}
theta[d, 1] = 1/den[d];
}
for(d in 1:D){
tasa_obs[d, 1] = theta[d,2]/(theta[d,1] + theta[d,2]);// TD
tasa_obs[d, 2] = theta[d,1]; // TO
tasa_obs[d, 3] = theta[d,1] + theta[d,2]; // TP
}
}
model {
L_u ~ lkj_corr_cholesky(1); // LKJ prior for the correlation matrix
to_vector(z_u) ~ normal(0, 10000);
// sigma_u ~ cauchy(0, 50);
sigma_u ~ inv_gamma(0.0001, 0.0001);
for(p in 2:P){
for(k in 1:K){
beta[p-1, k] ~ normal(0, 10000);
}
}
for(d in 1:D){
target += multinomial_lpmf(hat_y[d, ] | theta[d, ]);
}
}
generated quantities {
matrix[D1,P] tasa_pred;
matrix[2, 2] Omega;
Omega = L_u * L_u'; // so that it return the correlation matrix
tasa_pred = pred_theta(X_pred, P, beta);
}