Important: Read this before posting to this forum

  1. This forum is for questions related to the use of Apollo. We will answer some general choice modelling questions too, where appropriate, and time permitting. We cannot answer questions about how to estimate choice models with other software packages.
  2. There is a very detailed manual for Apollo available at http://www.ApolloChoiceModelling.com/manual.html. This contains detailed descriptions of the various Apollo functions, and numerous examples are available at http://www.ApolloChoiceModelling.com/examples.html. In addition, help files are available for all functions, using e.g. ?apollo_mnl
  3. Before asking a question on the forum, users are kindly requested to follow these steps:
    1. Check that the same issue has not already been addressed in the forum - there is a search tool.
    2. Ensure that the correct syntax has been used. For any function, detailed instructions are available directly in Apollo, e.g. by using ?apollo_mnl for apollo_mnl
    3. Check the frequently asked questions section on the Apollo website, which discusses some common issues/failures. Please see http://www.apollochoicemodelling.com/faq.html
    4. Make sure that R is using the latest official release of Apollo.
  4. If the above steps do not resolve the issue, then users should follow these steps when posting a question:
    1. provide full details on the issue, including the entire code and output, including any error messages
    2. posts will not immediately appear on the forum, but will be checked by a moderator first. This may take a day or two at busy times. There is no need to submit the post multiple times.

Multilevel Multinomial logit model

Ask general questions about model specification and estimation that are not Apollo specific but relevant to Apollo users.
Post Reply
tsaghapour
Posts: 7
Joined: 09 Mar 2022, 00:45

Multilevel Multinomial logit model

Post by tsaghapour »

Hi,

I have cluster membership in my data (individuals nested within households), and I want to run a multilevel multinomial logit model. Would you please advise which Apollo example I need to follow?

Regards,
Tayebeh
stephanehess
Site Admin
Posts: 974
Joined: 24 Apr 2020, 16:29

Re: Multilevel Multinomial logit model

Post by stephanehess »

Hi

it's not clear what you mean. Can you explain the specific model structure you are thinking of?

Thanks

Stephane
--------------------------------
Stephane Hess
www.stephanehess.me.uk
tsaghapour
Posts: 7
Joined: 09 Mar 2022, 00:45

Re: Multilevel Multinomial logit model

Post by tsaghapour »

Hi Stephane,

Thanks for getting back to me.

I’m trying to run a multilevel nested logit model. To do so, I need to add a random error component to the model equation to capture the deviation of the intercept of a group from the overall intercept. In other words, I need to run a random intercepts model in which intercepts are allowed to vary, and therefore, the scores on the dependent variable for each individual observation are predicted by the intercept that varies across groups (households in my example). Hence, I am expecting to get the same parameter estimates from both single-level model and multi-level model; however, standard errors should be adjusted for clusters in households.

So, I've run a single-level nested logit model and I've got the results, then I added a random error component to adjust the standard errors for the clusters in household IDs. However, the estimates and standard errors from both the single-level nested logit and the multilevel nested logit are exactly the same. I copied my codes below, I appreciate if you can have a look and advise what could be the issue?

### Clear memory
rm(list = ls())

### Load Apollo library
library(apollo)

### Initialise code
apollo_initialise()

### Set core controls
apollo_control = list(
modelName = "ModeChoice",
modelDescr = "Mixed Nested logit with socio-demographics on mode choice",
indivID = "id",
panelData = FALSE,
mixing = TRUE,
nCores = 4
)

outputDir <- "JIBE/modechoice/"
database <- tripdata
# ################################################################# #
#### LOAD DATA AND APPLY ANY TRANSFORMATIONS ####
# ################################################################# #
#### DEFINE MODEL PARAMETERS
### Vector of parameters, including any that are kept fixed in estimation

