Page 1 of 1

mixed logit model with truncated normal distribution

Posted: 19 Jun 2021, 21:34
by doosun1
Dear sir or madam,

Hi, I am trying to estimate mixed logit model w/ truncated normal distribution.

I made code based on example 14.

I had no problem when estimating mixed logit model w/ normal distribution or lognormal distribution. But confronted problem w/ truncated normal distribution.

I used truncated normal distribution random parameter reference with the previous apollo forum (https://groups.google.com/g/apollo-choi ... qyGEJsBQAJ)

I came up with "Error in value[[3L]](cond)" error during apollo_estimate().

Here's my code of random parameter part.

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

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

## truncated norm setting.
time_lower = pnorm(-Inf, mean=mu_beta_time, sd=sigma_beta_time)
time_upper = pnorm(0, mean=mu_beta_time, sd=sigma_beta_time)
fee_lower = pnorm(-Inf, mean=mu_beta_fee, sd=sigma_beta_fee)
fee_upper = pnorm(0, mean=mu_beta_fee, sd=sigma_beta_fee)

randcoeff = list()

## lognorm
# randcoeff[["beta_time_rd"]] = -exp( mu_beta_time + sigma_beta_time * draws_time )
# randcoeff[["beta_fee_rd"]] = -exp( mu_beta_fee + sigma_beta_fee * draws_fee )

## norm
# randcoeff[["beta_time_rd"]] = mu_beta_time + sigma_beta_time * draws_time
# randcoeff[["beta_fee_rd"]] = mu_beta_fee + sigma_beta_fee * draws_fee

## truncated norm variable
randcoeff[['beta_time_rd']] = qnorm(time_lower + eta1*(time_upper-time_lower), mu_beta_time, sigma_beta_time)
randcoeff[['beta_fee_rd']] = qnorm(fee_lower + eta2*(fee_upper-fee_lower), mu_beta_fee, sigma_beta_fee)

return(randcoeff)
}

Can you tell me what's wrong with my code? Thanks!

Best regards,
Hong

Specification of truncated normal distribution with random p

Posted: 22 Jun 2021, 05:17
by lagarzon
Dear All members and Professor Stephane.

Regarding the Apollo library in R. At the moment I am working with random coefficients and I am using the different types of distributions. :ugeek:

In the Apollo manual, in section "12.4 Model Specification"-(pg 142), several types of distributions are indicated, among them the truncated normal distribution; however, I have not been able to obtain it. Maybe you can help me with some kind of instruction or library that I could use to get the truncated normal?

I attached the specification of my mixed logit model with random parameters for a single variable "cs"

Later, I added in row 48 the following specification
sigma_cs = 0,
mu_cs = 0)

### 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("asc_alt2","mu_cs")

I thought that I could truncate the distribution this way, but later I noticed that I am only setting the mean of the distribution to 0. :D

Thanks All for your kind help.

Best regards,

Re: Specification of truncated normal distribution with random p

Posted: 25 Jun 2021, 17:02
by stephanehess
Hi

you need to start of with uniform draws, and then use a formula for translating these into truncated normals. See e.g. https://people.sc.fsu.edu/~jburkardt/pr ... normal.pdf

Stephane

Re: Specification of truncated normal distribution with random p

Posted: 29 Jun 2021, 11:15
by stephanehess
Hi

could you please reproduce your entire code file, including the starting values, etc, and the on screen output

Thanks

Stephane

Re: Specification of truncated normal distribution with random p

Posted: 07 Jul 2021, 20:10
by lagarzon
Thank you very much for your kind help professor Stephane.
Any person can continue to collaborate if there is any improvement
I share the code, the file and the processed results with the instructions and the shared article. :arrow:

# ################################################################# #
#### LOAD LIBRARY AND DEFINE CORE SETTINGS ####
# ################################################################# #
### Clear memory
#rm(list = ls())

### Load libraries
library(apollo)
library(EnvStats)
library(stats) # This library allows to use some functions created to work with distributions and especially to truncate (qnorm)

### Initialise code
apollo_initialise()

### Set core controls
apollo_control = list(
modelName ="ML-Random Parameters",
modelDescr ="MixedLogit_Random Parameters",
indivID ="id",
panelData=TRUE,
mixing = TRUE,
workInLogs=TRUE,
nCores =8)

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

setwd("file directory")
database = read.csv("CSP5.csv",header=TRUE,sep=",") #File attached so that any user can execute

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

### Vector of parameters, including any that are kept fixed in estimation
apollo_beta=c(asc_alt1 = 0,
asc_alt2 = 0.05,
asc_alt3 = 0.05,

#The specification contains five principal parameters:
#1."b_ev" green zones density, 2."b_cp" pedestrian density, 3."b_cv" traffic flow, 4."b_cs"sound pollution4 and 5."cost" for fee rent of a dweling

b_ev = 0.60, #Green zone density (green spaces/m2)
b_cp = -0.49, # Crowdedness (pedestrian/m2)
b_cv = -1.03, #Traffic flow (volume/capacity ratio)
#This variable b_cs is selected for truncation of the values of normal distribution
#b_cs = 1.5, # Equivalent sound pressure level (LAeq) - This varia
b_cost = -0.002, #Rent Fee
sigma_cs = 0.005,
mu_cs =0.05)

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

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

