# Conditional logit function creation

I am in a stage of learning to use Stan and Rstan for modeling hierarchical problems. I am trying to create my own in stan function to estimate conditional logit models, but in my function definition I have some problem. I am writing to see if it is possible for you to help me. I share my code:

``````functions {
real my_logit(int choice, matrix Xm, row_vector[K] eta) {
vector[rows(Xm)] probs;
probs = softmax(Xm * eta);
return categorical_lpmf(choice| probs);
}
}
data{
int<lower=2> J; // of alternatives/outcomes
int<lower=1> N;  // of observations
int<lower=1> K; // of covariates
int<lower=0,upper=J> Y[N];
matrix[J,K] X[N];
}

parameters {
vector[K] beta;  // attribute effects
}

model{
for (i in 1:N)
my_logit(Y[i],X[i,i],beta[1:K])
}
``````

[edit: escape formatting]

The problem here is that you’re not incrementing the target log density. Your model loop should be this:

``````for (n in 1:N) {
target += my_logit(Y[n], X[n, n], beta);
}
``````

But you’ll find this won’t compile because your matrix operations are not going to conform dimensionally. Multi-logit has a vector of covariates per item and a matrix of parameters. But you have to be careful about identifiability and even if you get all this right, your model won’t work without an identification strategy (such as a prior on `beta`).

For the idiomatic way to define multi-logit and a discussion of identifiability in Stan, see:

We also have a more stable `categorical_logit` built-in which does the softmax internally.

Hello, maybe there is a confusion. The function is rather a nice conditional logit where each alternative or possible value of y has its predictor variables. I’ll give you a data generating function in R. for more detail.

``````generate_mnl_data <- function(N=1000, K=2, J=3, beta=c(1, -2)){
if(length(beta) != K) stop ("incorrect number of parameters")
Y <- rep(NA, N)
X <- list(NULL)
for (i in 1:N) {
X[[i]] <- matrix(rnorm(J*K), ncol=K)
Y[i] <- sample(x=J, size=1, prob=exp(X[[i]]%*%beta))
}
list(N=N, J=J, K=K, Y=Y, X=X, beta=beta)
}
d0 <- generate_mnl_data()
``````

where K is the number of attributes of the alternatives, J are the alternatives and N the individuals

I don’t know R that well. Is that prob statement just going to normalize, so the real probabilities would be `softmax(X[[I]] %*% beta)`?

I had to look up R’s sample function—that takes a single draw with probabilities proportional to the `prob` argument. So this really just is a categorical softmax thing. So the code is very simple and matches yours, but I didn’t use a function and I used `categorical_logit` (which applies softmax to its argument).

``````data {
int<lower=2> J;
int<lower=1> N;
int<lower=1> K;
array[N] int<lower=1, upper=J> y;
array[N] matrix[J, K] x;
}
parameters {
vector[K] beta;
}
model {
for (n in 1:N) {
y[n] ~ categorical_logit(x[n] * beta);
}
}
``````

This model is overparameterized as described in the user’s guide section I linked in the last reply. Thus it’s not identified and won’t work as is. The section discusses strategies for identification:

1. Pin one of the value sin `beta` to 0.
2. Enforce a sum-to-zero constraint on `beta`
3. Put a proper prior on `beta`

The code for these strategies are discussed in our user’s guide. For pinning you declare `vector[K - 1] beta_prefix` and then append a 0 to the end (or beginning) to define `beta`. For sum-to-zero, you declare also with `K - 1` and then set the last value to the negative sum of the first elements. For prior, you can leave it as K.

Thank you.