Page 1 of 1

Specifying the latent variables in ICLV

Posted: 30 Nov 2022, 04:00
by nctiglao
Hello Prof. Hess,

I am working on an ICLV model for bicycle to work decisions that is specified as a binary choice. I am trying to incorporate 4 latent variables namely safebiking, environment, easeoftravel and lowtraffic. The measurement model consists of 12 indicator variables which I have separately established through an exploratory factor analysis.

It seems that the effects of the LVs are rather insignificant based on the t ratio. However, I am not sure if I am specifying the latent variables correctly in the model.

Hope you can check my current model at https://gist.github.com/ncctiglao/aa2d4 ... 9c4bbb3c41

Best regards,

Noriel Tiglao

Here are the model outputs:

Code: Select all

Model run by User using Apollo 0.2.8 on R 4.2.1 for Windows.
www.ApolloChoiceModelling.com

Model name                                  : Hybrid Model for Bicycle to Work
Model description                           : ICLV model
Model run at                                : 2022-11-30 10:50:39
Estimation method                           : bfgs
Model diagnosis                             : successful convergence 
Number of individuals                       : 519
Number of rows in database                  : 519
Number of modelled outcomes                 : 5709
              indic_safebiking_1 : 519
              indic_safebiking_2 : 519
              indic_safebiking_3 : 519
             indic_environment_1 : 519
             indic_environment_2 : 519
             indic_easoftravel_1 : 519
             indic_easoftravel_2 : 519
              indic_lowtraffic_1 : 519
              indic_lowtraffic_2 : 519
              indic_lowtraffic_3 : 519
                      biketowork : 519

Number of cores used                        :  4 
Number of inter-individual draws            : 100 (halton)
WARNING: Inter-individual draws were used
         without a panel data structure.

LL(start)                                   : -7173.31
LL (whole model) at equal shares, LL(0)     : Not applicable
LL (whole model) at observed shares, LL(C)  : Not applicable
LL(final, whole model)                      : -3063.91
Rho-squared vs equal shares                  :  Not applicable 
Adj.Rho-squared vs equal shares              :  Not applicable 
Rho-squared vs observed shares               :  Not applicable 
Adj.Rho-squared vs observed shares           :  Not applicable 
AIC                                         :  6191.81 
BIC                                         :  6327.87 

LL(0,indic_safebiking_1)         : Not applicable
LL(final,indic_safebiking_1)     : -276.69
LL(0,indic_safebiking_2)         : Not applicable
LL(final,indic_safebiking_2)     : -261.8
LL(0,indic_safebiking_3)         : Not applicable
LL(final,indic_safebiking_3)     : -239.68
LL(0,indic_environment_1)        : Not applicable
LL(final,indic_environment_1)    : -311.07
LL(0,indic_environment_2)        : Not applicable
LL(final,indic_environment_2)    : -337.84
LL(0,indic_easeoftravel_1)       : Not applicable
LL(final,indic_easeoftravel_1)   : -276.03
LL(0,indic_easeoftravel_2)       : Not applicable
LL(final,indic_easeoftravel_2)   : -304.06
LL(0,indic_lowtraffic_1)         : Not applicable
LL(final,indic_lowtraffic_1)     : -302.58
LL(0,indic_lowtraffic_2)         : Not applicable
LL(final,indic_lowtraffic_2)     : -276.16
LL(0,indic_lowtraffic_3)         : Not applicable
LL(final,indic_lowtraffic_3)     : -343.2
LL(0,biketowork)                 : -359.74
LL(final,biketowork)             : -276.98

Estimated parameters                        :  32
Time taken (hh:mm:ss)                       :  00:02:23.62 
     pre-estimation                         :  00:00:22.76 
     estimation                             :  00:00:23.4 
     post-estimation                        :  00:01:37.46 
Iterations                                  :  55  
Min abs eigenvalue of Hessian               :  0.570972 

Unconstrained optimisation.

These outputs have had the scaling used in estimation applied to them.
Estimates:
                       Estimate        s.e.   t.rat.(0)    Rob.s.e. Rob.t.rat.(0)
