.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/bayesian_swissmetro/plot_b11_cnl.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_bayesian_swissmetro_plot_b11_cnl.py: 11. Cross-nested logit ====================== Bayesian estimation of a cross-nested logit model with two nests: - one with existing alternatives (car and train), - one with public transportation alternatives (train and Swissmetro) Michel Bierlaire, EPFL Mon Nov 03 2025, 20:14:23 .. GENERATED FROM PYTHON SOURCE LINES 14-23 .. code-block:: Python import biogeme.biogeme_logging as blog from IPython.core.display_functions import display from biogeme.bayesian_estimation import BayesianResults, get_pandas_estimated_parameters from biogeme.biogeme import BIOGEME from biogeme.expressions import Beta from biogeme.models import logcnl from biogeme.nests import NestsForCrossNestedLogit, OneNestForCrossNestedLogit .. GENERATED FROM PYTHON SOURCE LINES 24-25 See the data processing script: :ref:`swissmetro_data`. .. GENERATED FROM PYTHON SOURCE LINES 25-45 .. code-block:: Python from swissmetro_data import ( CAR_AV_SP, CAR_CO_SCALED, CAR_TT_SCALED, CHOICE, GA, SM_AV, SM_COST_SCALED, SM_HE, SM_TT_SCALED, TRAIN_AV_SP, TRAIN_COST_SCALED, TRAIN_HE, TRAIN_TT_SCALED, database, ) logger = blog.get_screen_logger(level=blog.INFO) logger.info('Example b11_cnl.py') .. rst-class:: sphx-glr-script-out .. code-block:: none Example b11_cnl.py .. GENERATED FROM PYTHON SOURCE LINES 46-47 Parameters to be estimated. .. GENERATED FROM PYTHON SOURCE LINES 47-59 .. code-block:: Python 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_swissmetro = Beta('b_time_swissmetro', 0, None, 0, 0) b_time_train = Beta('b_time_train', 0, None, 0, 0) b_time_car = Beta('b_time_car', 0, None, 0, 0) b_cost = Beta('b_cost', 0, None, 0, 0) b_headway_swissmetro = Beta('b_headway_swissmetro', 0, None, 0, 0) b_headway_train = Beta('b_headway_train', 0, None, 0, 0) ga_train = Beta('ga_train', 0, None, None, 0) ga_swissmetro = Beta('ga_swissmetro', 0, None, None, 0) .. GENERATED FROM PYTHON SOURCE LINES 60-63 .. code-block:: Python existing_nest_parameter = Beta('existing_nest_parameter', 1.05, 1, 3, 0) public_nest_parameter = Beta('public_nest_parameter', 1.05, 1, 3, 0) .. GENERATED FROM PYTHON SOURCE LINES 64-65 Nest membership parameters. .. GENERATED FROM PYTHON SOURCE LINES 65-68 .. code-block:: Python alpha_existing = Beta('alpha_existing', 0.5, 0, 1, 0) alpha_public = 1 - alpha_existing .. GENERATED FROM PYTHON SOURCE LINES 69-70 Definition of the utility functions .. GENERATED FROM PYTHON SOURCE LINES 70-86 .. code-block:: Python v_train = ( asc_train + b_time_train * TRAIN_TT_SCALED + b_cost * TRAIN_COST_SCALED + b_headway_train * TRAIN_HE + ga_train * GA ) v_swissmetro = ( asc_sm + b_time_swissmetro * SM_TT_SCALED + b_cost * SM_COST_SCALED + b_headway_swissmetro * SM_HE + ga_swissmetro * GA ) v_car = asc_car + b_time_car * CAR_TT_SCALED + b_cost * CAR_CO_SCALED .. GENERATED FROM PYTHON SOURCE LINES 87-88 Associate utility functions with the numbering of alternatives .. GENERATED FROM PYTHON SOURCE LINES 88-90 .. code-block:: Python v = {1: v_train, 2: v_swissmetro, 3: v_car} .. GENERATED FROM PYTHON SOURCE LINES 91-92 Associate the availability conditions with the alternatives .. GENERATED FROM PYTHON SOURCE LINES 92-94 .. code-block:: Python av = {1: TRAIN_AV_SP, 2: SM_AV, 3: CAR_AV_SP} .. GENERATED FROM PYTHON SOURCE LINES 95-96 Definition of nests. .. GENERATED FROM PYTHON SOURCE LINES 96-113 .. code-block:: Python nest_existing = OneNestForCrossNestedLogit( nest_param=existing_nest_parameter, dict_of_alpha={1: alpha_existing, 2: 0.0, 3: 1.0}, name='existing', ) nest_public = OneNestForCrossNestedLogit( nest_param=public_nest_parameter, dict_of_alpha={1: alpha_public, 2: 1.0, 3: 0.0}, name='public', ) nests = NestsForCrossNestedLogit( choice_set=[1, 2, 3], tuple_of_nests=(nest_existing, nest_public) ) .. GENERATED FROM PYTHON SOURCE LINES 114-115 The choice model is a cross-nested logit, with availability conditions. .. GENERATED FROM PYTHON SOURCE LINES 115-117 .. code-block:: Python log_probability = logcnl(v, av, nests, CHOICE) .. GENERATED FROM PYTHON SOURCE LINES 118-119 Create the Biogeme object .. GENERATED FROM PYTHON SOURCE LINES 119-129 .. code-block:: Python the_biogeme = BIOGEME( database, log_probability, chains=4, bayesian_draws=40_000, warmup=40_000, calculate_loo=False, ) the_biogeme.model_name = 'b11_cnl' .. rst-class:: sphx-glr-script-out .. code-block:: none Biogeme parameters read from biogeme.toml. .. GENERATED FROM PYTHON SOURCE LINES 130-131 Estimate the parameters. .. GENERATED FROM PYTHON SOURCE LINES 131-138 .. code-block:: Python try: results = BayesianResults.from_netcdf( filename=f'saved_results/{the_biogeme.model_name}.nc' ) except FileNotFoundError: results = the_biogeme.bayesian_estimation() .. rst-class:: sphx-glr-script-out .. code-block:: none Loaded NetCDF file size: 9.1 GB load finished in 52660 ms (52.66 s) .. GENERATED FROM PYTHON SOURCE LINES 139-141 .. code-block:: Python print(results.short_summary()) .. rst-class:: sphx-glr-script-out .. code-block:: none posterior_predictive_loglike finished in 11028 ms (11.03 s) expected_log_likelihood finished in 423 ms best_draw_log_likelihood finished in 209 ms /Users/bierlair/python_envs/venv313/lib/python3.13/site-packages/arviz/stats/stats.py:1667: UserWarning: For one or more samples the posterior variance of the log predictive densities exceeds 0.4. This could be indication of WAIC starting to fail. See http://arxiv.org/abs/1507.04544 for details warnings.warn( waic_res finished in 23126 ms (23.13 s) waic finished in 23126 ms (23.13 s) /Users/bierlair/python_envs/venv313/lib/python3.13/site-packages/arviz/stats/stats.py:1057: RuntimeWarning: overflow encountered in exp weights = 1 / np.exp(len_scale - len_scale[:, None]).sum(axis=1) /Users/bierlair/python_envs/venv313/lib/python3.13/site-packages/numpy/_core/_methods.py:52: RuntimeWarning: overflow encountered in reduce return umr_sum(a, axis, dtype, out, keepdims, initial, where) /Users/bierlair/python_envs/venv313/lib/python3.13/site-packages/arviz/stats/stats.py:797: UserWarning: Estimated shape parameter of Pareto distribution is greater than 0.70 for one or more samples. You should consider using a more robust model, this is because importance sampling is less likely to work well if the marginal posterior and LOO posterior are very different. This is more likely to happen with a non-robust model and highly influential observations. warnings.warn( loo_res finished in 597241 ms (9.95 min) loo finished in 597242 ms (9.95 min) Sample size 6768 Sampler NUTS Number of chains 4 Number of draws per chain 40000 Total number of draws 160000 Acceptance rate target 0.9 Run time 2:32:21.137282 Posterior predictive log-likelihood (sum of log mean p) -6715.03 Expected log-likelihood E[log L(Y|θ)] -109707.06 Best-draw log-likelihood (posterior upper bound) -4998.66 WAIC (Widely Applicable Information Criterion) -8656808.31 WAIC Standard Error 474795.01 Effective number of parameters (p_WAIC) 8650093.28 LOO (Leave-One-Out Cross-Validation) -231017.83 LOO Standard Error 5573.76 Effective number of parameters (p_LOO) 224302.79 .. GENERATED FROM PYTHON SOURCE LINES 142-144 .. code-block:: Python pandas_results = get_pandas_estimated_parameters(estimation_results=results) display(pandas_results) .. rst-class:: sphx-glr-script-out .. code-block:: none Diagnostics computation took 1237.0 seconds (cached). Name Value (mean) ... ESS (bulk) ESS (tail) 0 asc_train -0.215706 ... 4.384520 4.001150 1 ga_train 0.763243 ... 5.009253 4.000800 2 ga_swissmetro -0.336791 ... 5.213472 4.001500 3 asc_car -0.310076 ... 7.014123 81.991726 4 b_time_train -1.198929 ... 5.795722 4.084138 5 b_cost -0.726218 ... 4.954078 78.640614 6 b_headway_train -0.898006 ... 4.955540 4.000800 7 alpha_existing 0.662106 ... 6.837447 4.007692 8 existing_nest_parameter 1.989690 ... 4.963419 80.614325 9 b_time_swissmetro -1.155630 ... 6.781623 4.000800 10 b_headway_swissmetro -0.597729 ... 4.959977 4.000800 11 b_time_car -0.879311 ... 4.383433 4.000800 12 public_nest_parameter 1.991096 ... 14.658280 80.734784 [13 rows x 12 columns] .. rst-class:: sphx-glr-timing **Total running time of the script:** (32 minutes 5.512 seconds) .. _sphx_glr_download_auto_examples_bayesian_swissmetro_plot_b11_cnl.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_b11_cnl.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_b11_cnl.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_b11_cnl.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_