apollo_beta =c(b_age_carp = 0, b_age_walk = 0, b_age_cycle = 0, b_age_train = 0, b_age_tram = 0, b_age_bus = 0,
b_male_carp = 0, b_male_walk = 0, b_male_cycle = 0, b_male_train = 0, b_male_tram = 0, b_male_bus = 0,
b_hhsize_carp = 0, b_hhsize_walk = 0, b_hhsize_cycle = 0, b_hhsize_train = 0, b_hhsize_tram = 0, b_hhsize_bus = 0,
b_hhcom_carp = 0, b_hhcom_walk = 0, b_hhcom_cycle = 0, b_hhcom_train = 0, b_hhcom_tram = 0, b_hhcom_bus = 0,
b_inc1_carp = 0, b_inc1_walk = 0, b_inc1_cycle = 0, b_inc1_train = 0, b_inc1_tram = 0, b_inc1_bus = 0,
b_inc2_carp = 0, b_inc2_walk = 0, b_inc2_cycle = 0, b_inc2_train = 0, b_inc2_tram = 0, b_inc2_bus = 0,
b_inc3_carp = 0, b_inc3_walk = 0, b_inc3_cycle = 0, b_inc3_train = 0, b_inc3_tram = 0, b_inc3_bus = 0,
b_inc4_carp = 0, b_inc4_walk = 0, b_inc4_cycle = 0, b_inc4_train = 0, b_inc4_tram = 0, b_inc4_bus = 0,
b_inc6_carp = 0, b_inc6_walk = 0, b_inc6_cycle = 0, b_inc6_train = 0, b_inc6_tram = 0, b_inc6_bus = 0,
b_lic_carp = 0, b_lic_walk = 0, b_lic_cycle = 0, b_lic_train = 0, b_lic_tram = 0, b_lic_bus = 0,
b_cars_carp = 0, b_cars_walk = 0, b_cars_cycle = 0, b_cars_train = 0, b_cars_tram = 0, b_cars_bus = 0,
b_bikes_carp = 0, b_bikes_walk = 0, b_bikes_cycle = 0, b_bikes_train = 0, b_bikes_tram = 0, b_bikes_bus = 0,
b_density_carp = 0, b_density_walk = 0, b_density_cycle = 0, b_density_train = 0, b_density_tram = 0, b_density_bus = 0,
b_si_carp = 0, b_si_walk = 0, b_si_cycle = 0, b_si_train = 0, b_si_tram = 0, b_si_bus = 0,
b_con_carp = 0, b_con_walk = 0, b_con_cycle = 0, b_con_train = 0, b_con_tram = 0, b_con_bus = 0,
#asc_card = 0, asc_carp = 0, asc_walk = 0, asc_cycle = 0, asc_train = 0, asc_tram = 0, asc_bus = 0,
b_costcard = 0, b_costcarp = 0, b_costtrain = 0, b_costtram = 0, b_costbus = 0,
b_timecard = 0, b_timecarp = 0, b_timewalk = 0, b_timecycle = 0, b_timetrain = 0, b_timetram = 0, b_timebus = 0,
sigma_hid = 0,
lambda_car = 1,
lambda_PT = 1)

# ################################################################# #
#### DEFINE RANDOM COMPONENTS ####
# ################################################################# #

### Vector with names (in quotes) of parameters to be kept fixed at their starting value in apollo_beta, use apollo_beta_fixed = c() if none
apollo_fixed = c()

### Set parameters for generating draws
apollo_draws = list(
interDrawsType = "halton",
interNDraws = 500,
interUnifDraws = c(),
interNormDraws = c("draws_hhid"),
intraDrawsType = "mlhs",
intraNDraws = 0,
intraUnifDraws = c(),
intraNormDraws = c()
)

### Create random parameters
apollo_randCoeff = function(apollo_beta, apollo_inputs){
randcoeff = list()

randcoeff[["b_hid"]] = sigma_hid * draws_hhid

return(randcoeff)
}

#### GROUP AND VALIDATE INPUTS
apollo_inputs = apollo_validateInputs()

#### DEFINE MODEL AND LIKELIHOOD FUNCTION ####
# ################################################################# #

