26. Triangular mixture with panel dataΒΆ

Example of a mixture of logit models, using Monte-Carlo integration. The mixing distribution is user-defined (triangular, here). The datafile is organized as panel data.

Michel Bierlaire, EPFL

import biogeme.biogeme_logging as blog
import numpy as np
from IPython.core.display_functions import display
from biogeme.biogeme import BIOGEME
from biogeme.draws import RandomNumberGeneratorTuple
from biogeme.expressions import (
    Beta,
    Draws,
    MonteCarlo,
    PanelLikelihoodTrajectory,
    log,
)
from biogeme.models import logit
from biogeme.results_processing import (
    EstimationResults,
    get_pandas_estimated_parameters,
)

See the data processing script: Panel data preparation for Swissmetro.

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

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

Function generating the draws.

def the_triangular_generator(sample_size: int, number_of_draws: int) -> np.ndarray:
    """
    Provide my own random number generator to the database.
    See the `numpy.random` documentation to obtain a list of other distributions.
    """
    return np.random.triangular(-1, 0, 1, (sample_size, number_of_draws))

Associate the function with a name.

my_random_number_generators = {
    'TRIANGULAR': RandomNumberGeneratorTuple(
        the_triangular_generator,
        'Draws from a triangular distribution',
    )
}

Parameters to be estimated.

b_cost = Beta('b_cost', 0, None, None, 0)

Define a random parameter, normally distributed across individuals, designed to be used for Monte-Carlo simulation.

Mean of the distribution.

b_time = Beta('b_time', 0, None, None, 0)

Scale of the distribution. It is advised not to use 0 as starting value for the following parameter.

b_time_s = Beta('b_time_s', 1, None, None, 0)
b_time_rnd = b_time + b_time_s * Draws('b_time_rnd', 'TRIANGULAR')

We do the same for the constants, to address serial correlation.

asc_car = Beta('asc_car', 0, None, None, 0)
asc_car_s = Beta('asc_car_s', 1, None, None, 0)
asc_car_rnd = asc_car + asc_car_s * Draws('asc_car_rnd', 'TRIANGULAR')

asc_train = Beta('asc_train', 0, None, None, 0)
asc_train_s = Beta('asc_train_s', 1, None, None, 0)
asc_train_rnd = asc_train + asc_train_s * Draws('asc_train_rnd', 'TRIANGULAR')

asc_sm = Beta('asc_sm', 0, None, None, 1)
asc_sm_s = Beta('asc_sm_s', 1, None, None, 0)
asc_sm_rnd = asc_sm + asc_sm_s * Draws('asc_sm_rnd', 'TRIANGULAR')

Definition of the utility functions.

v_train = asc_train_rnd + b_time_rnd * TRAIN_TT_SCALED + b_cost * TRAIN_COST_SCALED
v_swissmetro = asc_sm_rnd + b_time_rnd * SM_TT_SCALED + b_cost * SM_COST_SCALED
v_car = asc_car_rnd + b_time_rnd * CAR_TT_SCALED + b_cost * CAR_CO_SCALED

Associate utility functions with the numbering of alternatives.

v = {1: v_train, 2: v_swissmetro, 3: v_car}

Associate the availability conditions with the alternatives.

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

Conditional to the random parameters, the likelihood of one observation is given by the logit model (called the kernel).

one_observation_conditional_probability = logit(v, av, CHOICE)

Conditional on the random parameters, the likelihood of all observations for one individual (the trajectory) is the product of the likelihood of each observation.

trajectory_conditional_probability = PanelLikelihoodTrajectory(
    one_observation_conditional_probability
)

We integrate over the random parameters using Monte-Carlo

log_probability = log(MonteCarlo(trajectory_conditional_probability))
the_biogeme = BIOGEME(
    database,
    log_probability,
    random_number_generators=my_random_number_generators,
    number_of_draws=5_000,
    calculating_second_derivatives='never',
    seed=1223,
)
the_biogeme.model_name = 'b26_triangular_panel_mixture'
Biogeme parameters read from biogeme.toml.

Estimate the parameters.

try:
    results = EstimationResults.from_yaml_file(
        filename=f'saved_results/{the_biogeme.model_name}.yaml'
    )
except FileNotFoundError:
    results = the_biogeme.estimate()
