Note
Go to the end to download the full example code
Estimation and simulation of a nested logit model
We estimate a nested logit model and we perform simulation using the estimated model.
- author:
Michel Bierlaire, EPFL
- date:
Wed Apr 12 21:05:16 2023
from biogeme import models
import biogeme.biogeme as bio
from optima_data import database
from scenarios import scenario
Obtain the specification for the default scenario. The definition of the scenarios is available in Specification of a nested logit model.
V, nests, Choice, _ = scenario()
The choice model is a nested logit, with availability conditions For estimation, we need the log of the probability.
logprob = models.lognested(V, None, nests, Choice)
Create the Biogeme object for estimation.
the_biogeme = bio.BIOGEME(database, logprob)
the_biogeme.modelName = 'b02estimation'
Estimate the parameters. Perform bootstrapping.
the_biogeme.bootstrap_samples = 100
results = the_biogeme.estimate(run_bootstrap=True)
0%| | 0/100 [00:00<?, ?it/s]
1%| | 1/100 [00:00<00:18, 5.36it/s]
2%|▏ | 2/100 [00:00<00:28, 3.46it/s]
3%|▎ | 3/100 [00:00<00:26, 3.63it/s]
4%|▍ | 4/100 [00:01<00:29, 3.21it/s]
5%|▌ | 5/100 [00:01<00:28, 3.34it/s]
6%|▌ | 6/100 [00:01<00:28, 3.34it/s]
7%|▋ | 7/100 [00:01<00:26, 3.56it/s]
8%|▊ | 8/100 [00:02<00:28, 3.28it/s]
9%|▉ | 9/100 [00:02<00:24, 3.75it/s]
10%|█ | 10/100 [00:02<00:26, 3.42it/s]
11%|█ | 11/100 [00:03<00:26, 3.41it/s]
12%|█▏ | 12/100 [00:03<00:26, 3.31it/s]
13%|█▎ | 13/100 [00:03<00:23, 3.69it/s]
14%|█▍ | 14/100 [00:03<00:23, 3.65it/s]
15%|█▌ | 15/100 [00:04<00:23, 3.68it/s]
16%|█▌ | 16/100 [00:04<00:21, 3.93it/s]
17%|█▋ | 17/100 [00:04<00:26, 3.15it/s]
18%|█▊ | 18/100 [00:05<00:24, 3.30it/s]
19%|█▉ | 19/100 [00:05<00:25, 3.19it/s]
20%|██ | 20/100 [00:05<00:26, 3.05it/s]
21%|██ | 21/100 [00:06<00:26, 3.04it/s]
22%|██▏ | 22/100 [00:06<00:23, 3.26it/s]
23%|██▎ | 23/100 [00:06<00:25, 3.06it/s]
24%|██▍ | 24/100 [00:07<00:23, 3.21it/s]
25%|██▌ | 25/100 [00:07<00:22, 3.34it/s]
26%|██▌ | 26/100 [00:07<00:21, 3.37it/s]
27%|██▋ | 27/100 [00:07<00:19, 3.70it/s]
28%|██▊ | 28/100 [00:08<00:19, 3.66it/s]
29%|██▉ | 29/100 [00:08<00:21, 3.24it/s]
30%|███ | 30/100 [00:08<00:22, 3.06it/s]
31%|███ | 31/100 [00:09<00:25, 2.75it/s]
32%|███▏ | 32/100 [00:09<00:25, 2.66it/s]
33%|███▎ | 33/100 [00:10<00:23, 2.82it/s]
34%|███▍ | 34/100 [00:10<00:28, 2.34it/s]
35%|███▌ | 35/100 [00:11<00:28, 2.32it/s]
36%|███▌ | 36/100 [00:11<00:26, 2.43it/s]
37%|███▋ | 37/100 [00:12<00:29, 2.17it/s]
38%|███▊ | 38/100 [00:12<00:28, 2.18it/s]
39%|███▉ | 39/100 [00:13<00:30, 2.02it/s]
40%|████ | 40/100 [00:13<00:28, 2.09it/s]
41%|████ | 41/100 [00:13<00:25, 2.27it/s]
42%|████▏ | 42/100 [00:14<00:22, 2.56it/s]
43%|████▎ | 43/100 [00:14<00:19, 2.87it/s]
44%|████▍ | 44/100 [00:14<00:17, 3.15it/s]
45%|████▌ | 45/100 [00:15<00:17, 3.09it/s]
46%|████▌ | 46/100 [00:15<00:18, 2.97it/s]
47%|████▋ | 47/100 [00:15<00:19, 2.69it/s]
48%|████▊ | 48/100 [00:16<00:21, 2.38it/s]
49%|████▉ | 49/100 [00:16<00:20, 2.50it/s]
50%|█████ | 50/100 [00:17<00:18, 2.68it/s]
51%|█████ | 51/100 [00:17<00:19, 2.57it/s]
52%|█████▏ | 52/100 [00:17<00:17, 2.80it/s]
53%|█████▎ | 53/100 [00:18<00:16, 2.91it/s]
54%|█████▍ | 54/100 [00:18<00:16, 2.81it/s]
55%|█████▌ | 55/100 [00:18<00:16, 2.70it/s]
56%|█████▌ | 56/100 [00:19<00:16, 2.68it/s]
57%|█████▋ | 57/100 [00:19<00:15, 2.72it/s]
58%|█████▊ | 58/100 [00:20<00:17, 2.43it/s]
59%|█████▉ | 59/100 [00:20<00:18, 2.23it/s]
60%|██████ | 60/100 [00:20<00:16, 2.43it/s]
61%|██████ | 61/100 [00:21<00:14, 2.74it/s]
62%|██████▏ | 62/100 [00:21<00:14, 2.62it/s]
63%|██████▎ | 63/100 [00:22<00:14, 2.47it/s]
64%|██████▍ | 64/100 [00:22<00:14, 2.52it/s]
65%|██████▌ | 65/100 [00:22<00:13, 2.68it/s]
66%|██████▌ | 66/100 [00:23<00:14, 2.42it/s]
67%|██████▋ | 67/100 [00:23<00:14, 2.35it/s]
68%|██████▊ | 68/100 [00:24<00:14, 2.22it/s]
69%|██████▉ | 69/100 [00:24<00:13, 2.27it/s]
70%|███████ | 70/100 [00:25<00:12, 2.40it/s]
71%|███████ | 71/100 [00:25<00:12, 2.38it/s]
72%|███████▏ | 72/100 [00:25<00:12, 2.21it/s]
73%|███████▎ | 73/100 [00:26<00:12, 2.24it/s]
74%|███████▍ | 74/100 [00:26<00:10, 2.37it/s]
75%|███████▌ | 75/100 [00:27<00:09, 2.54it/s]
76%|███████▌ | 76/100 [00:27<00:09, 2.59it/s]
77%|███████▋ | 77/100 [00:27<00:08, 2.82it/s]
78%|███████▊ | 78/100 [00:28<00:08, 2.73it/s]
79%|███████▉ | 79/100 [00:28<00:06, 3.05it/s]
80%|████████ | 80/100 [00:28<00:06, 2.97it/s]
81%|████████ | 81/100 [00:29<00:06, 2.96it/s]
82%|████████▏ | 82/100 [00:29<00:06, 2.86it/s]
83%|████████▎ | 83/100 [00:29<00:05, 3.03it/s]
84%|████████▍ | 84/100 [00:30<00:05, 2.94it/s]
85%|████████▌ | 85/100 [00:30<00:05, 2.90it/s]
86%|████████▌ | 86/100 [00:30<00:05, 2.66it/s]
87%|████████▋ | 87/100 [00:31<00:04, 3.05it/s]
88%|████████▊ | 88/100 [00:31<00:03, 3.10it/s]
89%|████████▉ | 89/100 [00:31<00:03, 2.85it/s]
90%|█████████ | 90/100 [00:32<00:03, 2.70it/s]
91%|█████████ | 91/100 [00:32<00:03, 2.61it/s]
92%|█████████▏| 92/100 [00:33<00:02, 2.77it/s]
93%|█████████▎| 93/100 [00:33<00:02, 2.93it/s]
94%|█████████▍| 94/100 [00:33<00:01, 3.20it/s]
95%|█████████▌| 95/100 [00:33<00:01, 2.87it/s]
96%|█████████▌| 96/100 [00:34<00:01, 2.82it/s]
97%|█████████▋| 97/100 [00:34<00:01, 2.81it/s]
98%|█████████▊| 98/100 [00:35<00:00, 2.85it/s]
99%|█████████▉| 99/100 [00:35<00:00, 2.69it/s]
100%|██████████| 100/100 [00:35<00:00, 2.63it/s]
100%|██████████| 100/100 [00:35<00:00, 2.79it/s]
Get the results in a pandas table
pandas_results = results.getEstimatedParameters()
pandas_results
Simulation
simulated_choices = logprob.getValue_c(betas=results.getBetaValues(), database=database)
simulated_choices
array([-0.65048784, -1.4326262 , -0.13259011, ..., -0.37239372,
-0.29534586, -0.26726783])
loglikelihood = logprob.getValue_c(
betas=results.getBetaValues(),
database=database,
aggregation=True,
)
print(f'Final log likelihood: {results.data.logLike}')
print(f'Simulated log likelihood: {loglikelihood}')
Final log likelihood: -1298.4982789719456
Simulated log likelihood: -1298.4982789719452
Total running time of the script: (0 minutes 37.367 seconds)