asc_yes                0.881703    1.310166     0.67297    1.266522       0.69616
b_age                 -0.006531    0.001337    -4.88497    0.001546      -4.22463
b_gender               0.055327    0.038335     1.44325    0.051166       1.08134
b_income              -0.050709    0.093310    -0.54345    0.096981      -0.52288
b_hhead               -0.015020    0.218529    -0.06873    0.212138      -0.07080
b_educ                -0.033341    0.165516    -0.20144    0.161943      -0.20588
b_bikeown              0.228399    0.049211     4.64122    0.056987       4.00791
b_sector              -0.537038    0.247046    -2.17383    0.245567      -2.18693
lambda_safebiking      0.169389    0.146053     1.15978    0.159044       1.06505
lambda_environment    -0.150562    0.129317    -1.16428    0.142029      -1.06007
lambda_easeoftravel    0.095543    0.149451     0.63929    0.177227       0.53910
lambda_lowtraffic      0.096464    0.144866     0.66589    0.148429       0.64990
gamma_bikelane         0.417917    0.016173    25.84050    0.019556      21.36980
gamma_pavement         0.419824    0.015004    27.98032    0.014935      28.10931
gamma_safety           0.420632    0.014614    28.78219    0.016087      26.14697
gamma_scenery          0.521763    0.019359    26.95217    0.024631      21.18285
gamma_shade            0.466516    0.021027    22.18600    0.024664      18.91473
gamma_shorttime        0.510761    0.019248    26.53647    0.026065      19.59600
gamma_shortestdist     0.491107    0.021110    23.26433    0.030557      16.07168
gamma_lesstraffic      0.408475    0.017942    22.76691    0.019754      20.67800
gamma_slowvehspeed     0.453849    0.018130    25.03262    0.021872      20.75067
gamma_resstreet        0.451214    0.020048    22.50623    0.022597      19.96764
sigma_bikelane         0.337446    0.015187    22.21926    0.030714      10.98656
sigma_pavement         0.318022    0.014153    22.47059    0.021745      14.62478
sigma_safety           0.282339    0.015179    18.60009    0.028665       9.84967
sigma_scenery          0.278361    0.037766     7.37068    0.050004       5.56676
sigma_shade            0.391462    0.026907    14.54896    0.039093      10.01354
sigma_shorttime        0.247070    0.025193     9.80699    0.026593       9.29090
sigma_shortestdist     0.324231    0.021698    14.94258    0.033897       9.56524
sigma_lesstraffic      0.380826    0.015691    24.27021    0.026708      14.25872
sigma_slowvehspeed     0.316406    0.017595    17.98298    0.025051      12.63039
sigma_resstreet        0.421170    0.017501    24.06589    0.023969      17.57129

Re: Specifying the latent variables in ICLV

Posted: 30 Nov 2022, 15:20
by stephanehess
Hi

this one was simple to find the issue. You are using your indicators as explanatory variables inside the structural equation for the latent variables, and then you use those latent variables to explain the indicators. So you are using the indicators to model the indicators. You need to drop all the parts with gamma from the structural equations

Stephane

Re: Specifying the latent variables in ICLV

Posted: 02 Dec 2022, 11:14
by nctiglao
Hello Prof. Hess,

Thanks for your quick feedback. I did take out the terms with gamma in the structural equations but the results have not improved.

On the other hand, may I inquire if apollo has a notion of latent construct which are commonplace in structural equations modeling. The SEM model structure that I am contemplating is as follows.

https://drive.google.com/file/d/1SHKVto ... share_link

Hoping for your kind help.

Best regards,

Noriel

Re: Specifying the latent variables in ICLV

Posted: 08 Dec 2022, 10:03
by nctiglao
Hello Prof. Hess,

Thanks for your reply. I made some edits on the program but the results are still not quite satisfactory. Here is the revised program https://gist.github.com/ncctiglao/d33fe ... 86de7df150

That said, may I ask if there is a way to specify a single construct based on 4 latent variables?

Best regards,

Noriel

Re: Specifying the latent variables in ICLV

Posted: 05 Jan 2023, 01:53
by nctiglao
Hello Prof. Hess,

Thanks for your earlier reply.

I ran the modified model with few improvements of the parameters estimates. This is the revised Apollo program code https://gist.github.com/ncctiglao/d33fe ... 86de7df150

Further, may I inquire if it is possible to specify endogenous and exogenous constructs in Apollo?

Best regards,

Noriel

Re: Specifying the latent variables in ICLV

Posted: 28 Feb 2023, 21:46
by dpalma
Hi Noriel.

Sorry for taking so long to reply.

Below is your code using the full structure you propose, including the endogenous construct idealroute which depends only on the other latent variables. Note that I increased the number of draws you were using. I set it up to a thousand, but I would more likely recommend 2000.

The code may contain some types, because I don't have your data so I can't test the code. But the basic idea is there.

Best wishes.
David

