Note
Go to the end to download the full example code.
Sequential estimation of a choice model with a latent variableΒΆ
This example illustrates the second step of a sequential estimation procedure.
The latent variable and its structural equation are first estimated using the
Gaussian MIMIC model of plot_h02_lv_mimic_gauss. The estimated structural
parameters are then loaded from the saved results file and used to construct
the latent-variable expression appearing in the choice model.
Only the choice-model parameters are estimated in this script. The latent variable is not re-estimated jointly with the measurement equations.
Michel Bierlaire Mon Jun 15 2026, 09:54:37
import sys
from choice_latent_variables import generate_utility_functions
from number_of_draws import NUMBER_OF_DRAWS
from one_latent_variable_spec import car_centric_attitude
from optima import (
Choice,
read_data,
)
import biogeme.biogeme_logging as blog
from biogeme.biogeme import BIOGEME
from biogeme.expressions import (
Draws,
MonteCarlo,
MultipleSum,
Variable,
exp,
log,
)
from biogeme.models import logit
from biogeme.results_processing import (
EstimationResults,
get_latex_estimated_parameters,
get_latex_general_statistics,
get_pandas_estimated_parameters,
)
logger = blog.get_screen_logger(level=blog.INFO)
Load data
database = read_data()
Read the results of the previously estimated MIMIC model.
FILE_WITH_ESTIMATION_RESULTS = 'saved_results/plot_h02_lv_mimic_gauss.yaml'
try:
estimation_results = EstimationResults.from_yaml_file(
filename=FILE_WITH_ESTIMATION_RESULTS
)
except FileNotFoundError:
print(
f'File {FILE_WITH_ESTIMATION_RESULTS} does not exist. Sequential estimation cannot be performed.'
)
sys.exit()
estimated_parameters: dict[str, float] = estimation_results.get_beta_values()
Reconstruct the latent-variable expression using the parameter estimates obtained from the MIMIC model. The sequential specification keeps both the deterministic component and the random structural disturbance.
list_of_explanatory_variables = (
car_centric_attitude.structural_equation.explanatory_variables
)
# The sigma parameter was estimated on the log scale in the MIMIC model.
# We therefore exponentiate it before scaling the structural disturbance.
terms = [
estimated_parameters[f'struct_car_centric_attitude_{var}'] * Variable(var)
for var in list_of_explanatory_variables
]
structural_sigma = exp(estimated_parameters['struct_car_centric_attitude_sigma_log'])
structural_error = structural_sigma * Draws(
'car_centric_attitude_draw', 'NORMAL_MLHS_ANTI'
)
car_centric_attitude = MultipleSum(terms) + structural_error
latent_expressions = {'car_centric_attitude': car_centric_attitude}
Utility functions including the latent-variable effect.
v = generate_utility_functions(latent_expressions=latent_expressions)
Choice model estimated conditionally on the latent-variable specification.
conditional_likelihood = logit(v, None, Choice)
loglikelihood = log(MonteCarlo(conditional_likelihood))
biogeme = BIOGEME(
database,
loglikelihood,
number_of_draws=NUMBER_OF_DRAWS,
numerically_safe=True,
max_iterations=5_000,
)
biogeme.model_name = 'plot_h03_model_lv_gauss_seq'
yaml_file_name = f'saved_results/{biogeme.model_name}.yaml'
results = biogeme.estimate_or_load(yaml_file_name=yaml_file_name)
print(results.short_summary())
print(get_pandas_estimated_parameters(estimation_results=results))
general_statistics = get_latex_general_statistics(estimation_results=results)
print(general_statistics)
estimated_parameters = get_latex_estimated_parameters(estimation_results=results)
for group_name, latex_table in estimated_parameters.items():
print(group_name if group_name else 'Estimated parameters')
print(latex_table)
Biogeme parameters read from biogeme.toml.
Estimation results are read from saved_results/plot_h03_model_lv_gauss_seq.yaml. No estimation is performed.
Results for model plot_h03_model_lv_gauss_seq
Nbr of parameters: 8
Sample size: 889
Excluded data: 0
Final log likelihood: -507.5701
Akaike Information Criterion: 1031.14
Bayesian Information Criterion: 1069.461
{'Estimated parameters': Name ... Robust p-value
0 choice_scale_parameter ... 0.000038
1 choice_asc_pt ... 0.139632
2 choice_beta_time_pt ... 0.004575
3 choice_asc_car ... 0.598397
4 choice_beta_time_car ... 0.003607
5 choice_beta_car_centric_attitude_car ... 0.101159
6 choice_beta_dist_work ... 0.001952
7 choice_beta_dist_other_purposes ... 0.000813
[8 rows x 5 columns]}
%% General statistics
\section{General statistics}
\begin{tabular}{ll}
Number of estimated parameters & 8 \\
Sample size & 889 \\
Excluded observations & 0 \\
Init log likelihood & -5607.637 \\
Final log likelihood & -507.5701 \\
Likelihood ratio test for the init. model & 10200.13 \\
Rho-square for the init. model & 0.909 \\
Rho-square-bar for the init. model & 0.908 \\
Akaike Information Criterion & 1031.14 \\
Bayesian Information Criterion & 1069.461 \\
Final gradient norm & 4.4292E-03 \\
Number of draws & 50000 \\
Draws generation time & 0:00:13.203576 \\
Types of draws & car\_centric\_attitude\_draw: NORMAL\_MLHS\_ANTI \\
Bootstrapping time & None \\
Algorithm & \verb$BFGS with trust region for simple bound constraints$ \\
Cause of termination & \verb$Relative gradient = 7.8e-07 <= 6.1e-06$ \\
Number of function evaluations & \verb$118$ \\
Number of gradient evaluations & \verb$69$ \\
Number of hessian evaluations & \verb$0$ \\
Number of iterations & \verb$49$ \\
Optimization time & \verb$0:00:53.058620$ \\
Proportion of Hessian calculation & \verb$0/34 = 0.0%$ \\
Relative gradient & \verb$7.803e-07$ \\
\end{tabular}
Estimated parameters
\begin{tabular}{rlr@{.}lr@{.}lr@{.}lr@{.}l}
& & \multicolumn{2}{l}{} & \multicolumn{2}{l}{Robust} & \multicolumn{4}{l}{} \\
Parameter & & \multicolumn{2}{l}{Coeff.} & \multicolumn{2}{l}{Asympt.} & \multicolumn{4}{l}{} \\
number & Description & \multicolumn{2}{l}{estimate} & \multicolumn{2}{l}{std. error} & \multicolumn{2}{l}{$t$-stat} & \multicolumn{2}{l}{$p$-value} \\
\hline
0 & choice\_scale\_parameter & 0&0782 & 0&0190 & 4&12 & 3&80e-05 \\
1 & choice\_asc\_pt & -8&79 & 5&95 & -1&48 & 0&140 \\
2 & choice\_beta\_time\_pt & -12&3 & 4&34 & -2&84 & 0&00457 \\
3 & choice\_asc\_car & -2&65 & 5&04 & -0&527 & 0&598 \\
4 & choice\_beta\_time\_car & -26&2 & 9&01 & -2&91 & 0&00361 \\
5 & choice\_beta\_car\_centric\_attitude\_car & 3&80 & 2&32 & 1&64 & 0&101 \\
6 & choice\_beta\_dist\_work & -2&62 & 0&845 & -3&10 & 0&00195 \\
7 & choice\_beta\_dist\_other\_purposes & -4&14 & 1&24 & -3&35 & 0&000813 \\
\end{tabular}
Total running time of the script: (0 minutes 1.032 seconds)