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.

Two level Nested Logit(NL) model specification for many alternatives

Ask questions about model specifications. Ideally include a mathematical explanation of your proposed model.
Post Reply
lucia
Posts: 4
Joined: 06 Apr 2022, 06:28

Two level Nested Logit(NL) model specification for many alternatives

Post by lucia »

Hi Prof. Stephane Hess,

I am currently estimating a nested logit model with location choice (randomly choose three alternatives, 'alt2', 'alt3', 'alt4', from all TAZ zones, and 'alt1' is always the choosing TAZ zone for an individual ) as the upper level and utility for four different travel modes ('Auto,'' Passenger,' 'Rideshare,' 'PT') as the lower level. I encountered two questions with the model specification, and I am writing to ask for your kind suggestions.

The two questions are:
1) I have both TAZ alternative-specific variables (b_LogCensusEmploy & b_LogCensuspop) and mode-specific variables (c_AutoPassUtil, C_Rideshare, C_PTUtil). Currently, I am coding the utility function as follows:

Code: Select all

    ### List of utilities
      V = list()
      for(s in 1:4){
      V[[paste0("Auto",s)]] = 0
   
      V[[paste0("Passenger",s)]] = get(paste0("asc_AutoPassen",s)) +
        b_LogCensusEmploy* get(paste0("CensusEmploy",s )) +
        b_LogCensuspop* get(paste0("CensusPop",s )) +
        C_AutoPassUtil* get(paste0("Auto_util",s))
   
      V[[paste0("Rideshare",s)]] = get(paste0("asc_Rideshare",s))+
        b_LogCensusEmploy* get(paste0("CensusEmploy",s )) +
        b_LogCensuspop* get(paste0("CensusPop",s )) +
        C_Rideshare* get(paste0("Auto_util",s)) *0.8
   
      V[[paste0("PT",s)]] = get(paste0("asc_PT",s)) +
        b_LogCensusEmploy* get(paste0("CensusEmploy",s )) +
        b_LogCensuspop* get(paste0("CensusPop",s )) +
        C_PTUtil* get(paste0("PT_util",s))

It seems inappropriate to put both alternative-specific variables and mode-specific variables in the same format as above, but I don't know what the appropriate way is to join both alternative and mode-specific variables in the utility function.

2) For the nlStructure settings, I tried to code it as a loop as I want to join more TAZ alternatives for the next step (currently random select 3 out of 1757 TAZs, extend it to random select 219 out of 1757 TAZs afterward). I coded the tree structure based on one of the questions you answered in the forum. However, when I estimated using the following codes, the LLstart became 0. I think there should be something wrong with the tree structure setting part, but when I ran the code separately, it generated the right tree structure.

Code: Select all

    ### Specify tree structure for NL model
     list_alt = paste0("alt",1:4)
     nlStructure = matrix(paste0(rep(c('Auto','Passenger','Rideshare','PT'), times=4), rep(1:4, each=4)), ncol=4, byrow=TRUE)
     nlStructure = setNames(split(nlStructure, 1:length(list_alt)), list_alt)
     nlStructure[['root']] = as.character(list_alt)
Thank you for your time and for developing the Apollo package!

Attached code below:

Code: Select all

  rm(list = ls())
  library(apollo)
  apollo_initialise()
  
  # #################################################################
  
  #### LOAD DATA AND APPLY ANY TRANSFORMATIONS
  
  # #################################################################
  
  database = read.csv(".\\02_TAZ_availablematrix_V2.csv", header = TRUE) 

  database <- database %>% 
    mutate(jointchoice = groupe_modes)

  #View(database)
  apollo_control = list(
    modelName  ="Apollo_NL",
    modelDescr ="Two-level NL model with Location and Mode choice",
    nCores    = 4,
    panelData=FALSE,
    indivID = "AID"
  )
   
  list_loc <- unique(seq(1, 4, by=1))   
  
  apollo_beta=c(c(
                asc_AutoPassen1        = 0,
                asc_Rideshare1         = 0,
                asc_PT1                = 0,
                asc_AutoPassen2        = 0,
                asc_Rideshare2         = 0,
                asc_PT2                = 0,
                asc_AutoPassen3        = 0,
                asc_Rideshare3         = 0,
                asc_PT3                = 0,
                asc_AutoPassen4        = 0,
                asc_Rideshare4         = 0,
                asc_PT4                = 0,
                C_AutoPassUtil         = 1,
                C_Rideshare            = 1,
                C_PTUtil               = 1,
 #               b_Dist                 = 0,
                b_LogCensusEmploy      = -3,
                b_LogCensuspop         = -3),
                setNames(rep(0.5, length(list_loc)), paste0("lamda", list_loc))
  )
 

  apollo_fixed =c()
  
  ### Group and validate inputs
  apollo_inputs = apollo_validateInputs()
  
  
  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()

    ### List of utilities: these must use the same names as in nl_settings, order is irrelevant
    V = list()
    
    for(s in 1:4){
      V[[paste0("Auto",s)]] = 0
    
      V[[paste0("Passenger",s)]] = get(paste0("asc_AutoPassen",s)) + 
        b_LogCensusEmploy* get(paste0("CensusEmploy",s )) +
        b_LogCensuspop* get(paste0("CensusPop",s )) + 
        C_AutoPassUtil* get(paste0("Auto_util",s))
    
      V[[paste0("Rideshare",s)]] = get(paste0("asc_Rideshare",s))+ 
        b_LogCensusEmploy* get(paste0("CensusEmploy",s )) +
        b_LogCensuspop* get(paste0("CensusPop",s )) + 
        C_Rideshare* get(paste0("Auto_util",s)) *0.8
    
      V[[paste0("PT",s)]] = get(paste0("asc_PT",s)) + 
        b_LogCensusEmploy* get(paste0("CensusEmploy",s )) +
        b_LogCensuspop* get(paste0("CensusPop",s )) + 
        C_PTUtil* get(paste0("PT_util",s))
    
      }

     nlNests = list(root=1)
     for (loc in 1:4) {
     nlNests[[paste0("alt",loc)]] <- get(paste0("lamda", loc))
     }
    
    ### Specify tree structure for NL model
     list_alt = paste0("alt",1:4)
     nlStructure = matrix(paste0(rep(c('Auto','Passenger','Rideshare','PT'), times=4), rep(1:4, each=4)), ncol=4, byrow=TRUE)
     nlStructure = setNames(split(nlStructure, 1:length(list_alt)), list_alt)
     nlStructure[['root']] = as.character(list_alt)
      
     #nlStructure= list() 
     #nlStructure[["root"]] = c("alt1","alt2","alt3","alt4")
     #nlStructure[["alt1"]] = c("Auto1","Passenger1","Rideshare1","PT1")
     #nlStructure[["alt2"]] = c("Auto2","Passenger2","Rideshare2","PT2")
     #nlStructure[["alt3"]] = c("Auto3","Passenger3","Rideshare3","PT3")
     #nlStructure[["alt4"]] = c("Auto4","Passenger4","Rideshare4","PT4")
    
     # Define settings for NL model
      nl_settings <- list(
        alternatives = c(Auto1=1,  Passenger1=2,  Rideshare1=3,  PT1=4,
                         Auto2=5,  Passenger2=6,  Rideshare2=7,  PT2=8,
                         Auto3=9,  Passenger3=10, Rideshare3=11, PT3=12,
                         Auto4=13, Passenger4=14, Rideshare4=15, PT4=16),
      
        avail        = 1,
        choiceVar    = jointchoice,
        V            = V,
        nlNests      = nlNests,
        nlStructure  = nlStructure
      )
    
    ### Compute probabilities using NL model
    
    ## Take product across observation for same individual
    #P = apollo_panelProd(P, apollo_inputs, functionality)
    P[["model"]] = apollo_nl(nl_settings, functionality)
    ### Prepare and return outputs of function
    P = apollo_prepareProb(P, apollo_inputs, functionality)
    return(P)
  }
  
  estimate_settings <- list(maxIterations = 10000)
  
  ### Optional starting values search
  apollo_beta=apollo_searchStart(apollo_beta, apollo_fixed,apollo_probabilities, apollo_inputs)
  # #################################################################
  
  #### MODEL ESTIMATION
  
  # #################################################################
  
  NLmodel = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs)
  #tmp=apollo_probabilities(apollo_beta,apollo_inputs,functionality="output")
}



apollo_modelOutput(NLmodel)

predictions_base = apollo_prediction(NLmodel, apollo_probabilities, apollo_inputs,
                                     prediction_settings=list(runs=30))

apollo_saveOutput(NLmodel)
stephanehess
Site Admin
Posts: 1049
Joined: 24 Apr 2020, 16:29

Re: Two level Nested Logit(NL) model specification for many alternatives

Post by stephanehess »

Hi

apologies for the slow reply, your message had got lost

Did you try with lambda=1 as a starting value. Essentially, you should first see if you can replicate MNL

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