apollo_probabilities=function(apollo_beta, apollo_inputs, functionality="estimate"){

### Attach inputs and detach after function exit
apollo_attach(apollo_beta, apollo_inputs)
on.exit(apollo_detach(apollo_beta, apollo_inputs))

### Create list of probabilities P
P = list()

### Create alternative specific constants and coefficients
age_carp_value = b_age_carp * AGE
age_walk_value = b_age_walk * AGE
age_cycle_value = b_age_cycle * AGE
age_train_value = b_age_train * AGE
age_tram_value = b_age_tram * AGE
age_bus_value = b_age_bus * AGE
male_carp_value = b_male_carp * sex
male_cycle_value = b_male_cycle * sex
male_walk_value = b_male_walk * sex
male_train_value = b_male_train * sex
male_tram_value = b_male_tram * sex
male_bus_value = b_male_bus * sex
hhsize_carp_value = b_hhsize_carp * HHSIZE
hhsize_cycle_value = b_hhsize_cycle * HHSIZE
hhsize_walk_value = b_hhsize_walk * HHSIZE
hhsize_train_value = b_hhsize_train * HHSIZE
hhsize_tram_value = b_hhsize_tram * HHSIZE
hhsize_bus_value = b_hhsize_bus * HHSIZE
hhcom_carp_value = b_hhcom_carp * HHcom
hhcom_walk_value = b_hhcom_walk * HHcom
hhcom_cycle_value = b_hhcom_cycle * HHcom
hhcom_train_value = b_hhcom_train * HHcom
hhcom_tram_value = b_hhcom_tram * HHcom
hhcom_bus_value = b_hhcom_bus * HHcom
cars_carp_value = b_cars_carp * CARS
cars_walk_value = b_cars_walk * CARS
cars_cycle_value = b_cars_cycle * CARS
cars_train_value = b_cars_train * CARS
cars_tram_value = b_cars_tram * CARS
cars_bus_value = b_cars_bus * CARS
bikes_carp_value = b_bikes_carp * ADULTBIKES
bikes_walk_value = b_bikes_walk * ADULTBIKES
bikes_cycle_value = b_bikes_cycle * ADULTBIKES
bikes_train_value = b_bikes_train * ADULTBIKES
bikes_tram_value = b_bikes_tram * ADULTBIKES
bikes_bus_value = b_bikes_bus * ADULTBIKES
lic_carp_value = b_lic_carp * NOLICENCE
lic_walk_value = b_lic_walk * NOLICENCE
lic_cycle_value = b_lic_cycle * NOLICENCE
lic_train_value = b_lic_train * NOLICENCE
lic_tram_value = b_lic_tram * NOLICENCE
lic_bus_value = b_lic_bus * NOLICENCE
inc1_carp_value = b_inc1_carp * (HHINCat == 1)
inc1_walk_value = b_inc1_walk * (HHINCat == 1)
inc1_cycle_value = b_inc1_cycle * (HHINCat == 1)
inc1_train_value = b_inc1_train * (HHINCat == 1)
inc1_tram_value = b_inc1_tram * (HHINCat == 1)
inc1_bus_value = b_inc1_bus * (HHINCat == 1)
inc2_carp_value = b_inc2_carp * (HHINCat == 2)
inc2_walk_value = b_inc2_walk * (HHINCat == 2)
inc2_cycle_value = b_inc2_cycle * (HHINCat == 2)
inc2_train_value = b_inc2_train * (HHINCat == 2)
inc2_tram_value = b_inc2_tram * (HHINCat == 2)
inc2_bus_value = b_inc2_bus * (HHINCat == 2)
inc3_carp_value = b_inc3_carp * (HHINCat == 3)
inc3_walk_value = b_inc3_walk * (HHINCat == 3)
inc3_cycle_value = b_inc3_cycle * (HHINCat == 3)
inc3_train_value = b_inc3_train * (HHINCat == 3)
inc3_tram_value = b_inc3_tram * (HHINCat == 3)
inc3_bus_value = b_inc3_bus * (HHINCat == 3)
inc4_carp_value = b_inc4_carp * (HHINCat == 4)
inc4_walk_value = b_inc4_walk * (HHINCat == 4)
inc4_cycle_value = b_inc4_cycle * (HHINCat == 4)
inc4_train_value = b_inc4_train * (HHINCat == 4)
inc4_tram_value = b_inc4_tram * (HHINCat == 4)
inc4_bus_value = b_inc4_bus * (HHINCat == 4)
inc6_carp_value = b_inc6_carp * (HHINCat == 6)
inc6_walk_value = b_inc6_walk * (HHINCat == 6)
inc6_cycle_value = b_inc6_cycle * (HHINCat == 6)
inc6_train_value = b_inc6_train * (HHINCat == 6)
inc6_tram_value = b_inc6_tram * (HHINCat == 6)
inc6_bus_value = b_inc6_bus * (HHINCat == 6)
den_carp_value = b_density_carp * gn_dd_nh1600m
den_walk_value = b_density_walk * gn_dd_nh1600m
den_cycle_value = b_density_cycle * gn_dd_nh1600m
den_train_value = b_density_train * gn_dd_nh1600m
den_tram_value = b_density_tram * gn_dd_nh1600m
den_bus_value = b_density_bus * gn_dd_nh1600m
con_carp_value = b_con_carp * gn_sc_nh1600m
con_walk_value = b_con_walk * gn_sc_nh1600m
con_cycle_value = b_con_cycle * gn_sc_nh1600m
con_train_value = b_con_train * gn_sc_nh1600m
con_tram_value = b_con_tram * gn_sc_nh1600m
con_bus_value = b_con_bus * gn_sc_nh1600m
si_carp_value = b_si_carp * si_mix
si_walk_value = b_si_walk * si_mix
si_cycle_value = b_si_cycle * si_mix
si_train_value = b_si_train * si_mix
si_tram_value = b_si_tram * si_mix
si_bus_value = b_si_bus * si_mix

### List of utilities: these must use the same names as in nl_settings, order is irrelevant
V = list()
V[['CarD']] = b_timecard * time_card + b_costcard * cost_card + b_hid
V[['CarP']] = si_carp_value + con_carp_value + den_carp_value + age_carp_value + male_carp_value + hhsize_carp_value + hhcom_carp_value + cars_carp_value + bikes_carp_value + lic_carp_value + inc1_carp_value + inc2_carp_value + inc3_carp_value + inc4_carp_value + inc6_carp_value + b_timecarp * time_carp + b_costcarp * cost_carp
V[['Walk']] = si_walk_value + con_walk_value + den_walk_value + age_walk_value + male_walk_value + hhsize_walk_value + hhcom_walk_value + cars_walk_value + bikes_walk_value + lic_walk_value + inc1_walk_value + inc2_walk_value + inc3_walk_value + inc4_walk_value + inc6_walk_value + b_timewalk * time_walk
V[['Cycle']] = si_cycle_value + con_cycle_value + den_cycle_value + age_cycle_value + male_cycle_value + hhsize_cycle_value + hhcom_cycle_value + cars_cycle_value + bikes_cycle_value + lic_cycle_value + inc1_cycle_value + inc2_cycle_value + inc3_cycle_value + inc4_cycle_value + inc6_cycle_value + b_timecycle * time_bicycle
V[['Train']] = si_train_value + con_train_value + den_train_value + age_train_value + male_train_value + hhsize_train_value + hhcom_train_value + cars_train_value + bikes_train_value + lic_train_value + inc1_train_value + inc2_train_value + inc3_train_value + inc4_train_value + inc6_train_value + b_timetrain * time_train + b_costtrain * cost_train
V[['Tram']] = si_tram_value + con_tram_value + den_tram_value + age_tram_value + male_tram_value + hhsize_tram_value + hhcom_tram_value + cars_tram_value + bikes_tram_value + lic_tram_value + inc1_tram_value + inc2_tram_value + inc3_tram_value + inc4_tram_value + inc6_tram_value + b_timetram * time_tram + b_costtram * cost_tram
V[['Bus']] = si_bus_value + con_bus_value + den_bus_value + age_bus_value + male_bus_value + hhsize_bus_value + hhcom_bus_value + cars_bus_value + bikes_bus_value + lic_bus_value + inc1_bus_value + inc2_bus_value + inc3_bus_value + inc4_bus_value + inc6_bus_value + b_timebus * time_bus + b_costbus * cost_bus

### Specify nests for NL model
nlNests = list(root=1, car = lambda_car, PT=lambda_PT)

### Specify tree structure for NL model
nlStructure = list()
nlStructure[["root"]] = c("car","Walk","Cycle","PT")
nlStructure[["car"]] = c("CarD","CarP")
nlStructure[["PT"]] = c("Train","Tram","Bus")

### Define settings for MNL model component
nl_settings = list(
alternatives = c(CarD= 1, CarP= 2, Walk = 3, Cycle = 4, Train = 5, Tram = 6, Bus= 7),
choiceVar = mainmode,
avail = list(CarD=av_card, CarP=av_carp, Walk=av_walk, Cycle=av_cycle, Train=av_train, Tram=av_tram, Bus=av_bus),
V = V,
nlNests = nlNests,
nlStructure = nlStructure
)

### Compute probabilities using MNL model
P[['model']] = apollo_nl(nl_settings, functionality)

### Average across inter-individual draws
P = apollo_avgInterDraws(P, apollo_inputs, functionality)

### Prepare and return outputs of function
#P = apollo_weighting(P, apollo_inputs, functionality)
P = apollo_prepareProb(P, apollo_inputs, functionality)
return(P)
}

