The multinomial probit model1 provides a mathematical representation of process of choosing one out of a finite number of mutually exclusive alternatives depending on a number of regressor variables characterizing the alternatives and the decider. It possesses the interpretation of a random utility maximization (RUM) model, whereby a decider assigns a utility value to each alternative and picks the one with highest utility. As the modeler does not have full information, the model represents the utility using a systematic part, depending on regressor variables, plus an additive error term, which for probit models is normally distributed (Agresti 2015).
The model output are conditional choice probabilities depending on the regressor values.2 The regressor variables potentially consist of characteristics describing the alternatives and the deciders. To be concrete, assume that we possess data of decision makers which choose between alternatives at each of choice occasions3. One example can be the choice of one out of a number of cars, both conventional and electric, for the next purchase. Specific to each decision maker, alternative and choice occasion, we observe choice attributes (like the purchase price, for example) that we use to explain the choices. Decider ’s utility for alternative at choice occasion is modeled as
for , and , where
() is a (column) vector of () characteristics of alternative as faced by at choice occasion ,
is a (column) vector of characteristics of the decider at occasion ,
is a vector of coefficients,
are called alternative specific constants (ASCs),
and is the model’s error term vector for at , which in the probit model is assumed to be multivariate normally distributed with zero mean and covariance matrix . Details on how such data sets are represented in Rprobit are given in the vignette Data and Simulation.
The three types of regressor variables are called
type I variables () that vary over alternatives but influence the utility with a common coefficient (that is, not depending on the alternative),
type II variables () that do not vary over alternatives and influence the utility with coefficients differing over alternatives,
type III variables () that vary over alternatives but influence the utility with coefficients differing over alternatives.
Now let denote the event that decision maker chooses alternative at her -th choice occasion. Assuming utility maximizing behavior of the decision makers, the decisions are linked to the utilities via4
In Rprobit the model is represented using a formula
as in the mlogit R package (Croissant 2020). The following
formula describes the dependent variable choice as a
function of the type I variable V1, the type II variable
V2 and the type III variable V3:
Hereby the following rules apply:
choice must be categorical variable listing the choices
taken.0V1 + V2 + V3.+ 0 such as V2 + 0.Consider a household deciding between different power trains for the car to be purchased. The options are a battery powered electric vehicle (BEV) and an internal combustion engine (ICE).
The alternative specific variables may include:
pricerangePSMainAll of these depend on the alternative at the time of buying. The driving range coefficient for the BEV will be much higher than for the ICEV, as the refilling of the ICEV is simpler.
The decider characteristics may include:
HIHSlocCFAttitudeThe corresponding formula might be assuming that
Attitude is not measured:
The tradeoff between the purchase price and the driving range of a car may depend on the commuting habits of the deciders that are not represented well in the data.
When maximizing utilities the level is not of importance: Adding a constant to all utilities does not change the maximizing alternative. Also the scale is not of importance: Multiplying all utilities with a positive constant leaves the maximizing alternative indifferent. This implies identifiability issues. (Train 2009)
For type I variables the difference between two utilities depends on the difference between the regressor variables. Therefore variables that do not vary over alternatives (resulting in ) cannot be used as type I variables. Additionally, needs to be identified from . Thus the type I variables must not be multicollinear.
For each type II variable the model includes coefficients . Subtracting from all utilities eliminates the coefficients corresponding to the first alternative from the model. The remaining coefficients for the type II variables are identifiable, if there are no multicollinearities between the type II variables. Here the choice of the first variable is arbitrary and any base alternative (=reference) can be chosen.
For type III variables we obtain in the utility differences. It follows that here all coefficients are identified, if vary over alternatives and are not multicollinear.
The same issue arises for the error terms: Subtracting the error from all utilities does not change the maximizing alternative. Thus we can without restriction of generality assume that (or pick any alternative as a reference alternative in this respect).
Finally for the identification of the scale one may either restrict one coefficient to unity (or minus unity). Or one might restrict one variance to a particular value (typically 1 or 0.5). For details see Train (2009) Section 5.2. Numerically fixing one coefficient to is more stable than fixing a variance.
While the specification of type I, type II and type III variables is
convenient for model specification and data storage, it is inconvenient
in the estimation phase. Thus Rprobit uses a unified
framework, recoding type II and type III variables into a set of type I
variables. This is exemplified below. The choice data object (described
in detail in the vignette Data and
Simulation) provides the method build_design to perform
the recoding according to a model formulation.
A type II variable is specific to the decider but not the alternatives. There are parameters corresponding to the type II variable, one for each alternative except for the base alternative. By interacting the type II variable with indicators of the alternatives we obtain variables varying over the alternatives: , where denotes the indicator function. This renders the vector of utilities (using the first alternative as the base):
This transforms the scalar type II variable in type I variables listed as the columns of the matrix .
The reformulation of one scalar type III variable into type I variables (listed as the diagonal of a matrix) follows a similar pattern:
Note that contrary to type II variables, for type III variables we obtain new type I variables.
Note that all coefficient vectors above are constant across decision makers. This assumption is too restrictive for many applications.5 Unobserved heterogeneity in choice behavior can be modeled by imposing a distribution on any element of such that each decider can have their own preferences.
Such models use a random coefficient setup wherein the random coefficients are assumed to be drawn independent of all regressor variables and the errors. Mathematically this implies a mixing of the implied choice probabilities (the expectation over the random terms mathematically leads to an integration). Rprobit currently only implements normally distributed random parameters, that can be correlated across coefficients.
More precisely, in the unified model representation using only type I variables some of the components of can be mixed using a normal distribution for mixing. We assume that the mixed coefficients appear in the trailing part of , that is .
It is assumed that all coefficients corresponding to one original
type II or type III variables are either mixed or not mixed. Thus the
mixed coefficients can be specified by providing the names of their
corresponding variables. For example in the model
formula <- choice ~ V1 | V2 | V3 the coefficients to
variable V1 and V3 are defined as mixing
via
According to the unification described above we achieve model specification using only type I variables as
Some of the components of can be mixed using a normal distribution for mixing. We assume that the mixed coefficients appear in the trailing part of , that is .
Therefore the parameterization of the model requires parameters for the vector and the two variance matrices and . The parameterization has to conform to the restriction that variance matrices are positive semidefinite. Additionally the parameterization must ascertain identifiability of the parameters.
The parameter vector is parameterized using a linear affine mapping, to allow for the imposition of some restrictions:
This allows to incorporate linear equality constraints on the parameters. For instance, restricting with free is achieved using
A common device to ensure positive semidefiniteness of matrices is to use Cholesky factors. For each positive semidefinite matrix there exists a lower triangular matrix such that .
We chose to parameterize the vectorization of the lower half of the Cholesky matrices using a linear affine mapping:
where denotes columnwise vectorization of the lower triangular matrix (including the diagonal). Thus for , for example, the lower triangular Cholesky factor includes 6 entries:
Here can be used to fix entries for identifiability reasons. For example, for parameterizing a diagonal matrix where the (1,1) entry is fixed to equal can be done using
Thus there are two parameters and . We do not impose non-negativity of these parameters, which leads to a non-identifiability as without this restriction on the diagonal entries the Cholesky factors are not unique. The tradeoff made here is the inclusion of multiple well separated global optima in favor of being able to leave out parameter non-negativity restrictions.
Rprobit collects all information related to the
model in a mod object. This object is implemented as a
R6 class. See here for the
perils of R6 classes.
The following example parameterizes a model for mode choice depending
on the price of the alternative modes (used as a type I
variable) and time (used as a type III variable) featuring
alternatives. The
ASC are mixed using a normal distribution:
Printing the object provides an overview of the specification:
print(m_basic)
#> <mod object>
#>
#> Formula: choice ~ price | 1 | time
#> Random effects: ASC
#> Alternative names: A, B, C
#> Coefficients: 4 fixed, 2 random
#> Free parameters total: 10
#>
#> Utility equations:
#>
#> U_A = b[1] * price_A + b[2] * time_A + eps[1]
#> U_B = b[1] * price_B + b[3] * time_B + b[5] + eps[2]
#> U_C = b[1] * price_C + b[4] * time_C + b[6] + eps[3]
#>
#> Parameter restrictions:
#>
#> b = H_b theta_b
#> length(theta_b): 6
#> H_b (6 x 6) =
#> theta_1 theta_2 theta_3 theta_4 theta_5 theta_6
#> b[1]:price 1 0 0 0 0 0
#> b[2]:time_A 0 1 0 0 0 0
#> b[3]:time_B 0 0 1 0 0 0
#> b[4]:time_C 0 0 0 1 0 0
#> b[5]:ASC_B 0 0 0 0 1 0
#> b[6]:ASC_C 0 0 0 0 0 1
#>
#>
#> O = vech(chol(Omega)) = H_O theta_O
#> length(theta_O): 2
#> H_O (3 x 2) =
#> theta_7 theta_8
#> ASC_B_:_ASC_B 1 0
#> ASC_C_:_ASC_B 0 0
#> ASC_C_:_ASC_C 0 1
#>
#>
#> L = vech(chol(Sigma)) = H_L theta_L + f_L
#> length(theta_L): 2
#> H_L (6 x 2) =
#> theta_9 theta_10
#> A_:_A 0 0
#> B_:_A 0 0
#> C_:_A 0 0
#> B_:_B 0 0
#> C_:_B 1 0
#> C_:_C 0 1
#> f_L (6 x 1) =
#>
#> A_:_A 0
#> B_:_A 0
#> C_:_A 0
#> B_:_B 1
#> C_:_B 0
#> C_:_C 0We can see that six coefficient parameters
(length_theta_b = 6) are free, the two ASCs are random
leading to a covariance
matrix that is modeled as a diagonal matrix using two parameters
(length_theta_O = 2). Finally the variance uses two parameters
(length_theta_L = 2):
There are more options to initialize a mod object:
alt_names <- c("train", "bus", "car")
m <- mod$new(
formula = formula, re = re, alt = 3,
alt_names = alt_names, # alternative labels
ref_alt = "train", # reference alternative (for type-2 effects)
corr_re = FALSE, # structure for Omega
error_struc = "diag" # structure for Sigma
)
print(m)
#> <mod object>
#>
#> Formula: choice ~ price | 1 | time
#> Random effects: ASC
#> Alternative names: train, bus, car
#> Coefficients: 4 fixed, 2 random
#> Free parameters total: 10
#>
#> Utility equations:
#>
#> U_train = b[1] * price_train + b[2] * time_train + eps[1]
#> U_bus = b[1] * price_bus + b[3] * time_bus + b[5] + eps[2]
#> U_car = b[1] * price_car + b[4] * time_car + b[6] + eps[3]
#>
#> Parameter restrictions:
#>
#> b = H_b theta_b
#> length(theta_b): 6
#> H_b (6 x 6) =
#> theta_1 theta_2 theta_3 theta_4 theta_5 theta_6
#> b[1]:price 1 0 0 0 0 0
#> b[2]:time_train 0 1 0 0 0 0
#> b[3]:time_bus 0 0 1 0 0 0
#> b[4]:time_car 0 0 0 1 0 0
#> b[5]:ASC_bus 0 0 0 0 1 0
#> b[6]:ASC_car 0 0 0 0 0 1
#>
#>
#> O = vech(chol(Omega)) = H_O theta_O
#> length(theta_O): 2
#> H_O (3 x 2) =
#> theta_7 theta_8
#> ASC_bus_:_ASC_bus 1 0
#> ASC_car_:_ASC_bus 0 0
#> ASC_car_:_ASC_car 0 1
#>
#>
#> L = vech(chol(Sigma)) = H_L theta_L + f_L
#> length(theta_L): 2
#> H_L (6 x 2) =
#> theta_9 theta_10
#> train_:_train 0 0
#> bus_:_train 0 0
#> car_:_train 0 0
#> bus_:_bus 1 0
#> car_:_bus 0 0
#> car_:_car 0 1
#> f_L (6 x 1) =
#>
#> train_:_train 1
#> bus_:_train 0
#> car_:_train 0
#> bus_:_bus 0
#> car_:_bus 0
#> car_:_car 0This adds labels to the alternatives and changes the error covariance
matrix to a diagonal structure. For the recoding ref_alt
defines the reference alternative, for which no ASC or type II
regressors are generated to avoid non-identifiability. The correlation
structure of is set to
FALSE leading to a diagonal matrix. The error variance
matrix is chosen diagonal. The available error structures are:
"full": the first Cholesky column is fixed to zero,
L[2,2] is fixed to one, and the remaining entries are
free"diag": the first Cholesky diagonal entry is fixed to
one and the remaining diagonal entries are free"ident": is
proportional to the identity matrix, with one shared free Cholesky
diagonal parameter"fixed": is
fixed to the identity matrix.Having defined objects, one wants to manipulate the models. To do this, we must know the fields of the model object. These can be grouped into fields that are read-only and fields that can be adapted.
Read-only fields are:
alt number of alternativesb_count vector of two integers, number of fixed and
random coefficientsvar_names list containing the names of fixed and random
coefficientslength_theta number of free model parameters, together
with length_theta_b, length_theta_O, and
length_theta_L splitting it into the parts corresponding to
.mod_list list containing the model representation used
by the numerical routines.These cannot be changed directly but are inferred from the adjustable fields:
formula: model formulare: vector of variables with random coefficientsalt_names: vector of strings labeling the
alternativesref_alt string identifying reference alternativeH_b, f_b, H_O, f_O, H_L, f_L: matrices implementing the
affine linear restrictions for the various matrices.suppress_warnings: Boolean.The last field suppresses warnings issued by the object. Changing
model-defining fields such as formula, re,
alt_names, or ref_alt can automatically adapt
dependent restriction matrices and vectors. By default, the object warns
about these adaptations.
To demonstrate this behavior, consider adding a random coefficient
for price:
m$suppress_warnings <- TRUE
m$re <- c("ASC", "price")
m
#> <mod object>
#>
#> Formula: choice ~ price | 1 | time
#> Random effects: ASC, price
#> Alternative names: train, bus, car
#> Coefficients: 3 fixed, 3 random
#> Free parameters total: 11
#>
#> Utility equations:
#>
#> U_train = b[1] * time_train + b[4] * price_train + eps[1]
#> U_bus = b[2] * time_bus + b[4] * price_bus + b[5] + eps[2]
#> U_car = b[3] * time_car + b[4] * price_car + b[6] + eps[3]
#>
#> Parameter restrictions:
#>
#> b = H_b theta_b
#> length(theta_b): 6
#> H_b (6 x 6) =
#> theta_1 theta_2 theta_3 theta_4 theta_5 theta_6
#> b[1]:time_train 1 0 0 0 0 0
#> b[2]:time_bus 0 1 0 0 0 0
#> b[3]:time_car 0 0 1 0 0 0
#> b[4]:price 0 0 0 1 0 0
#> b[5]:ASC_bus 0 0 0 0 1 0
#> b[6]:ASC_car 0 0 0 0 0 1
#>
#>
#> O = vech(chol(Omega)) = H_O theta_O
#> length(theta_O): 3
#> H_O (6 x 3) =
#> theta_7 theta_8 theta_9
#> price_:_price 1 0 0
#> ASC_bus_:_price 0 0 0
#> ASC_car_:_price 0 0 0
#> ASC_bus_:_ASC_bus 0 1 0
#> ASC_car_:_ASC_bus 0 0 0
#> ASC_car_:_ASC_car 0 0 1
#>
#>
#> L = vech(chol(Sigma)) = H_L theta_L + f_L
#> length(theta_L): 2
#> H_L (6 x 2) =
#> theta_10 theta_11
#> train_:_train 0 0
#> bus_:_train 0 0
#> car_:_train 0 0
#> bus_:_bus 1 0
#> car_:_bus 0 0
#> car_:_car 0 1
#> f_L (6 x 1) =
#>
#> train_:_train 1
#> bus_:_train 0
#> car_:_train 0
#> bus_:_bus 0
#> car_:_bus 0
#> car_:_car 0Since suppress_warnings is set to TRUE, no
warning is issued. If we set suppress_warnings to
FALSE and change the model back, we get a warning:
m$suppress_warnings <- FALSE
m$re <- c("ASC")
m
#> <mod object>
#>
#> Formula: choice ~ price | 1 | time
#> Random effects: ASC
#> Alternative names: train, bus, car
#> Coefficients: 4 fixed, 2 random
#> Free parameters total: 10
#>
#> Utility equations:
#>
#> U_train = b[1] * price_train + b[2] * time_train + eps[1]
#> U_bus = b[1] * price_bus + b[3] * time_bus + b[5] + eps[2]
#> U_car = b[1] * price_car + b[4] * time_car + b[6] + eps[3]
#>
#> Parameter restrictions:
#>
#> b = H_b theta_b
#> length(theta_b): 6
#> H_b (6 x 6) =
#> theta_1 theta_2 theta_3 theta_4 theta_5 theta_6
#> b[1]:price 1 0 0 0 0 0
#> b[2]:time_train 0 1 0 0 0 0
#> b[3]:time_bus 0 0 1 0 0 0
#> b[4]:time_car 0 0 0 1 0 0
#> b[5]:ASC_bus 0 0 0 0 1 0
#> b[6]:ASC_car 0 0 0 0 0 1
#>
#>
#> O = vech(chol(Omega)) = H_O theta_O
#> length(theta_O): 2
#> H_O (3 x 2) =
#> theta_7 theta_8
#> ASC_bus_:_ASC_bus 1 0
#> ASC_car_:_ASC_bus 0 0
#> ASC_car_:_ASC_car 0 1
#>
#>
#> L = vech(chol(Sigma)) = H_L theta_L + f_L
#> length(theta_L): 2
#> H_L (6 x 2) =
#> theta_9 theta_10
#> train_:_train 0 0
#> bus_:_train 0 0
#> car_:_train 0 0
#> bus_:_bus 1 0
#> car_:_bus 0 0
#> car_:_car 0 1
#> f_L (6 x 1) =
#>
#> train_:_train 1
#> bus_:_train 0
#> car_:_train 0
#> bus_:_bus 0
#> car_:_bus 0
#> car_:_car 0To impose a restriction on , we
may change the matrices H_b, f_b directly. For example,
restricting to equal we may use the following commands:
m$H_b <- m$H_b[, -1]
m$f_b[1] <- 1
m
#> <mod object>
#>
#> Formula: choice ~ price | 1 | time
#> Random effects: ASC
#> Alternative names: train, bus, car
#> Coefficients: 4 fixed, 2 random
#> Free parameters total: 9
#>
#> Utility equations:
#>
#> U_train = b[1] * price_train + b[2] * time_train + eps[1]
#> U_bus = b[1] * price_bus + b[3] * time_bus + b[5] + eps[2]
#> U_car = b[1] * price_car + b[4] * time_car + b[6] + eps[3]
#>
#> Parameter restrictions:
#>
#> b = H_b theta_b + f_b
#> length(theta_b): 5
#> H_b (6 x 5) =
#> theta_1 theta_2 theta_3 theta_4 theta_5
#> b[1]:price 0 0 0 0 0
#> b[2]:time_train 1 0 0 0 0
#> b[3]:time_bus 0 1 0 0 0
#> b[4]:time_car 0 0 1 0 0
#> b[5]:ASC_bus 0 0 0 1 0
#> b[6]:ASC_car 0 0 0 0 1
#> f_b (6 x 1) =
#>
#> price 1
#> time_train 0
#> time_bus 0
#> time_car 0
#> ASC_bus 0
#> ASC_car 0
#>
#>
#> O = vech(chol(Omega)) = H_O theta_O
#> length(theta_O): 2
#> H_O (3 x 2) =
#> theta_6 theta_7
#> ASC_bus_:_ASC_bus 1 0
#> ASC_car_:_ASC_bus 0 0
#> ASC_car_:_ASC_car 0 1
#>
#>
#> L = vech(chol(Sigma)) = H_L theta_L + f_L
#> length(theta_L): 2
#> H_L (6 x 2) =
#> theta_8 theta_9
#> train_:_train 0 0
#> bus_:_train 0 0
#> car_:_train 0 0
#> bus_:_bus 1 0
#> car_:_bus 0 0
#> car_:_car 0 1
#> f_L (6 x 1) =
#>
#> train_:_train 1
#> bus_:_train 0
#> car_:_train 0
#> bus_:_bus 0
#> car_:_bus 0
#> car_:_car 0To check that the first element is restricted to one, we can draw a random parameter vector and calculate the system corresponding to this parameter vector:
set.seed(1)
theta <- runif(m$length_theta)
(parameter <- m$build_parameter(theta))
#> $b
#>
#> price 1.0000000
#> time_train 0.2655087
#> time_bus 0.3721239
#> time_car 0.5728534
#> ASC_bus 0.9082078
#> ASC_car 0.2016819
#>
#> $O
#>
#> ASC_bus_:_ASC_bus 0.8983897
#> ASC_car_:_ASC_bus 0.0000000
#> ASC_car_:_ASC_car 0.9446753
#>
#> $Omega_chol
#> ASC_bus ASC_car
#> ASC_bus 0.8983897 0.0000000
#> ASC_car 0.0000000 0.9446753
#>
#> $Omega
#> ASC_bus ASC_car
#> ASC_bus 0.807104 0.0000000
#> ASC_car 0.000000 0.8924114
#>
#> $L
#>
#> train_:_train 1.0000000
#> bus_:_train 0.0000000
#> car_:_train 0.0000000
#> bus_:_bus 0.6607978
#> car_:_bus 0.0000000
#> car_:_car 0.6291140
#>
#> $Sigma_chol
#> train bus car
#> train 1 0.0000000 0.000000
#> bus 0 0.6607978 0.000000
#> car 0 0.0000000 0.629114
#>
#> $Sigma
#> train bus car
#> train 1 0.0000000 0.0000000
#> bus 0 0.4366537 0.0000000
#> car 0 0.0000000 0.3957845Sometimes it is useful to go the other way and calculate the parameter vector corresponding to a particular system:
theta2 <- m$build_theta(
b = parameter$b,
Omega = parameter$Omega,
Sigma = parameter$Sigma
)
all.equal(theta, theta2)
#> [1] TRUEThis helps for example when a given variance matrix shall be parameterized.
Restrictions on and can be handled analogously. Note, that
Rprobit provides much freedom with respect to choosing
the parameterization of the model. The user can change the matrices and
vectors in the three affine linear mappings within the dimensions
implied by the model. Consequently, the user has to make sure that her
parameterization is identifiable. (Train 2009) discusses in section 5.2.
guidelines to achieve identification. This is supported via the method
check_identifiability which performs a numeric check by
calculating the column rank of the Jacobian of a normalized
representation of , , and the differenced for a randomly chosen parameter vector
.
If in the example above, for example, we change the parameterization
back to estimate all entries in
and to also include the -element
of as a free parameter, then the
model loses its identifiability due to a lack of identifying the scale
of the utility. Some problems with identifiability can be checked using
the check_identifiability() function. The first model is
identifiable…
… while the second is not:
m2 <- m$clone()
m2$H_L <- diag(6)[, -c(1, 2, 3)]
m2$f_L <- matrix(0, ncol = 1, nrow = 6)
m2$check_identifiability()
#> Warning: The parameter set may not be identified; check the specification.
#> [1] FALSENote, that instead of just assigning m to the second
model m2 we need to clone() the object.
R6 objects have reference semantics, so a direct
assignment would refer to the same object. Cloning creates an
independent object.
The name probit is a portmanteau of probability and unit. (Bliss 1934)↩︎
An alternative way to view the probit model is that it provides a function linking regressors to choice probabilities. The RUM interpretation is only one viewpoint. Thus one does not have to believe in rational behavior to use the probit models.↩︎
For notational simplicity, the number of choice occasions is assumed to be the same for each decision maker here. However, we are not restricted to this case: Rprobit allows for unbalanced panels, i.e. varying over deciders. Of course, the cross-sectional case is possible.↩︎
Here, picks the smallest maximizing argument in the unlikely case of a draw.↩︎
For example, the tradeoff between the purchase price and the driving range may depend on the commuting habits of the deciders that are not represented well in the data.↩︎