Hi there,
I am working on an ordinal regression problem.
The idea is to model ordinal responses of a survey’s question by using a linear or non-linear combination of a set of predictors, e.g. respondent’s age and gender, under the assumption that the underlying distribution of the response variable is Hurdle Negative Binomial. The survey questions are how often you do something, and the ordinal answers are e.g. every day, once week, once a month, or never.
I have treated the problem as an ordinal regression, and so mapped the survey answers to a set of cut-points.
I have a maximum likelihood solution for this problem. But now I want to use stan to solve the same problem in a Bayesian fashion. The motivation is to put a prior on the cut-points, because respondents don’t literally mean ‘6 months’ but the model treats them like they do.
I can get the hurdle negative binomial to work (thanks BRMS) but I cannot figure out how to do the ordinal negative binomial bit. Below is the code of the stan model.
Thanks in advance for any help.
Likelihood for Ordinal Negative Binomial (doesn’t always work, Log probability evaluates to log(0), i.e. negative infinity. )
data {
int<lower=1> N; // total number of observations
int<lower=2> N_cat; // number of categories
int<lower=1,upper=N_cat> y[N]; // response variable
int<lower=1> K; // number of population-level effects
vector[K] x_means; // column means of X before centering
row_vector[K] x[N]; // pop level variables by row (for looping)
int<lower=0> bound_lo[N_cat]; // lower bound of cut off points
}
transformed data {
}
parameters {
vector[K] beta; // population-level effects
real<lower=0> phi; // neg binomial shape parameter
}
transformed parameters {
}
model {
vector[N_cat] theta;
// prior specifications
// likelihood contribution
for (n in 1:N) {
real eta;
eta = exp(x[n] * beta);
theta[1] = neg_binomial_2_cdf(0 , eta, phi);
for (i in 2:N_cat-1) {
theta[i] = neg_binomial_2_cdf(bound_lo[i] , eta, phi) - neg_binomial_2_cdf(bound_lo[i-1] , eta, phi);
}
theta[N_cat] = 1-neg_binomial_2_cdf(bound_lo[N_cat-1] , eta, phi);
/*if (is_inf(target())){ print("beta params: ",beta); print("phi: ",phi); print("theta is: ", theta); print("log-posterior = ", target()); }*/ y[n] ~ categorical(theta);
}
}
Hi there,
I am working on an ordinal regression problem.
The idea is to model ordinal responses of a survey’s question by using a linear or non-linear combination of a set of predictors, e.g. respondent’s age and gender, under the assumption that the underlying distribution of the response variable is Hurdle Negative Binomial. The survey questions are how often you do something, and the ordinal answers are e.g. every day, once week, once a month, or never.
I have treated the problem as an ordinal regression, and so mapped the survey answers to a set of cut-points. Each cut-point is the number of days a person goes for a run, plays tennis etc a year, e.g. the cut-point of “once a month” is 12, and the cut-point of every day is 365 etc.
I have a maximum likelihood solution for this problem. But now I want to use stan to solve the same problem in a Bayesian fashion. The motivation is to put a prior on the cut-points, because respondents don’t literally mean ‘6 months’ but the model treats them like they do.
I can get the hurdle negative binomial to work (thanks BRMS) but I cannot figure out how to do the ordinal negative binomial bit. Also my stan model is too slow and not sure how can I make it faster. Below is the code of the stan model.
Thanks in advance for any help.
(1) Negative binomial hurdle …. works but ignores cut points
functions {
/* hurdle negative binomial log-PDF of a single response
* logit parameterization for the hurdle part
* Args:
* y: the response value
* eta: linear predictor for negative binomial part
* eta_hu: linear predictor of hurdle part
* shape: shape parameter of negative binomial distribution
* Returns:
* a scalar to be added to the log posterior
*/
real hurdle_neg_binomial_logit_lpmf(int y, real eta, real eta_hu, real shape) {
if (y == 0) {
return bernoulli_logit_lpmf(1 | eta_hu);
} else {
return bernoulli_logit_lpmf(0 | eta_hu) +
neg_binomial_2_log_lpmf(y | eta, shape) -
log(1 - (shape / (exp(eta) + shape))^shape);
}
}
}
data {
int<lower=1> N; // total number of observations
// int<lower=2> N_cat; // number of categories
int y[N]; // response variable
int<lower=1> K; // number of population-level effects
matrix[N, K] X; // centered population-level design matrix
vector[K] X_means; // column means of X before centering
//row_vector[K] x[N]; // pop level variables by row (for looping)
//int<lower=0> bound_lo[N_cat]; // lower bound of cut off points
}
transformed data {
}
parameters {
vector[K] b; // population-level effects
real temp_Intercept; // temporary Intercept
real<lower=0> shape; // shape parameter
real<lower=0,upper=1> hu; // hurdle probability
}
transformed parameters {
}
model {
vector[N] eta;
eta = X * b + temp_Intercept;
// prior specifications
shape ~ gamma(0.01, 0.01);
hu ~ beta(1, 1);
to_vector(b) ~ normal(0,2);
// likelihood contribution
for (n in 1:N) {
y[n] ~ hurdle_neg_binomial(eta[n], hu, shape);
}
}
generated quantities {
real b_Intercept; // population-level intercept
b_Intercept = temp_Intercept - dot_product(X_means, b);
}
1. Likelihood for Ordinal Negative Binomial (doesn’t work, get a sum of theta = NAN objection)
data {
int<lower=1> N; // total number of observations
int<lower=2> N_cat; // number of categories
int<lower=1,upper=N_cat> y[N]; // response variable
int<lower=1> K; // number of population-level effects
// matrix[N, K] X; // centered population-level design matrix
vector[K] x_means; // column means of X before centering
row_vector[K] x[N]; // pop level variables by row (for looping)
int<lower=0> bound_lo[N_cat]; // lower bound of cut off points
}
transformed data {
}
parameters {
vector[K] beta; // population-level effects
//ordered[N_cat-1] c; // temporary thresholds
real<lower=0> phi; // neg binomial shape parameter
}
transformed parameters {
// vector[N] eta; // linear predictor
// compute linear predictor
// eta = X * b;
}
model {
vector[N_cat] theta;
// prior specifications
// to_vector(c) ~ normal(0,5);
// likelihood contribution
for (n in 1:N) {
real eta;
eta = exp(x[n] * beta);
theta[1] = 1 - neg_binomial_2_lcdf(0 | eta, phi);
for (i in 2:N_cat-1) {
theta[i] = log_diff_exp(neg_binomial_2_lcdf(bound_lo[i] | eta, phi),
neg_binomial_2_lcdf(bound_lo[i-1] | eta, phi));
}
theta[N_cat] = neg_binomial_2_lcdf(bound_lo[N_cat-1] | eta, phi);
y[n] ~ categorical(theta);
}
}
CHECKING DATA AND PREPROCESSING FOR MODEL 'ONB_bayes_1' NOW.
COMPILING MODEL 'ONB_bayes_1' NOW.
STARTING SAMPLER FOR MODEL 'ONB_bayes_1' NOW.
SAMPLING FOR MODEL 'ONB_bayes_1' NOW (CHAIN 1). [1] "Rejecting initial value:" [2] " Log probability evaluates to log(0), i.e. negative infinity." [3] " Stan can't start sampling from this initial value." ..
.
[299] " Log probability evaluates to log(0), i.e. negative infinity." [300] " Stan can't start sampling from this initial value." [301] "Initialization between (-2, 2) failed after 100 attempts. " [302] " Try specifying initial values, reducing ranges of constrained values, or reparameterizing the model." [303] "Error in eval(substitute(expr), envir, enclos) : " [1] "error occurred during calling the sampler; sampling not done"