# ################################################################# #
#### MODEL ESTIMATION ####
# ################################################################# #

model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs)


Thanks and regards,
Tayebeh
stephanehess
Site Admin
Posts: 974
Joined: 24 Apr 2020, 16:29

Re: Multilevel Multinomial logit model

Post by stephanehess »

Hi

could you explain this mathematically maybe?

Stephane
--------------------------------
Stephane Hess
www.stephanehess.me.uk
tsaghapour
Posts: 7
Joined: 09 Mar 2022, 00:45

Re: Multilevel Multinomial logit model

Post by tsaghapour »

Hi Stephane,

Thanks for your reply. The only thing that I could find was equations for single and multilevel multinomial regression models. I am trying to run similar model for nested logit. I couldn't attach the word file, so I copied them here. I hope that's clear.

Single-level multinomial logistic regression

Suppose that yi is the unordered categorical response for individual i, and that the response variable has t categories. We denote the probability of being in category s by π_i^((s)) = Pr(yi = s). In a multinomial logistic model, one of the response categories is taken as the reference category, just as the category coded ‘0’ is usually taken as the reference category in a binary response model. A set of t-1 equations is then estimated, contrasting each of the remaining response categories with the chosen reference category. Suppose that the last category is taken as the reference. Then, for a single explanatory variable xi,

