Multinomial logit model#
This guide presents an introduction to a simple MNL model example using PyCMTensor.
Include all necessary packages, including pandas and numpy:
1import numpy as np
2import pandas as pd
3import pycmtensor as cmt
4from pycmtensor.expressions import Beta
5from pycmtensor.models import MNL
6from pycmtensor.statistics import elasticities
Load the swissmetro.dat dataset and define the Data object. The arguments for Data are as follows:
df: the pandas DataFrame objectchoice: column label in the DataFrame object which corresponds to the dependent choice variabledrop: list of conditional statement(s) which is used to drop certain rowsautoscale: boolean variable which indicates whether to scale the variables to between -10 and 10autoscale_except: list of column label(s) which to ignore whenautoscaleis Truesplit: split ratio for training:validation datasets (1.0indicates all samples are used for training and no validation samples)
1sm = pd.read_csv("swissmetro.dat", sep="\t")
2db = cmt.Data(
3 df=sm,
4 choice="CHOICE",
5 drop=[sm["CHOICE"] == 0],
6 autoscale=True,
7 autoscale_except=["ID", "ORIGIN", "DEST", "CHOICE"],
8 split=0.8,
9)
Model specification#
Describe the model by defining the \(\beta\) variables Beta() and specify the utility as a list of equations. Optionally, include the availability conditions if required.
Variables are referenced by using db["<name_of_column>"]
1b_cost = Beta("b_cost", 0.0, None, None, 0)
2b_time = Beta("b_time", 0.0, None, None, 0)
3asc_train = Beta("asc_train", 0.0, None, None, 0)
4asc_car = Beta("asc_car", 0.0, None, None, 0)
5asc_sm = Beta("asc_sm", 0.0, None, None, 1)
6
7U_1 = b_cost * db["TRAIN_CO"] + b_time * db["TRAIN_TT"] + asc_train
8U_2 = b_cost * db["SM_CO"] + b_time * db["SM_TT"] + asc_sm
9U_3 = b_cost * db["CAR_CO"] + b_time * db["CAR_TT"] + asc_car
10
11# specify the utility function and the availability conditions
12U = [U_1, U_2, U_3] # utility
13AV = [db["TRAIN_AV"], db["SM_AV"], db["CAR_AV"]] # availability
Define the model#
Define the MNL model MNL(db=,params=,utility=,av=,**kwargs).
Argument options explanation:
db: theDataobjectparams: dict of params where the keys are the name of the parameter and the values are theBetaobjects. For example,params={"asc_car":asc_car, "asc_train":asc_train}. A simple shortcut is to uselocals()to load all locally defined Python variables.
keyword arguments are the model hyperparameters. For example, optimizer=SGD sets the optimizer algorithm to stochastic gradient descent.
1mymodel = MNL(db=db, params=locals(), utility=U, av=AV)
Train the model#
Train the model by calling the function .train(db, **kwargs).
Keyword arguments are the training hyperparameters. Possible options are max_steps:int, patience:int, lr_scheduler:scheduler.Scheduler, batch_size:int. For more information and other possible options, see config.Config.hyperparameters
1mymodel.train(db, max_steps=100)
11:01:26 [INFO] Start (n=8575)
11:01:35 [INFO] End (t=00:00:10, VE=40.224%, LL=-7529.683422816989, S=23)
Output results and statistics#
Beta parameters
1print(mymodel.results.beta_statistics())
value std err t-test p-value rob. std err rob. t-test \
asc_car -0.853707 0.047113 -18.120447 0.0 0.001773 -481.494189
asc_sm 0.0 - - - - -
asc_train -1.845829 0.05049 -36.558574 0.0 0.010834 -170.368325
b_cost 0.025854 0.019678 1.313796 0.188915 0.00523 4.943254
b_time -0.5217 0.053767 -9.702955 0.0 0.003695 -141.184022
rob. p-value
asc_car 0.0
asc_sm -
asc_train 0.0
b_cost 0.000001
b_time 0.0
Model statistics
1print(mymodel.results.model_statistics())
value
Number of training samples used 8575.0
Number of validation samples used 2143.0
Init. log likelihood -8885.386433
Final log likelihood -7529.683423
Accuracy 59.78%
Likelihood ratio test 2711.40602
Rho square 0.152577
Rho square bar 0.152014
Akaike Information Criterion 15069.366846
Bayesian Information Criterion 15104.649877
Final gradient norm 0.003011
Correlation matrix
1print(mymodel.results.model_correlation_matrix())
b_cost b_time asc_train asc_car
b_cost 1.000000 0.215873 0.234180 -0.019954
b_time 0.215873 1.000000 0.750515 0.814288
asc_train 0.234180 0.750515 1.000000 0.685223
asc_car -0.019954 0.814288 0.685223 1.000000
Benchmark
1print(mymodel.results.benchmark())
value
Seed 980
Model build time 00:00:13
Model train time 00:00:10
iterations per sec 345.14/s
Predictions
1# predictions
2print(mymodel.predict(db, return_choices=False))
3print(np.unique(mymodel.predict(db), return_counts=True))
[[0.12138601 0.55492529 0.3236887 ]
[0.10724806 0.5969908 0.29576114]
[0.10717803 0.60330066 0.28952132]
...
[0.11440961 0.55831256 0.32727783]
[0.12859771 0.5241943 0.34720798]
[0.10920566 0.58416641 0.30662793]]
(array([1, 2], dtype=int64), array([2068, 75], dtype=int64))
Elasticities
1print(elasticities(mymodel, db, 0, "TRAIN_TT"))
[-0.06027963 -0.15127238 -0.20175932 ... -0.02805637 -0.05351249
-0.04710554]