Note
Go to the end to download the full example code
Catalog of nonlinear specifications
Investigate of nonlinear specifications for the travel time variables:
linear specification,
Box-Cox transform,
power series,
for a total of 3 specifications. See Bierlaire and Ortelli (2023).
- author:
Michel Bierlaire, EPFL
- date:
Thu Jul 13 21:31:54 2023
import biogeme.biogeme as bio
import biogeme.biogeme_logging as blog
from biogeme import models
from biogeme.expressions import Expression, Beta
from biogeme.models import boxcox
from biogeme.catalog import Catalog
from biogeme.results import compile_estimation_results, pareto_optimal
See 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)
Parameters to be estimated.
ASC_CAR = Beta('ASC_CAR', 0, None, None, 0)
ASC_TRAIN = Beta('ASC_TRAIN', 0, None, None, 0)
B_TIME = Beta('B_TIME', 0, None, 0, 0)
B_COST = Beta('B_COST', 0, None, 0, 0)
Non linear specifications for the travel time.
Parameter of the Box-Cox transform.
ell_travel_time = Beta('lambda_travel_time', 1, -10, 10, 0)
Coefficients of the power series.
square_tt_coef = Beta('square_tt_coef', 0, None, None, 0)
cube_tt_coef = Beta('cube_tt_coef', 0, None, None, 0)
Function calculation the power series.
def power_series(the_variable: Expression) -> Expression:
"""Generate the expression of a polynomial of degree 3
:param the_variable: variable of the polynomial
"""
return (
the_variable
+ square_tt_coef * the_variable**2
+ cube_tt_coef * the_variable * the_variable**3
)
Train travel time
Linear specification.
linear_train_tt = TRAIN_TT_SCALED
Box-Cox transform.
boxcox_train_tt = boxcox(TRAIN_TT_SCALED, ell_travel_time)
Power series.
power_train_tt = power_series(TRAIN_TT_SCALED)
Definition of the catalog.
train_tt_catalog = Catalog.from_dict(
catalog_name='train_tt_catalog',
dict_of_expressions={
'linear': linear_train_tt,
'boxcox': boxcox_train_tt,
'power': power_train_tt,
},
)
Swissmetro travel time
Linear specification.
linear_sm_tt = SM_TT_SCALED
Box-Cox transform.
boxcox_sm_tt = boxcox(SM_TT_SCALED, ell_travel_time)
Power series.
power_sm_tt = power_series(SM_TT_SCALED)
Definition of the catalog. Note that the controller is the same as for train.
sm_tt_catalog = Catalog.from_dict(
catalog_name='sm_tt_catalog',
dict_of_expressions={
'linear': linear_sm_tt,
'boxcox': boxcox_sm_tt,
'power': power_sm_tt,
},
controlled_by=train_tt_catalog.controlled_by,
)
Car travel time
Linear specification.
linear_car_tt = CAR_TT_SCALED
Box-Cox transform.
boxcox_car_tt = boxcox(CAR_TT_SCALED, ell_travel_time)
Power series.
power_car_tt = power_series(CAR_TT_SCALED)
Definition of the catalog. Note that the controller is the same as for train.
car_tt_catalog = Catalog.from_dict(
catalog_name='car_tt_catalog',
dict_of_expressions={
'linear': linear_car_tt,
'boxcox': boxcox_car_tt,
'power': power_car_tt,
},
controlled_by=train_tt_catalog.controlled_by,
)
Definition of the utility functions.
V1 = ASC_TRAIN + B_TIME * train_tt_catalog + B_COST * TRAIN_COST_SCALED
V2 = B_TIME * sm_tt_catalog + B_COST * SM_COST_SCALED
V3 = ASC_CAR + B_TIME * car_tt_catalog + 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 the model. This is the contribution of each observation to the log likelihood function.
logprob = models.loglogit(V, av, CHOICE)
Create the Biogeme object.
the_biogeme = bio.BIOGEME(database, logprob)
the_biogeme.modelName = 'b02nonlinear'
the_biogeme.generate_html = False
the_biogeme.generate_pickle = False
File biogeme.toml has been parsed.
Estimate the parameters.
dict_of_results = the_biogeme.estimate_catalog()
Estimating 3 models.
File biogeme.toml has been parsed.
*** Initial values of the parameters are obtained from the file __b02nonlinear_000000.iter
Cannot read file __b02nonlinear_000000.iter. Statement is ignored.
Optimization algorithm: hybrid Newton/BFGS with simple bounds [simple_bounds]
** Optimization: Newton with trust region for simple bounds
Iter. ASC_CAR ASC_TRAIN B_COST B_TIME Function Relgrad Radius Rho
0 -0.49 -0.92 -0.88 -0.67 5.4e+03 0.041 10 1.1 ++
1 -0.18 -0.73 -1 -1.2 5.3e+03 0.0072 1e+02 1.1 ++
2 -0.16 -0.7 -1.1 -1.3 5.3e+03 0.00018 1e+03 1 ++
3 -0.16 -0.7 -1.1 -1.3 5.3e+03 1.1e-07 1e+03 1 ++
Results saved in file b02nonlinear_000000.html
Results saved in file b02nonlinear_000000.pickle
File biogeme.toml has been parsed.
*** Initial values of the parameters are obtained from the file __b02nonlinear_000001.iter
Cannot read file __b02nonlinear_000001.iter. Statement is ignored.
Optimization algorithm: hybrid Newton/BFGS with simple bounds [simple_bounds]
** Optimization: Newton with trust region for simple bounds
Iter. ASC_CAR ASC_TRAIN B_COST B_TIME lambda_travel_t Function Relgrad Radius Rho
0 -0.5 -0.71 -0.82 -1 1.7 5.6e+03 0.053 1 0.77 +
1 -0.35 -0.77 -1.3 -1.7 0.69 5.4e+03 0.032 10 1 ++
2 0.017 -0.47 -1 -1.7 0.53 5.3e+03 0.002 1e+02 0.96 ++
3 -0.0043 -0.48 -1.1 -1.7 0.51 5.3e+03 1.3e-05 1e+03 1 ++
4 -0.0043 -0.48 -1.1 -1.7 0.51 5.3e+03 1.8e-09 1e+03 1 ++
Results saved in file b02nonlinear_000001.html
Results saved in file b02nonlinear_000001.pickle
File biogeme.toml has been parsed.
*** Initial values of the parameters are obtained from the file __b02nonlinear_000002.iter
Cannot read file __b02nonlinear_000002.iter. Statement is ignored.
Optimization algorithm: hybrid Newton/BFGS with simple bounds [simple_bounds]
** Optimization: Newton with trust region for simple bounds
Iter. ASC_CAR ASC_TRAIN B_COST B_TIME cube_tt_coef square_tt_coef Function Relgrad Radius Rho
0 0 0 0 0 0 0 7e+03 0.27 0.5 -0.86 -
1 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 5 1 ++
2 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 2.5 -10 -
3 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 1.2 -6.4 -
4 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.62 -3.8 -
5 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.31 -2.3 -
6 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.16 -1.8 -
7 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.078 -1.8 -
8 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.039 -2.2 -
9 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.02 -2.7 -
10 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.0098 -3.2 -
11 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.0049 -3.5 -
12 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.0024 -2.4 -
13 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.0012 -1.6 -
14 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.00061 -0.92 -
15 -0.079 -0.5 -0.5 -0.5 0 0 5.7e+03 7.4 0.00031 -0.11 -
16 -0.08 -0.5 -0.5 -0.5 -0.00031 0.00031 5.7e+03 3.5 0.00031 0.69 +
17 -0.08 -0.5 -0.5 -0.5 -0.00025 0.00061 5.7e+03 1.2 0.00031 0.87 +
18 -0.08 -0.5 -0.5 -0.5 -0.00027 0.00092 5.7e+03 0.15 0.0031 1 ++
19 -0.08 -0.5 -0.5 -0.5 -0.00027 0.004 5.7e+03 0.95 0.031 1 ++
20 -0.086 -0.52 -0.5 -0.53 -0.00041 0.034 5.6e+03 0.27 0.31 1 ++
21 -0.12 -0.66 -0.6 -0.83 -0.0014 0.26 5.5e+03 3 0.31 0.6 +
22 -0.11 -0.78 -0.91 -0.98 -0.00018 -0.017 5.3e+03 5 0.31 0.64 +
23 -0.25 -0.8 -1 -1.3 -7.2e-05 -0.047 5.3e+03 4 3.1 1.1 ++
24 -0.25 -0.8 -1 -1.3 -7.2e-05 -0.047 5.3e+03 4 0.83 -12 -
25 -0.25 -0.8 -1 -1.3 -7.2e-05 -0.047 5.3e+03 4 0.41 -1.5 -
26 -0.11 -0.8 -1.1 -1.7 0.00021 -0.11 5.3e+03 7.3 0.41 0.6 +
27 0.042 -0.4 -1.1 -2.1 0.00012 -0.088 5.2e+03 2.6 0.41 0.86 +
28 0.024 -0.41 -1.1 -2.4 0.00023 -0.11 5.2e+03 13 0.41 0.38 +
29 0.055 -0.39 -1.1 -2.3 0.00019 -0.11 5.2e+03 2 4.1 0.95 ++
30 0.043 -0.41 -1.1 -2.3 0.00019 -0.1 5.2e+03 0.013 41 1 ++
31 0.043 -0.41 -1.1 -2.3 0.00019 -0.1 5.2e+03 1.4e-05 4.1e+02 1 ++
32 0.043 -0.41 -1.1 -2.3 0.00019 -0.1 5.2e+03 5.6e-07 4.1e+02 1 ++
Results saved in file b02nonlinear_000002.html
Results saved in file b02nonlinear_000002.pickle
Number of estimated models.
print(f'A total of {len(dict_of_results)} models have been estimated')
A total of 3 models have been estimated
All estimation results
compiled_results, specs = compile_estimation_results(
dict_of_results, use_short_names=True
)
compiled_results
Glossary
for short_name, spec in specs.items():
print(f'{short_name}\t{spec}')
Model_000000 train_tt_catalog:linear
Model_000001 train_tt_catalog:boxcox
Model_000002 train_tt_catalog:power
Estimation results of the Pareto optimal models.
pareto_results = pareto_optimal(dict_of_results)
compiled_pareto_results, pareto_specs = compile_estimation_results(
pareto_results, use_short_names=True
)
No Pareto file has been provided
compiled_pareto_results
Glossary.
for short_name, spec in pareto_specs.items():
print(f'{short_name}\t{spec}')
Model_000000 train_tt_catalog:power
Model_000001 train_tt_catalog:boxcox
Model_000002 train_tt_catalog:linear
Total running time of the script: (0 minutes 0.893 seconds)