log⁡((π_i^((s) ))/(π_i^((t) ) ))= β_0^((s))+β_1^((s)) x_i, s=1,….,t-1 (10.1)

A separate intercept and slope parameter is usually estimated for each contrast, as indicated by the s superscripts, although it is possible to constrain some or all to be equal. In the model above, the same explanatory variable appears in each of the t − 1 contrasts.

The parameter β_1^((s)) is interpreted as the additive effect of a 1-unit increase in x on the log-odds of being in category s rather than category t. As in the binary logit model, it is more meaningful to interpret exp⁡(β_1^((s))), which is the multiplicative effect of a 1-unit increase in x on the odds of being in category s rather than category t. However, an easier way to interpret the effect of x is to calculate predicted probabilities π_i^((s)) (s = 1, . . . , t) for different values of x.

The following expression for π_i^((s)) (s = 1, . . . , t−1) can be derived from (10.1):

π_i^((s) )=(exp⁡(β_0^((s))+β_1^((s)) x_i))/(1+∑_(k=1)^(t-1)▒〖(β_0^((k))+β_1^((k)) x_i)〗) (10.2)

The probability of being in the reference category t is obtained by subtraction:

π_i^((t) )=1-∑_(k-1)^(t-1)▒π_i^((k) )
(10.3)
A two-level random intercept multinomial logistic regression model

Suppose that yij is the categorical response for individual i in district j, and denote the probability of being in category s by π_ij^((s)). Equation (10.1) can be a two-level random intercept model:

log⁡((π_i^((s) ))/(π_i^((t) ) ))=β_0^((s))+β_1^((s)) x_ij+u_j^((s)), s=1,…,t-1 (10.4)

where u_j^((s)) is a district-level random effect, assumed to be Normally distributed with mean 0 and variance σ2(s). The random effects are contrast- specific, as indicated by the s superscript, because different unobserved district-level factors may affect each contrast. Or, equivalently, the intra-district correlation in contraceptive use may vary by type of method. However, the random effects may be correlated across contrasts: cov(u_j^((s)),u_j^((r)))=σ_u^((s,r))≠r. Correlated random effects would arise, for example, if there were unobserved district-level factors which affect the choice of more than one method type.

Thanks for your support.

Regards,
Tayebeh
tsaghapour
Posts: 7
Joined: 09 Mar 2022, 00:45

Re: Multilevel Multinomial logit model

Post by tsaghapour »

Hi Stephane,

Thanks for your reply. I couldn't write down the equations here, so I shared the document in which it shows the mathematical difference between single and multilevel multinational logistic regression models. Can you please have a look and advise if I can do it using apollo package?

https://1drv.ms/w/s!Aqvuf8oT9xIpgeILb4H ... w?e=fpWbQe

Regards,
Tayebeh
stephanehess
Site Admin
Posts: 974
Joined: 24 Apr 2020, 16:29

Re: Multilevel Multinomial logit model

Post by stephanehess »

Hi

apologies for the slow reply.

It's still not quite clear what you are aiming to do here. Is it a case of capturing correlation between individuals within a group?

Stephane
--------------------------------
Stephane Hess
www.stephanehess.me.uk
tsaghapour
Posts: 7
Joined: 09 Mar 2022, 00:45

Re: Multilevel Multinomial logit model

Post by tsaghapour »

Hi Stephane,

Thanks so much for your reply.

Yes, that's right. I want to capture the correlation between individuals within a group. Would please advise if this is achievable with the Apollo package? If so, how I can do that?

Many thanks and regards,
Tayebeh
stephanehess
Site Admin
Posts: 974
Joined: 24 Apr 2020, 16:29

Re: Multilevel Multinomial logit model

Post by stephanehess »

Hi

this is not something Apollo is readily set up to do. You could contemplate a model with error components at the group level, possibly, but you'd need to think carefully about the setup and theoretical as well as empirical identification of the model

Stephane
--------------------------------
Stephane Hess
www.stephanehess.me.uk
Post Reply