Code: Select all

# ################################################################# #
#### LOAD LIBRARY AND DEFINE CORE SETTINGS                       ####
# ################################################################# #

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

### Load libraries
library(apollo)
library(tidyverse)

### Initialise code
apollo_initialise()

### Set core controls
apollo_control = list(
  modelName = "Hybrid Model for Bicycle to Work",
  modelDescr = "ICLV model",
  indivID = "id",
  mixing = TRUE,
  nCores = 4,
  outputDirectory = "output"
)

# ################################################################# #
#### LOAD DATA AND APPLY ANY TRANSFORMATIONS                     ####
# ################################################################# #

database = read.csv("ils-biketoworkdata.csv", header=TRUE)
#database <- na.omit(database)
#View(database)

### Subtract mean of indicator variables to center them on zero
database$bikelane     = database$bikelane     - mean(database$bikelane) 
database$pavement     = database$pavement     - mean(database$pavement)
database$safety       = database$safety       - mean(database$safety)
database$scenery      = database$scenery      - mean(database$scenery)
database$shade        = database$shade        - mean(database$shade)
database$shorttime    = database$shorttime    - mean(database$shorttime)
database$shortestdist = database$shortestdist - mean(database$shortestdist)
database$lesstraffic  = database$lesstraffic  - mean(database$lesstraffic)
database$slowvehspeed = database$slowvehspeed - mean(database$slowvehspeed)
database$resstreet    = database$resstreet    - mean(database$resstreet)

# ################################################################# #
#### DEFINE MODEL PARAMETERS                                     ####
# ################################################################# #

### Vector of parameters, including any that are kept fixed in estimation
apollo_beta=c(asc_yes = 0,
              b_age =0,
              b_gender =0,
              b_income = 0,
              b_hhead =0,
              b_educ =0,
              b_bikeown = 0,
              b_sector = 0,
              lambda_safebiking = 0,
              lambda_environment = 0,
              lambda_easeoftravel = 0,
              lambda_lowtraffic = 0,
              zeta_idealroute = 1, 
              gamma_bikelane = 1,
              gamma_pavement = 1,
              gamma_safety = 1,
              gamma_scenery = 1,
              gamma_shade = 1,
              gamma_shorttime = 1,
              gamma_shortestdist = 1,
              gamma_lesstraffic = 1,
              gamma_slowvehspeed = 1,
              gamma_resstreet = 1,
              sigma_bikelane = 1,
              sigma_pavement = 1,
              sigma_safety = 1,
              sigma_scenery = 1,
              sigma_shade = 1,
              sigma_shorttime = 1,
              sigma_shortestdist = 1,
              sigma_lesstraffic = 1,
              sigma_slowvehspeed = 1,
              sigma_resstreet = 1)

### 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()

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

### Set parameters for generating draws
apollo_draws = list(
  interDrawsType="mlhs",
  interNDraws   =1000,
  interUnifDraws=c(),
  interNormDraws=c("eta_safebiking", "eta_environment", "eta_easeoftravel", 
                   "eta_lowtraffic", "eta_idealroute")
)

