Nested logit model

Example of a nested logit model, using the original syntax for nests. Since biogeme 3.13, a new syntax, more explicit, has been adopted.

author:

Michel Bierlaire, EPFL

date:

Tue Oct 24 13:37:27 2023

import biogeme.biogeme_logging as blog
import biogeme.biogeme as bio
from biogeme import models
from biogeme.expressions import Beta

See the data processing script: Data preparation for Swissmetro.

from swissmetro_data import (
    database,
    CHOICE,
    SM_AV,
    CAR_AV_SP,
    TRAIN_AV_SP,
    TRAIN_TT_SCALED,
    TRAIN_COST_SCALED,
    SM_TT_SCALED,
    SM_COST_SCALED,
    CAR_TT_SCALED,
    CAR_CO_SCALED,
)

logger = blog.get_screen_logger(level=blog.INFO)
logger.info('Example b09nested')
Example b09nested

Parameters to be estimated.

ASC_CAR = Beta('ASC_CAR', 0, None, None, 0)
ASC_TRAIN = Beta('ASC_TRAIN', 0, None, None, 0)
ASC_SM = Beta('ASC_SM', 0, None, None, 1)
B_TIME = Beta('B_TIME', 0, None, None, 0)
B_COST = Beta('B_COST', 0, None, None, 0)
MU = Beta('MU', 1, 1, 10, 0)

Definition of the utility functions.

V1 = ASC_TRAIN + B_TIME * TRAIN_TT_SCALED + B_COST * TRAIN_COST_SCALED
V2 = ASC_SM + B_TIME * SM_TT_SCALED + B_COST * SM_COST_SCALED
V3 = ASC_CAR + B_TIME * CAR_TT_SCALED + B_COST * CAR_CO_SCALED

Associate utility functions with the numbering of alternatives.

V = {1: V1, 2: V2, 3: V3}

Associate the availability conditions with the alternatives.

av = {1: TRAIN_AV_SP, 2: SM_AV, 3: CAR_AV_SP}

Definition of nests. In this example, we create a nest for the existing modes, that is train (1) and car (3). Each nest is associated with a tuple containing (i) the nest parameter and (ii) the list of alternatives.

existing = MU, [1, 3]
future = 1.0, [2]
nests = existing, future

Definition of the model. This is the contribution of each observation to the log likelihood function. The choice model is a nested logit, with availability conditions.

logprob = models.lognested(V, av, nests, CHOICE)
It is recommended to define the nests of the nested logit model using the objects OneNestForNestedLogit and NestsForNestedLogit defined in biogeme.nests.

Create the Biogeme object.

the_biogeme = bio.BIOGEME(database, logprob)
the_biogeme.modelName = "b09nested"
File biogeme.toml has been parsed.

Calculate the null log likelihood for reporting.

the_biogeme.calculateNullLoglikelihood(av)
-6964.662979191462

Estimate the parameters.

results = the_biogeme.estimate()
*** Initial values of the parameters are obtained from the file __b09nested.iter
Parameter values restored from __b09nested.iter
Optimization algorithm: hybrid Newton/BFGS with simple bounds [simple_bounds]
** Optimization: Newton with trust region for simple bounds
Results saved in file b09nested~00.html
Results saved in file b09nested~00.pickle
print(results.short_summary())
Results for model b09nested
Nbr of parameters:              5
Sample size:                    6768
Excluded data:                  3960
Null log likelihood:            -6964.663
Final log likelihood:           -5236.9
Likelihood ratio test (null):           3455.526
Rho square (null):                      0.248
Rho bar square (null):                  0.247
Akaike Information Criterion:   10483.8
Bayesian Information Criterion: 10517.9
pandas_results = results.getEstimatedParameters()
pandas_results
Value Rob. Std err Rob. t-test Rob. p-value
ASC_CAR -0.167155 0.054529 -3.065428 2.173586e-03
ASC_TRAIN -0.511948 0.079114 -6.471047 9.732637e-11
B_COST -0.856667 0.060035 -14.269453 0.000000e+00
B_TIME -0.898666 0.107112 -8.389947 0.000000e+00
MU 2.054056 0.164201 12.509383 0.000000e+00


Total running time of the script: (0 minutes 0.213 seconds)

Gallery generated by Sphinx-Gallery