### Set parameters for generating draws
apollo_draws = list(

interDrawsType = "halton",
interNDraws = 500,
#Uniform distribution
interUnifDraws = c("draw_cs"),
#Normal distribution
interNormDraws = c(),

intraDrawsType = "halton",
intraNDraws = 0,
intraUnifDraws = c(),
intraNormDraws = c()

)

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

## truncated norm setting.
##in this case I am interested in negative distribution values
b_cs_low = pnorm(-Inf, mean = mu_cs, sd=sigma_cs)
b_cs_upper = pnorm(0, mean = mu_cs, sd=sigma_cs)

randcoeff = list()

#### NORMAL DISTRIBUTION##########
#randcoeff[["b_cs"]] = mu_cs + sigma_cs * draws_cs

####TRUNCATED NORMAL DISTRIBUTION##########
## truncated norm variable
randcoeff[["b_cs"]] = qnorm(b_cs_low + draw_cs * (b_cs_upper - b_cs_low), mean = mu_cs , sd = sigma_cs)

####LOGNORMAL DISTRIBUTION#########
#randcoeff[["b_cs"]] = -exp ( mu_cs + sigma_cs * draws_cs )

return(randcoeff)
}

# ################################################################# #
#### GROUP AND VALIDATE INPUTS ####
# ################################################################# #

#validar inputs
apollo_inputs = apollo_validateInputs()

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

#definir apollo probabilities function
apollo_probabilities=function(apollo_beta, apollo_inputs, functionality="estimate"){

### Function initialisation: do not change the following three commands
### 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 mnl_settings, order is irrelevant
V = list()
##My goal is to know the importance of the attributes independently of the selected alternatives.
V[['alt1']] = asc_alt1 + b_cv * alt1_cv + b_ev * alt1_ev + b_cs * alt1_cs + b_cp * alt1_cp + b_cost * alt1_c
V[['alt2']] = asc_alt2 + b_cv * alt2_cv + b_ev * alt2_ev + b_cs * alt2_cs + b_cp * alt2_cp + b_cost * alt2_c
V[['alt3']] = asc_alt3 + b_cv * alt3_cv + b_ev * alt3_ev + b_cs * alt3_cs + b_cp * alt3_cp + b_cost * alt3_c

### Define settings for MNL model component
mnl_settings = list(
alternatives = c(alt1=1, alt2=2, alt3=3),
avail = list(alt1=1, alt2=1, alt3=1),
choiceVar = choice,
V = V
)

### Compute probabilities using MNL model
P[['model']] = apollo_mnl(mnl_settings, functionality)

### Take product across observation for same individual
P = apollo_panelProd(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,
estimate_settings=list(hessianRoutine="maxLik"))

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

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

# ----------------------------------------------------------------- #
#---- CONDITIONALS AND UNCONDITIONALS ----
# ----------------------------------------------------------------- #
#Error term distribution
unconditionals <- apollo_unconditionals(model,apollo_probabilities, apollo_inputs)

#Drawing of the distribution density function of the parameter
plot(density(as.vector(unconditionals[["b_cs"]])))

# ----------------------------------------------------------------- #
#---- OUTPUT ----
# ----------------------------------------------------------------- #

Model run using Apollo for R, version 0.2.4 on Windows by andre
www.ApolloChoiceModelling.com

Model name : ML-Random Parameters
Model description : MixedLogit_Random Parameters
Model run at : 2021-07-07 11:57:50
Estimation method : bfgs
Model diagnosis : successful convergence
Number of individuals : 543
Number of rows in database : 1629
Number of modelled outcomes : 1629

Number of cores used : 8
Number of inter-individual draws : 500 (halton)

LL(start) : -1758.017
LL(0) : -1789.639
LL(final) : -1653.133
Rho-square (0) : 0.0763
Adj.Rho-square (0) : 0.0718
AIC : 3322.27
BIC : 3365.43

Estimated parameters : 8
Time taken (hh:mm:ss) : 00:02:57.84
pre-estimation : 00:00:15.68
estimation : 00:01:55.55
post-estimation : 00:00:46.61
Iterations : 42
Min abs eigenvalue of Hessian : 0.000231

Estimates:
Estimate s.e. t.rat.(0) Rob.s.e. Rob.t.rat.(0)
asc_alt1 0.000000 NA NA NA NA
asc_alt2 0.066425 0.07065 0.9402 0.07272 0.9135
asc_alt3 0.159065 0.07090 2.2436 0.08327 1.9103
b_ev 0.600499 0.07321 8.2019 0.08162 7.3571
b_cp -0.647385 0.08224 -7.8722 0.08724 -7.4208
b_cv -0.513378 0.08433 -6.0880 0.08471 -6.0601
b_cost -0.004889 7.9720e-04 -6.1322 8.3563e-04 -5.8502
sigma_cs 5.907047 6.31581 0.9353 2.95235 2.0008
mu_cs 29.139463 65.49067 0.4449 28.61342 1.0184

> mean(unconditionals[["b_cs"]])
[1] -1.114828
>
> sd(unconditionals[["b_cs"]])
[1] 1.08024