### Create random parameters
apollo_randCoeff=function(apollo_beta, apollo_inputs){
  randcoeff = list()
  
  randcoeff[["LV_safebiking"]]   = eta_safebiking 
  randcoeff[["LV_environment"]]  = eta_environment
  randcoeff[["LV_easeoftravel"]] = eta_easeoftravel
  randcoeff[["LV_lowtraffic"]]   = eta_lowtraffic
  randcoeff[["LV_idealroute"]]   = eta_idealroute + 
    lambda_safebiking*randcoeff[["LV_safebiking"]] + 
    lambda_environment*randcoeff[["LV_environment"]] + 
    lambda_easeoftravel*randcoeff[["LV_easeoftravel"]] + 
    lambda_lowtraffic*randcoeff[["LV_lowtraffic"]]
    
  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()
  
  ### Likelihood of indicators
  normalDensity_settings1 = list(outcomeNormal=bikelane,
                                 xNormal=gamma_bikelane*LV_safebiking,
                                 mu=0,
                                 sigma=sigma_bikelane,
                                 componentName='indic_safebiking_1')
  
  normalDensity_settings2 = list(outcomeNormal=pavement,
                                 xNormal=gamma_pavement*LV_safebiking,
                                 mu=0,
                                 sigma=sigma_pavement,
                                 componentName='indic_safebiking_2')
  
  normalDensity_settings3 = list(outcomeNormal=safety,
                                 xNormal=gamma_safety*LV_safebiking,
                                 mu=0,
                                 sigma=sigma_safety,
                                 componentName='indic_safebiking_3')
  
  normalDensity_settings4 = list(outcomeNormal=scenery,
                                 xNormal=gamma_scenery*LV_environment,
                                 mu=0,
                                 sigma=sigma_scenery,
                                 componentName='indic_environment_1')
  
  normalDensity_settings5 = list(outcomeNormal=shade,
                                 xNormal=gamma_shade*LV_environment,
                                 mu=0,
                                 sigma=sigma_shade,
                                 componentName='indic_environment_2')
  
  normalDensity_settings6 = list(outcomeNormal=shorttime,
                                 xNormal=gamma_shorttime*LV_easeoftravel,
                                 mu=0,
                                 sigma=sigma_shorttime,
                                 componentName='indic_easeoftravel_1')
  
  normalDensity_settings7 = list(outcomeNormal=shortestdist,
                                 xNormal=gamma_shortestdist*LV_easeoftravel,
                                 mu=0,
                                 sigma=sigma_shortestdist,
                                 componentName='indic_easeoftravel_2')
  
  normalDensity_settings8 = list(outcomeNormal=lesstraffic,
                                 xNormal=gamma_lesstraffic*LV_lowtraffic,
                                 mu=0,
                                 sigma=sigma_lesstraffic,
                                 componentName='indic_lowtraffic_1')
  
  normalDensity_settings9 = list(outcomeNormal=slowvehspeed,
                                 xNormal=gamma_slowvehspeed*LV_lowtraffic,
                                 mu=0,
                                 sigma=sigma_slowvehspeed,
                                 componentName='indic_lowtraffic_2')
  
  normalDensity_settings10= list(outcomeNormal=resstreet,
                                 xNormal=gamma_resstreet*LV_lowtraffic,
                                 mu=0,
                                 sigma=sigma_resstreet,
                                 componentName='indic_lowtraffic_3')
  
  P[["indic_safebiking_1"]]   = apollo_normalDensity(normalDensity_settings1, functionality)
  P[["indic_safebiking_2"]]   = apollo_normalDensity(normalDensity_settings2, functionality)
  P[["indic_safebiking_3"]]   = apollo_normalDensity(normalDensity_settings3, functionality)
  P[["indic_environment_1"]]  = apollo_normalDensity(normalDensity_settings4, functionality)
  P[["indic_environment_2"]]  = apollo_normalDensity(normalDensity_settings5, functionality)
  P[["indic_easeoftravel_1"]] = apollo_normalDensity(normalDensity_settings6, functionality)
  P[["indic_easeoftravel_2"]] = apollo_normalDensity(normalDensity_settings7, functionality)
  P[["indic_lowtraffic_1"]]   = apollo_normalDensity(normalDensity_settings8, functionality)
  P[["indic_lowtraffic_2"]]   = apollo_normalDensity(normalDensity_settings9, functionality)
  P[["indic_lowtraffic_3"]]   = apollo_normalDensity(normalDensity_settings10, functionality)
  
  ### Likelihood of choices
  ### List of utilities: these must use the same names as in mnl_settings, order is irrelevant
  
  V = list()
  V[['No']] = 0
  V[['Yes']] = asc_yes + b_age*age + b_gender*gender + b_income*income + 
    b_hhead*hhead + b_educ*educ + b_sector*sector + b_bikeown*bikeown + 
    zeta_idealroute*LV_idealroute
  
  
  ### Define settings for MNL model component
  mnl_settings = list(
    alternatives = c(No=0,Yes=1),
    avail = 1,
    choiceVar = biketowork,
    V = V,
    componentName = "MNL_biketowork"
  )
  
  ### Compute probabilities for MNL model component
  P[["biketowork"]] = apollo_mnl(mnl_settings, functionality)
  
  ### Likelihood of the whole model
  P = apollo_combineModels(P, apollo_inputs, functionality)
  
  ### Average across inter-individual draws
  P = apollo_avgInterDraws(P, apollo_inputs, functionality)
  
  ### Prepare and return outputs of function
  P = apollo_prepareProb(P, apollo_inputs, functionality)
  return(P)
}

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

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

# ################################################################# #
#### MODEL OUTPUTS ####
# ################################################################# #

# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO SCREEN)                               ----
# ----------------------------------------------------------------- #

apollo_modelOutput(model)

# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO FILE, using model name)               ----
# ----------------------------------------------------------------- #

apollo_saveOutput(model)