Flattening database [(6768, 38)].
Database flattened [(752, 362)]
*** Initial values of the parameters are obtained from the file __b26_triangular_panel_mixture.iter
Parameter values restored from __b26_triangular_panel_mixture.iter
Starting values for the algorithm: {'asc_train': -0.3579068677530871, 'asc_train_s': 5.672923903548474, 'b_time': -6.078873916291999, 'b_time_s': 8.941037943738221, 'b_cost': -3.2829038751791275, 'asc_sm_s': 3.4921755055663684, 'asc_car': 0.35511086490784627, 'asc_car_s': 9.534559216931386}
As the model is rather complex, we cancel the calculation of second derivatives. If you want to control the parameters, change the algorithm from "automatic" to "simple_bounds" in the TOML file.
Optimization algorithm: hybrid Newton/BFGS with simple bounds [simple_bounds]
** Optimization: BFGS with trust region for simple bounds
Iter.       asc_train     asc_train_s          b_time        b_time_s          b_cost        asc_sm_s         asc_car       asc_car_s     Function    Relgrad   Radius      Rho
    0           -0.36             5.7            -6.1             8.9            -3.3             3.5            0.36             9.5      3.6e+03      0.005      0.5     -9.2    -
    1           -0.36             5.7            -6.1             8.9            -3.3             3.5            0.36             9.5      3.6e+03      0.005     0.25     -3.4    -
    2           -0.36             5.7            -6.1             8.9            -3.3             3.5            0.36             9.5      3.6e+03      0.005     0.12     -1.6    -
    3           -0.36             5.7            -6.1             8.9            -3.3             3.5            0.36             9.5      3.6e+03      0.005    0.062    -0.74    -
    4           -0.36             5.7            -6.1             8.9            -3.3             3.5            0.36             9.5      3.6e+03      0.005    0.031     -0.2    -
    5           -0.33             5.7            -6.1             8.9            -3.3             3.5            0.39             9.6      3.6e+03      0.004    0.031     0.44    +
    6           -0.33             5.7            -6.1             8.9            -3.3             3.5            0.39             9.6      3.6e+03      0.004    0.016   -0.036    -
    7           -0.33             5.7            -6.1             8.9            -3.3             3.4             0.4             9.5      3.6e+03     0.0025    0.016     0.66    +
    8           -0.34             5.7            -6.1             8.9            -3.3             3.4            0.42             9.5      3.6e+03     0.0035    0.016     0.46    +
    9           -0.33             5.7            -6.1             8.9            -3.3             3.4            0.43             9.5      3.6e+03     0.0028    0.016     0.68    +
   10           -0.33             5.7            -6.1             8.9            -3.2             3.4            0.42             9.5      3.6e+03     0.0014     0.16        1   ++
   11           -0.35             5.7              -6             8.8            -3.2             3.2            0.41             9.5      3.6e+03     0.0021     0.16     0.68    +
   12           -0.35             5.7              -6             8.8            -3.2             3.2            0.41             9.5      3.6e+03     0.0021    0.078     -4.9    -
   13           -0.35             5.7              -6             8.8            -3.2             3.2            0.41             9.5      3.6e+03     0.0021    0.039     -1.1    -
   14           -0.35             5.8              -6             8.8            -3.2             3.2            0.41             9.5      3.6e+03     0.0012    0.039     0.16    +
   15           -0.36             5.8              -6             8.8            -3.2             3.2             0.4             9.5      3.6e+03     0.0029    0.039     0.21    +
   16           -0.36             5.8              -6             8.8            -3.2             3.2            0.41             9.5      3.6e+03     0.0028    0.039     0.29    +
   17           -0.35             5.8              -6             8.8            -3.2             3.1             0.4             9.4      3.6e+03     0.0004    0.039     0.74    +
   18           -0.35             5.8              -6             8.8            -3.2             3.1             0.4             9.4      3.6e+03     0.0004     0.02     -1.3    -
   19           -0.35             5.8              -6             8.8            -3.2             3.1             0.4             9.4      3.6e+03     0.0004   0.0098   -0.065    -
   20           -0.36             5.8              -6             8.8            -3.2             3.1            0.41             9.4      3.6e+03      0.001   0.0098     0.48    +
   21           -0.37             5.8              -6             8.8            -3.2             3.1            0.41             9.4      3.6e+03    0.00021   0.0098     0.61    +
   22           -0.37             5.8              -6             8.8            -3.2             3.1            0.41             9.4      3.6e+03    0.00021   0.0049    -0.24    -
   23           -0.36             5.8              -6             8.8            -3.2             3.1             0.4             9.4      3.6e+03    0.00047   0.0049     0.71    +
   24           -0.36             5.8              -6             8.8            -3.2             3.1             0.4             9.4      3.6e+03    0.00067   0.0049     0.26    +
   25           -0.37             5.8              -6             8.8            -3.2             3.1             0.4             9.4      3.6e+03    0.00022   0.0049     0.72    +
   26           -0.37             5.8              -6             8.8            -3.2             3.1             0.4             9.4      3.6e+03    0.00012   0.0049     0.73    +
   27           -0.37             5.8              -6             8.8            -3.2             3.1             0.4             9.4      3.6e+03    0.00011    0.049     0.95   ++
   28           -0.37             5.9              -6             8.7            -3.2               3             0.4             9.4      3.6e+03     0.0013    0.049     0.42    +
   29           -0.38             5.9              -6             8.8            -3.2               3            0.39             9.4      3.6e+03    0.00062    0.049     0.48    +
   30           -0.38             5.9              -6             8.8            -3.2               3            0.39             9.4      3.6e+03    0.00062    0.024     -5.2    -
   31           -0.38             5.9              -6             8.8            -3.2               3            0.39             9.4      3.6e+03    0.00062    0.012     -1.2    -
   32           -0.37             5.9              -6             8.8            -3.2               3             0.4             9.4      3.6e+03    0.00025    0.012      0.4    +
   33           -0.37             5.9              -6             8.8            -3.2               3             0.4             9.4      3.6e+03    0.00025   0.0061     -0.6    -
   34           -0.38             5.9              -6             8.8            -3.2               3            0.39             9.4      3.6e+03    0.00027   0.0061     0.49    +
   35           -0.38             5.9              -6             8.8            -3.2               3             0.4             9.5      3.6e+03    0.00013   0.0061     0.21    +
   36           -0.37             5.9              -6             8.8            -3.2               3             0.4             9.5      3.6e+03    4.7e-05   0.0061     0.71    +
   37           -0.37             5.9              -6             8.8            -3.2               3             0.4             9.5      3.6e+03    4.4e-05   0.0061     0.33    +
   38           -0.37             5.9              -6             8.8            -3.2               3             0.4             9.5      3.6e+03    2.5e-05   0.0061     0.59    +
   39           -0.37             5.9              -6             8.8            -3.2               3             0.4             9.5      3.6e+03    2.5e-05   0.0031    -0.51    -
   40           -0.37             5.9              -6             8.8            -3.2               3             0.4             9.5      3.6e+03    1.1e-05   0.0031     0.56    +
   41           -0.37             5.9              -6             8.8            -3.2               3             0.4             9.5      3.6e+03    4.1e-06   0.0031     0.75    +
