The math behind choicer: Bayesian multinomial probit
Source:vignettes/articles/bayesian_multinomial_probit_math.Rmd
bayesian_multinomial_probit_math.RmdThis document provides a detailed mathematical description of the
Bayesian multinomial probit (MNP) model as implemented in
src/mnprobit.cpp, with sampling primitives in
src/bayes_samplers.h and the RNG core in
src/rng.h.
Table of Contents
- Notation
- Model Definition
- Identification
- Priors and Joint Posterior
- The Gibbs Sampler
- Sampling Primitives
- Post-Processing and Reported Quantities
- Implementation Details
- References
Notation
| Symbol | Description |
|---|---|
| Index for individuals (choice situations) | |
| Index for alternatives; alternative 1 is the base alternative | |
| Dimension of the utility differences | |
| Choice of individual : for the base alternative, for the -th non-base alternative | |
| Latent utility differences of individual () | |
| Differenced design matrix of individual () | |
| Coefficient vector () | |
| Covariance matrix of the differenced errors () | |
| Precision matrix | |
| Prior mean and prior precision of | |
| Inverse-Wishart prior degrees of freedom and scale | |
,
burn, thin
|
Total Gibbs iterations, burn-in, thinning interval |
seed |
Master RNG seed (all streams derive from it) |
| The element of , used for identification |
1. Model Definition
1.1 Utility Specification and Differencing
Each individual derives latent utility from alternative , with jointly normal errors, and chooses the alternative with the highest utility. Only utility differences matter for the choice, so the model is estimated in differences against the base alternative (alternative 1 in the package’s integer coding):
which gives the -dimensional latent regression
where row of contains the differenced covariates .
1.2 Choice Rule
The observed choice is determined by the latent differences:
The “0” threshold is the base alternative’s (differenced) utility.
Code reference: src/mnprobit.cpp
1.3 Alternative-Specific Constants and the Base Alternative
ASCs enter the differenced model as
intercepts, one per non-base alternative: the ASC column for alternative
is an indicator that equals 1 in row
of every
.
This mirrors the package’s reference-alternative convention for the
frequentist models (first sorted alternative is the reference); the
base_alt argument moves a chosen label to the front of the
factor levels, exactly as outside_opt_label does for
prepare_mnl_data().
Balanced choice sets are required: every choice situation must
contain the same
alternatives. A user who wants an outside good includes it as explicit
rows with zero covariates and sets base_alt to its
label.
Code reference: mnprobit_utils.R (prepare_mnp_data)
2. Identification
2.1 Scale Invariance
The choice rule is invariant to a common rescaling of the latent utilities: for any ,
imply identical choice probabilities. One scale restriction is therefore required.
2.2 The Two Standard Strategies
Fully identified sampler (McCulloch, Polson & Rossi 2000): restrict inside the sampler, placing a prior directly on the identified parameters. This requires a non-standard prior on a decomposition of and a non-conjugate conditional, and the resulting chain is known to mix more slowly.
Non-identified chain with post-processing (McCulloch & Rossi 1994; the
bayesm::rmnpGibbsapproach): run the Gibbs sampler on the unrestricted with a conjugate inverse-Wishart prior, and report the identified quantities
computed per draw .
2.3 The Package Default
choicer implements strategy 2. Rationale: every Gibbs
conditional remains standard (truncated normal, multivariate normal,
inverse-Wishart), the chain navigates the posterior more freely, and the
reported quantities
are fully identified. The caveat, stated in McCulloch, Polson &
Rossi (2000), is that the prior on the identified parameters is
induced by the prior on the non-identified ones rather than specified
directly. Calling the raw-scale defaults diffuse does
not make that induced prior innocuous: scale
normalization can produce consequential dependence and tail behavior,
especially for covariance and correlation functionals. Applied work
should examine the induced prior on
and
,
run prior-predictive checks, and report sensitivity to
.
Code reference: mnprobit_utils.R (run_mnprobit post-processing)
2.4 What Identifies the Covariance in Practice
Scale normalization removes the formal redundancy; whether the data inform is a separate question. After normalization the differenced covariance carries free parameters, and the sample disciplines them only through variation that shifts choice probabilities differentially across alternatives. Keane (1992) shows that when the covariates do not vary across alternatives — demographics interacted with ASCs, or constants alone — the covariance parameters are identified by the normal functional form alone, and estimation is fragile: near-flat likelihood regions, erratic point estimates, and strong sensitivity to specification. Alternative-specific regressors (prices, distances, attributes varying across the options within a choice situation) act as the exclusion restrictions that identify in practice. The Bayesian machinery does not repeal this: with weak alternative-specific variation the posterior is dominated by the prior and the functional form rather than by the data. A useful habit is to compare the reported posterior against its prior — if they nearly coincide, the substitution pattern the covariance implies is maintained, not estimated.
3. Priors and Joint Posterior
3.1 Priors
where the inverse-Wishart density is parameterized (matching
bayesm) as
Defaults: , , , and . Thus the raw-scale prior mean is
not . This is not a contradiction because the raw scale is unidentified and every reported draw is subsequently divided by its own . More importantly, it is not a reason to call the induced prior on weak: normalization changes dependence and tail behavior. These defaults should be interrogated through prior-predictive and sensitivity analysis, especially for covariance, correlation, and substitution conclusions when alternative-specific identifying variation is limited. The engine accepts , which is sufficient for a proper inverse-Wishart under this convention; the displayed prior-mean formula exists only for .
3.2 Augmented Joint Posterior
With the latent treated as additional unknowns (Albert & Chib 1993), the joint posterior is
where is the -variate normal density and is the cone implied by the choice rule of §1.2. All three blocks of full conditionals are standard, which is exactly what data augmentation buys: no MNP choice probabilities (multivariate normal rectangle probabilities) are ever evaluated.
4. The Gibbs Sampler
One iteration cycles through three blocks.
4.1 Latent Utilities:
Given , the are independent across , and each component given the others is univariate normal, truncated to the region implied by . Writing and using the precision matrix , the untruncated conditional moments are
The truncation bounds, using the current values of the other components, are:
| Case | Lower bound | Upper bound |
|---|---|---|
| (this component chosen) | ||
| (base chosen) | ||
| , (another non-base chosen) |
Each is drawn from and immediately replaces the old value (a within- Gibbs sweep over ).
Because the are conditionally independent across , the sweep over choice situations is parallelized with OpenMP — this is an exact Gibbs step, not an approximation. The within- sweep over stays sequential.
Code reference: src/mnprobit.cpp
4.2 Coefficients:
Stacking the latent regressions and applying standard conjugate GLS algebra:
Two computational identities keep this cheap:
- Precomputed Gram blocks. Let be the matrix collecting the component- rows of all , and . Then
The do not depend on the chain and are computed once at startup; assembling then costs per iteration, independent of .
- No inverse. With the Cholesky factorization ( upper triangular), the mean solves two triangular systems and the draw is
so without ever forming .
Code reference: src/mnprobit.cpp (Gram blocks), src/mnprobit.cpp (draw)
4.3 Covariance:
With and , conjugacy of the inverse-Wishart gives
The implementation accumulates the lower triangle of in fixed order, copies it to the upper triangle, and symmetrizes before factorization. The fixed-order accumulation is deliberate: it avoids a threaded BLAS reduction whose rounding order could vary with the OpenMP configuration.
Code reference: src/mnprobit.cpp
5. Sampling Primitives
All primitives are implemented from scratch (header-only) and draw from the package’s own RNG, never from R’s RNG.
5.1 Truncated Univariate Normal
To draw from , standardize to bounds and, when , use normal symmetry to mirror the interval into the upper half-line. The current implementation selects among three exact algorithms. Write .
Wide central interval ( and ): draw until . In this region ordinary rejection avoids the relatively expensive
pnorm/qnormround trip while retaining adequate acceptance probability. This is the common MNP augmentation case.Wide or ultra-deep-tail interval ( or , outside the preceding case): use Robert’s (1995) exponential rejection. With rate
propose with , reject , and accept with probability . This remains stable arbitrarily far into the tail.
- Narrow interval ( and ): inverse CDF on the upper-tail scale,
Narrow intervals can make rejection stall. Upper-tail probabilities avoid the loss of precision that occurs when rounds to one in the positive tail.
and
are evaluated with Rmath’s pnorm/qnorm (pure
functions, thread-safe — only R’s RNG is unusable in
threads).
Code reference: src/bayes_samplers.h
5.2 Standard Normal, Gamma, Chi-Squared
- Normal: Marsaglia polar method — exact, no tables; generates pairs and caches the spare. Code reference: src/rng.h
- Gamma: Marsaglia & Tsang (2000) squeeze method — exact for any ; for the boosting identity is used. Code reference: src/rng.h
- Chi-squared, valid for non-integer (needed by Bartlett). Code reference: src/rng.h
5.3 Multivariate Normal
with the lower Cholesky factor of and .
Code reference: src/bayes_samplers.h
5.4 Wishart and Inverse-Wishart
Wishart via the Bartlett decomposition: with (lower) and lower triangular where
the draw is . Inverse-Wishart: draw and return (symmetrized).
Code reference: src/bayes_samplers.h
6. Post-Processing and Reported Quantities
The kept draws live on the non-identified scale. The R wrapper computes, for every kept draw,
and all reported summaries — posterior means (coef()),
posterior standard deviations, posterior covariance
(vcov()), and equal-tailed credible intervals
(summary()) — are computed on these identified draws.
The normalization must be per draw: the identified quantity is a nonlinear function of the chain state, so
and normalizing posterior means after averaging would be biased. By construction for every draw.
Code reference: mnprobit_utils.R (run_mnprobit post-processing)
7. Implementation Details
7.1 Data Layout and Parameter Vector
prepare_mnp_data() differences the covariates against
the base alternative and stacks the result into a single
matrix X, rows grouped by choice situation with components
in alternative order. The coefficient vector is
(
columns when use_asc = TRUE); the C++ engine sees only the
generic latent regression and has no ASC logic. Alternative-invariant
covariates difference into the span of the ASC columns and are removed
by the collinearity check.
y is an integer
-vector
with 0 for the base and
for the
-th
non-base alternative.
7.2 In-Place Chain State
The latent matrix
()
is allocated once and swept in place for the entire run — iteration
starts from iteration
’s
values, which is precisely the Markov property. The systematic-utility
matrix Mu,
workspace Vm, and all
-draw
workspaces are likewise pre-allocated. Matrix-vector products that enter
the master-thread conditionals are accumulated with explicit loops in a
fixed order; the implementation does not rely on a parallel BLAS
reduction inside the persistent OpenMP region.
Code reference: src/mnprobit.cpp
7.3 RNG Streams and Reproducibility
The RNG core is xoshiro256++ seeded via splitmix64 (the generator authors’ recommended initialization). Every consumer derives an independent stream from the master seed:
- the latent update of observation in iteration uses stream ;
- the and draws of iteration use the tagged streams and .
Streams are deterministic functions of their key, so the draws are
reproducible given the seed and a fixed number of OpenMP threads; across
different thread counts they are invariant only up to floating-point
reduction-order round-off (~1e-15), not bitwise
(independent validation disconfirmed an earlier “bitwise, tested 1-vs-4
threads” claim). When the user does not pass mcmc$seed, the
master seed is drawn from R’s RNG, so set.seed() governs
the run end-to-end, consistent with the rest of the package.
Code reference: src/rng.h, src/mnprobit.cpp
7.4 Parallelization
The entire chain runs in one persistent
#pragma omp parallel region. Within it, a static
work-sharing loop distributes choice situations for the latent sweep;
threads write disjoint columns of
and share read-only
and Mu. The
and
draws are master-only. Every 100 iterations the master polls for an
interrupt through R_ToplevelExec; abort codes are
synchronized at barriers and converted to Rcpp::stop() only
after the region closes, so neither an R long jump nor a C++ exception
crosses an OpenMP boundary. Thread count follows the package-wide
convention (set_num_threads() /
get_num_threads()). Iterations themselves remain
sequential; only conditionally independent within-iteration work is
distributed.
Code reference: src/mnprobit.cpp
7.5 Draw Storage
betadraw is
with
.
sigmadraw is
,
storing the lower triangle of
in row-major order
— the same vech_row() convention used by the mixed logit
code, with display names Sigma_ij.
Code reference: src/mnprobit.cpp
7.6 Per-Iteration Complexity
| Step | Cost | Notes |
|---|---|---|
| Latent sweep | parallelized over | |
| , residual cross-product | fixed-order master-thread loops | |
| fixed-order master-thread loop | ||
| Assemble | independent of (Gram blocks) | |
| Cholesky / solves for | ||
| draw |
For fixed , total arithmetic cost is linear in and the Gram-block construction removes an term from each iteration. The latent sweep is the principal work-shared component; its realized speedup depends on problem size, thread overhead, memory bandwidth, and the distribution of truncation-rejection work, so linear thread scaling is not assumed.
7.7 Scope of Post-Estimation
The choicer_mnp object is a posterior-draw object, not a
choicer_fit. Version 0.2.0 reports identified coefficient
and covariance summaries but does not implement
predict(), elasticities, diversion ratios, WTP, logsum,
consumer surplus, logLik(), AIC, or BIC for this class. In
particular, one must not substitute a logit softmax for MNP
probabilities: prediction requires multivariate-normal probability
evaluation or simulation under each posterior draw. These omissions are
API boundaries, not mathematical claims that the corresponding
quantities do not exist.
run_mnprobit() currently runs one chain and does not
expose the multi-chain
rank-/ESS
machinery provided for choicer_hb. Applied work should
therefore fit independently seeded runs, compare identified-scale
posterior summaries and traces externally, and check Monte Carlo
stability. Re-running a single chain longer is not a substitute for
overdispersed-chain evidence.
References
- Albert, J. H., & Chib, S. (1993). Bayesian Analysis of Binary and Polychotomous Response Data. Journal of the American Statistical Association, 88(422), 669–679.
- Allenby, G. M., & Rossi, P. E. (1999). Marketing models of consumer heterogeneity. Journal of Econometrics, 89(1–2), 57–78.
- Blackman, D., & Vigna, S. (2021). Scrambled Linear Pseudorandom Number Generators. ACM Transactions on Mathematical Software, 47(4), 1–32.
- Keane, M. P. (1992). A note on identification in the multinomial probit model. Journal of Business & Economic Statistics, 10(2), 193–200.
- Marsaglia, G., & Tsang, W. W. (2000). A Simple Method for Generating Gamma Variables. ACM Transactions on Mathematical Software, 26(3), 363–372.
- McCulloch, R., & Rossi, P. E. (1994). An exact likelihood analysis of the multinomial probit model. Journal of Econometrics, 64(1–2), 207–240.
- McCulloch, R. E., Polson, N. G., & Rossi, P. E. (2000). A Bayesian analysis of the multinomial probit model with fully identified parameters. Journal of Econometrics, 99(1), 173–193.
- Robert, C. P. (1995). Simulation of truncated normal variables. Statistics and Computing, 5(2), 121–125.
- Rossi, P. E., Allenby, G. M., & McCulloch, R. (2005). Bayesian Statistics and Marketing. John Wiley & Sons.
- Train, K. E. (2009). Discrete Choice Methods with Simulation (2nd ed.). Cambridge University Press. Chapter 5.