.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/latentbis/plot_m03_simultaneous_estimation.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_latentbis_plot_m03_simultaneous_estimation.py: Choice model with the latent variable: maximum likelihood estimation ==================================================================== Mixture of logit. Measurement equation for the indicators. Maximum likelihood (full information) estimation. :author: Michel Bierlaire, EPFL :date: Fri Apr 14 10:07:43 2023 .. GENERATED FROM PYTHON SOURCE LINES 13-58 .. code-block:: default import sys from functools import reduce import biogeme.biogeme_logging as blog import biogeme.biogeme as bio import biogeme.exceptions as excep import biogeme.distributions as dist import biogeme.results as res from biogeme import models from biogeme.expressions import ( Beta, Variable, log, RandomVariable, Integrate, Elem, bioNormalCdf, exp, ) from read_or_estimate import read_or_estimate from optima import ( database, male, age, haveChildren, highEducation, childCenter, childSuburb, SocioProfCat, WaitingTimePT, Choice, TimePT_scaled, TimeCar_scaled, MarginalCostPT_scaled, CostCarCHF_scaled, distance_km_scaled, PurpHWH, PurpOther, ) logger = blog.get_screen_logger(level=blog.INFO) logger.info('Example m03_simultaneous_estimation.py') .. rst-class:: sphx-glr-script-out .. code-block:: none Example m03_simultaneous_estimation.py .. GENERATED FROM PYTHON SOURCE LINES 59-60 Read the estimates from the structural equation estimation. .. GENERATED FROM PYTHON SOURCE LINES 60-72 .. code-block:: default MODELNAME = 'm01_latent_variable' try: struct_results = res.bioResults(pickleFile=f'saved_results/{MODELNAME}.pickle') except excep.BiogemeError: print( f'Run first the script {MODELNAME}.py in order to generate the ' f'file {MODELNAME}.pickle, and move it to the directory saved_results' ) sys.exit() struct_betas = struct_results.getBetaValues() .. GENERATED FROM PYTHON SOURCE LINES 73-74 Coefficients .. GENERATED FROM PYTHON SOURCE LINES 74-94 .. code-block:: default coef_intercept = Beta('coef_intercept', struct_betas['coef_intercept'], None, None, 0) coef_age_30_less = Beta( 'coef_age_30_less', struct_betas['coef_age_30_less'], None, None, 0 ) coef_haveChildren = Beta( 'coef_haveChildren', struct_betas['coef_haveChildren'], None, None, 0 ) coef_highEducation = Beta( 'coef_highEducation', struct_betas['coef_highEducation'], None, None, 0 ) coef_artisans = Beta('coef_artisans', struct_betas['coef_artisans'], None, None, 0) coef_employees = Beta('coef_employees', struct_betas['coef_employees'], None, None, 0) coef_male = Beta('coef_male', struct_betas['coef_male'], None, None, 0) coef_child_center = Beta( 'coef_child_center', struct_betas['coef_child_center'], None, None, 0 ) coef_child_suburb = Beta( 'coef_child_suburb', struct_betas['coef_child_suburb'], None, None, 0 ) .. GENERATED FROM PYTHON SOURCE LINES 95-96 Latent variable: structural equation .. GENERATED FROM PYTHON SOURCE LINES 98-100 Define a random parameter, normally distributed, designed to be used for numerical integration .. GENERATED FROM PYTHON SOURCE LINES 100-104 .. code-block:: default omega = RandomVariable('omega') density = dist.normalpdf(omega) sigma_s = Beta('sigma_s', 1, None, None, 0) .. GENERATED FROM PYTHON SOURCE LINES 105-118 .. code-block:: default ACTIVELIFE = ( coef_intercept + coef_child_center * childCenter + coef_child_suburb * childSuburb + coef_highEducation * highEducation + coef_artisans * (SocioProfCat == 5) + coef_employees * (SocioProfCat == 6) + coef_age_30_less * (age <= 30) + coef_male * male + coef_haveChildren * haveChildren + sigma_s * omega ) .. GENERATED FROM PYTHON SOURCE LINES 119-120 Measurement equations .. GENERATED FROM PYTHON SOURCE LINES 120-129 .. code-block:: default indicators = [ 'ResidCh01', 'ResidCh04', 'ResidCh05', 'ResidCh06', 'LifSty07', 'LifSty10', ] .. GENERATED FROM PYTHON SOURCE LINES 130-131 We define the intercept parameters. The first one is normalized to 0. .. GENERATED FROM PYTHON SOURCE LINES 131-134 .. code-block:: default inter = {k: Beta(f'inter_{k}', 0, None, None, 0) for k in indicators[1:]} inter[indicators[0]] = Beta(f'INTER_{indicators[0]}', 0, None, None, 1) .. GENERATED FROM PYTHON SOURCE LINES 135-136 We define the coefficients. The first one is normalized to 1. .. GENERATED FROM PYTHON SOURCE LINES 136-139 .. code-block:: default coefficients = {k: Beta(f'coeff_{k}', 0, None, None, 0) for k in indicators[1:]} coefficients[indicators[0]] = Beta(f'B_{indicators[0]}', 1, None, None, 1) .. GENERATED FROM PYTHON SOURCE LINES 140-141 We define the measurement equations for each indicator .. GENERATED FROM PYTHON SOURCE LINES 141-143 .. code-block:: default linear_models = {k: inter[k] + coefficients[k] * ACTIVELIFE for k in indicators} .. GENERATED FROM PYTHON SOURCE LINES 144-145 We define the scale parameters of the error terms. .. GENERATED FROM PYTHON SOURCE LINES 145-148 .. code-block:: default sigma_star = {k: Beta(f'sigma_star_{k}', 1, 1.0e-5, None, 0) for k in indicators[1:]} sigma_star[indicators[0]] = Beta(f'sigma_star_{indicators[0]}', 1, None, None, 1) .. GENERATED FROM PYTHON SOURCE LINES 149-150 Symmetric threshold. .. GENERATED FROM PYTHON SOURCE LINES 150-157 .. code-block:: default delta_1 = Beta('delta_1', 0.1, 1.0e-5, None, 0) delta_2 = Beta('delta_2', 0.2, 1.0e-5, None, 0) tau_1 = -delta_1 - delta_2 tau_2 = -delta_1 tau_3 = delta_1 tau_4 = delta_1 + delta_2 .. GENERATED FROM PYTHON SOURCE LINES 158-159 Ordered probit models. .. GENERATED FROM PYTHON SOURCE LINES 159-177 .. code-block:: default tau_1_residual = {k: (tau_1 - linear_models[k]) / sigma_star[k] for k in indicators} tau_2_residual = {k: (tau_2 - linear_models[k]) / sigma_star[k] for k in indicators} tau_3_residual = {k: (tau_3 - linear_models[k]) / sigma_star[k] for k in indicators} tau_4_residual = {k: (tau_4 - linear_models[k]) / sigma_star[k] for k in indicators} dict_prob_indicators = { k: { 1: bioNormalCdf(tau_1_residual[k]), 2: bioNormalCdf(tau_2_residual[k]) - bioNormalCdf(tau_1_residual[k]), 3: bioNormalCdf(tau_3_residual[k]) - bioNormalCdf(tau_2_residual[k]), 4: bioNormalCdf(tau_4_residual[k]) - bioNormalCdf(tau_3_residual[k]), 5: 1 - bioNormalCdf(tau_4_residual[k]), 6: 1.0, -1: 1.0, -2: 1.0, } for k in indicators } .. GENERATED FROM PYTHON SOURCE LINES 178-179 Product of the likelihood of the indicators. .. GENERATED FROM PYTHON SOURCE LINES 179-186 .. code-block:: default prob_indicators = reduce( lambda x, y: x * Elem(dict_prob_indicators[y], Variable(y)), indicators, Elem(dict_prob_indicators[indicators[0]], Variable(indicators[0])), ) .. GENERATED FROM PYTHON SOURCE LINES 187-190 Choice model Read the estimates from the sequential estimation, and use them as starting values .. GENERATED FROM PYTHON SOURCE LINES 190-201 .. code-block:: default MODELNAME = 'm02_sequential_estimation' try: choice_results = res.bioResults(pickleFile=f'saved_results/{MODELNAME}.pickle') except excep.BiogemeError: print( f'Run first the script {MODELNAME}.py in order to generate the ' f'file {MODELNAME}.pickle, and move it to the directory saved_results' ) sys.exit() choice_betas = choice_results.getBetaValues() .. GENERATED FROM PYTHON SOURCE LINES 202-228 .. code-block:: default ASC_CAR = Beta('ASC_CAR', choice_betas['ASC_CAR'], None, None, 0) ASC_PT = Beta('ASC_PT', 0, None, None, 1) ASC_SM = Beta('ASC_SM', choice_betas['ASC_SM'], None, None, 0) BETA_COST_HWH = Beta('BETA_COST_HWH', choice_betas['BETA_COST_HWH'], None, None, 0) BETA_COST_OTHER = Beta( 'BETA_COST_OTHER', choice_betas['BETA_COST_OTHER'], None, None, 0 ) BETA_DIST = Beta('BETA_DIST', choice_betas['BETA_DIST'], None, None, 0) BETA_TIME_CAR_REF = Beta( 'BETA_TIME_CAR_REF', choice_betas['BETA_TIME_CAR_REF'], None, 0, 0 ) BETA_TIME_CAR_AL = Beta( 'BETA_TIME_CAR_AL', choice_betas['BETA_TIME_CAR_AL'], None, None, 0 ) BETA_TIME_PT_REF = Beta( 'BETA_TIME_PT_REF', choice_betas['BETA_TIME_PT_REF'], None, 0, 0 ) BETA_TIME_CAR = BETA_TIME_CAR_REF * exp(BETA_TIME_CAR_AL * ACTIVELIFE) BETA_TIME_PT_AL = Beta( 'BETA_TIME_PT_AL', choice_betas['BETA_TIME_PT_AL'], None, None, 0 ) BETA_TIME_PT = BETA_TIME_PT_REF * exp(BETA_TIME_PT_AL * ACTIVELIFE) BETA_WAITING_TIME = Beta( 'BETA_WAITING_TIME', choice_betas['BETA_WAITING_TIME'], None, None, 0 ) .. GENERATED FROM PYTHON SOURCE LINES 229-230 Definition of utility functions: .. GENERATED FROM PYTHON SOURCE LINES 230-247 .. code-block:: default V0 = ( ASC_PT + BETA_TIME_PT * TimePT_scaled + BETA_WAITING_TIME * WaitingTimePT + BETA_COST_HWH * MarginalCostPT_scaled * PurpHWH + BETA_COST_OTHER * MarginalCostPT_scaled * PurpOther ) V1 = ( ASC_CAR + BETA_TIME_CAR * TimeCar_scaled + BETA_COST_HWH * CostCarCHF_scaled * PurpHWH + BETA_COST_OTHER * CostCarCHF_scaled * PurpOther ) V2 = ASC_SM + BETA_DIST * distance_km_scaled .. GENERATED FROM PYTHON SOURCE LINES 248-249 Associate utility functions with the numbering of alternatives .. GENERATED FROM PYTHON SOURCE LINES 249-251 .. code-block:: default V = {0: V0, 1: V1, 2: V2} .. GENERATED FROM PYTHON SOURCE LINES 252-254 Conditional on omega, we have a logit model (called the kernel) for the choice .. GENERATED FROM PYTHON SOURCE LINES 254-256 .. code-block:: default condprob = models.logit(V, None, Choice) .. GENERATED FROM PYTHON SOURCE LINES 257-259 Conditional on omega, we have the product of ordered probit for the indicators. .. GENERATED FROM PYTHON SOURCE LINES 259-261 .. code-block:: default condlike = prob_indicators * condprob .. GENERATED FROM PYTHON SOURCE LINES 262-263 We integrate over omega using numerical integration .. GENERATED FROM PYTHON SOURCE LINES 263-265 .. code-block:: default loglike = log(Integrate(condlike * density, 'omega')) .. GENERATED FROM PYTHON SOURCE LINES 266-267 Create the Biogeme object .. GENERATED FROM PYTHON SOURCE LINES 267-270 .. code-block:: default the_biogeme = bio.BIOGEME(database, loglike) the_biogeme.modelName = 'm03_simultaneous_estimation' .. rst-class:: sphx-glr-script-out .. code-block:: none File biogeme.toml has been parsed. .. GENERATED FROM PYTHON SOURCE LINES 271-273 If estimation results are saved on file, we read them to speed up the process. If not, we estimate the parameters. .. GENERATED FROM PYTHON SOURCE LINES 273-275 .. code-block:: default results = read_or_estimate(the_biogeme=the_biogeme, directory='saved_results') .. GENERATED FROM PYTHON SOURCE LINES 276-278 .. code-block:: default print(results.short_summary()) .. rst-class:: sphx-glr-script-out .. code-block:: none Results for model m03_simultaneous_estimation Nbr of parameters: 37 Sample size: 1906 Excluded data: 359 Final log likelihood: -15178.83 Akaike Information Criterion: 30431.66 Bayesian Information Criterion: 30637.11 .. GENERATED FROM PYTHON SOURCE LINES 279-282 .. code-block:: default print(f'Final log likelihood: {results.data.logLike:.3f}') print(f'Output file: {results.data.htmlFileName}') .. rst-class:: sphx-glr-script-out .. code-block:: none Final log likelihood: -15178.829 Output file: m03_simultaneous_estimation.html .. GENERATED FROM PYTHON SOURCE LINES 283-284 .. code-block:: default results.getEstimatedParameters() .. raw:: html
Value Rob. Std err Rob. t-test Rob. p-value
ASC_CAR 0.664627 0.119378 5.567438 2.585113e-08
ASC_SM 0.169755 0.306409 0.554016 5.795680e-01
BETA_COST_HWH -1.180142 0.267148 -4.417565 9.981925e-06
BETA_COST_OTHER -0.556328 0.114508 -4.858404 1.183359e-06
BETA_DIST -1.151594 0.262733 -4.383143 1.169792e-05
BETA_TIME_CAR_AL 0.001630 0.004710 0.346112 7.292588e-01
BETA_TIME_CAR_REF -6.414696 1.292676 -4.962337 6.965005e-07
BETA_TIME_PT_AL -0.000477 0.005487 -0.086948 9.307131e-01
BETA_TIME_PT_REF -1.777138 0.607850 -2.923644 3.459605e-03
BETA_WAITING_TIME -0.020978 0.007567 -2.772418 5.564161e-03
coef_age_30_less 47.924453 3.586199 13.363577 0.000000e+00
coef_artisans -0.347921 0.381494 -0.911997 3.617704e-01
coef_child_center 2.401157 2.303511 1.042390 2.972308e-01
coef_child_suburb 1.586959 2.300117 0.689947 4.902274e-01
coef_employees -0.007955 0.250222 -0.031793 9.746373e-01
coef_haveChildren 13.727760 2.233246 6.146998 7.896321e-10
coef_highEducation -15.357200 1.412346 -10.873536 0.000000e+00
coef_intercept -46.875602 3.602223 -13.012964 0.000000e+00
coef_male 15.747680 1.296598 12.145379 0.000000e+00
coeff_LifSty07 0.219754 0.032807 6.698373 2.107514e-11
coeff_LifSty10 0.220491 0.027794 7.932942 2.220446e-15
coeff_ResidCh04 0.251910 0.027454 9.175749 0.000000e+00
coeff_ResidCh05 0.602666 0.047296 12.742425 0.000000e+00
coeff_ResidCh06 0.383646 0.041095 9.335647 0.000000e+00
delta_1 33.783060 3.120931 10.824674 0.000000e+00
delta_2 71.483870 6.216996 11.498137 0.000000e+00
inter_LifSty07 -58.539864 5.548443 -10.550683 0.000000e+00
inter_LifSty10 -13.721599 2.182355 -6.287520 3.225777e-10
inter_ResidCh04 13.152788 2.031354 6.474887 9.488255e-11
inter_ResidCh05 -111.806138 9.999910 -11.180714 0.000000e+00
inter_ResidCh06 -29.530546 3.713242 -7.952767 1.776357e-15
sigma_s 69.519678 6.177397 11.253878 0.000000e+00
sigma_star_LifSty07 78.148260 7.047972 11.088049 0.000000e+00
sigma_star_LifSty10 66.904224 5.969069 11.208486 0.000000e+00
sigma_star_ResidCh04 63.302189 5.767499 10.975674 0.000000e+00
sigma_star_ResidCh05 91.806284 8.382677 10.951905 0.000000e+00
sigma_star_ResidCh06 93.782658 8.467819 11.075185 0.000000e+00


.. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.193 seconds) .. _sphx_glr_download_auto_examples_latentbis_plot_m03_simultaneous_estimation.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_m03_simultaneous_estimation.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_m03_simultaneous_estimation.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_