Optimization algorithm has converged.
Relative gradient: 4.144730231720455e-06
Cause of termination: Relative gradient = 4.1e-06 <= 6.1e-06
Number of function evaluations: 97
Number of gradient evaluations: 55
Number of hessian evaluations: 0
Algorithm: BFGS with trust region for simple bound constraints
Number of iterations: 42
Proportion of Hessian calculation: 0/27 = 0.0%
Optimization time: 0:00:45.151425
Calculate BHHH
File b26_triangular_panel_mixture.html has been generated.
File b26_triangular_panel_mixture.yaml has been generated.
print(results.short_summary())
Results for model b26_triangular_panel_mixture
Nbr of parameters:              8
Sample size:                    752
Observations:                   6768
Excluded data:                  0
Final log likelihood:           -3599.787
Akaike Information Criterion:   7215.573
Bayesian Information Criterion: 7252.555
pandas_results = get_pandas_estimated_parameters(estimation_results=results)
display(pandas_results)
          Name     Value  BHHH std err.  BHHH t-stat.  BHHH p-value
0    asc_train -0.371950       0.226528     -1.641960      0.100598
1  asc_train_s  5.890475       0.602045      9.784113      0.000000
2       b_time -5.992359       0.273432    -21.915335      0.000000
3     b_time_s  8.764962       0.615886     14.231465      0.000000
4       b_cost -3.201639       0.137116    -23.349784      0.000000
5     asc_sm_s  2.984671       0.678491      4.398982      0.000011
6      asc_car  0.396768       0.202729      1.957135      0.050332
7    asc_car_s  9.466908       0.599459     15.792424      0.000000

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

Gallery generated by Sphinx-Gallery