logitr (development version)
-
Breaking change: the default
numDrawsfor mixed logit models increased from50to500. Draw counts in the tens (the historical convention: {mlogit} and {gmnl} default to 40, Stata’smixlogitto 50) produce noticeably unstable simulated log-likelihoods, especially with many random parameters – large enough to change model-selection decisions. With the compiled backend the extra cost is a very low overhead on typical models, so a statistically sound default is now affordable. Models estimated with the default will produce (better, but) different results than under previous versions; setnumDraws = 50explicitly to reproduce old results. - The parallelized multistart now uses the {mirai} package instead of
parallel::mclapply()/PSOCK clusters, which gives consistent behavior across platforms (no separate Windows code path). Behavior is otherwise unchanged: the cores are used to run the multistart iterations in parallel, and each model is estimated single-threaded (benchmarking shows this is more efficient than using threads to speed up individual models). The message printed at the start of a multistart now says so. Advanced users can nest the two forms of parallelism by explicitly settingnumThreadsalongside a multistart. logitr runs its daemons on a dedicated {mirai} compute profile, so it will not interfere with (or tear down) any daemons you have set up yourself. - Standard deviation estimates for uncorrelated mixed logit models are now always reported as positive. The sign of a standard deviation is not identified (the mixing distributions are symmetric, so
sd = sandsd = -sdescribe the same model), so only the magnitude is meaningful. This avoids the confusion of occasionally seeing a negative standard deviation. The sign change is implemented as an exact relabeling of the converged model (the standard draw columns of flipped parameters are negated along with the coefficient), so the reported log-likelihood, gradient, standard errors, and predictions are exactly those of the converged solution. Correlated models are unaffected, since there the parameters are Cholesky factors whose signs jointly determine the covariance matrix. - Added a compiled C++ backend for mixed logit models, controlled with the new
backendargument. This is now the default for mixed logit (MXL) models (backend = "cpp"), and is roughly 4x faster than the previous R implementation (and faster still with multiple threads; seenumThreads) while producing the same results to floating-point precision. Multinomial logit (MNL) models continue to use the R implementation. All mixed logit model types are supported: preference and willingness-to-pay (WTP) space, uncorrelated and correlated heterogeneity, and normal, log-normal, and censored-normal parameter distributions. Setbackend = "cpu"to use the native R implementation instead (for example if you need exactly bit-reproducible results). Note that installing the development version from source now requires a C++ compiler (see the installation instructions); the released CRAN version does not. - Added multithreaded evaluation of the mixed logit log-likelihood via the new
numThreadsargument (used bybackend = "cpp"). The random draws are processed in parallel, giving further speedups on top of the compiled backend that scale with the number of cores. Defaults to using a single thread when running a parallel multistart (numMultiStarts > 1) and all but one of the available cores otherwise. - Changed the default
drawTypefor mixed logit models from"halton"to"sobol". Sobol draws are better distributed than Halton draws in higher dimensions, where Halton sequences become correlated (roughly when there are more than 5 random parameters). Both are deterministic, so results remain reproducible. - Added support for Modified Latin Hypercube Sampling draws via
drawType = "mlhs"(Hess, Train, and Polak 2006). MLHS draws typically reach a given level of accuracy with fewer draws than Halton draws in higher dimensions. Unlike Halton and Sobol draws, MLHS draws are randomized and are therefore controlled byset.seed(). - Tightened the default optimization stopping tolerances on the objective:
ftol_relandftol_abschanged from1e-6to1e-10(the parameter tolerancesxtol_rel/xtol_absare unchanged at1e-6). With the looser value, runs could stop as soon as the log-likelihood stalled between iterations, sometimes at points with clearly non-zero gradients – which is what occasionally producedNaNstandard errors (an indefinite hessian at a non-converged point). The tighter default costs only a few percent more iterations (negligible with the compiled backend) and returns solutions with gradients near zero. Setoptions = list(ftol_rel = 1e-6, ftol_abs = 1e-6, ...)to reproduce old behavior. - Fixed the analytic gradient for WTP space models with a censored-normal scale parameter (
randScale = "cn"). Draws where the scale censors to zero previously producedNaNentries in the gradient (a0/0in the scale parameter’s partials), which caused optimization failures. - Added the
numDrawsBatchargument to stream the random draws in batches when evaluating the mixed logit log-likelihood withbackend = "cpu". This keeps peak memory bounded by the batch size rather than the total number of draws, which makes large draw counts (e.g. 10,000+) feasible on the R backend. By default logitr streams automatically only when the draws would otherwise exceed an internal memory budget, so typical models are unaffected. The default"cpp"backend is memory-flat in the number of draws and ignores this argument.
logitr 1.1.2
CRAN release: 2024-07-24
- Added
broom.helpers (>= 1.15.0)andgtsummary (>= 2.0.0)in DESCRIPTION to accord with an update in {gtsummary}.
logitr 1.1.1
CRAN release: 2023-09-29
- Updated the
convergence.Rmdvignette to not run any actual code using other packages to fix issue on CRAN where not all packages are available on all platforms. Now the results are hard-coded in place. - Fixed bug in
makeObsID()wheretable()was sorting the results stored inreps, which has to be manually undone. Fixes #50.
logitr 1.1.0
CRAN release: 2023-05-17
- Modified
predict()method to use theintervalandlevelarguments of more standardpredict()methods. - Added
ci()function. - Added
logit_probs()function.
logitr 1.0.1
CRAN release: 2023-02-19
- Fixed bug in
adjustFactorLevels()where thelevels_origobject was being accidentally overwritten. - Changed the name of
adjustFactorLevels()tocheckFactorLevels(). - Added a startup message when the package is loaded.
logitr 0.8.0
CRAN release: 2022-10-03
- Added
tidy(),glance(), andaugment()methods for use with the {broom} package. - Added
model.matrix.logitr(),terms.logitr(), andmodel.frame.logitr()methods for use with {broom.helpers}. - Added new vignette comparing convergence issues in WTP space models with other similar packages.
- Added new vignette on summarizing results from estimated models.
logitr 0.7.2
- Checks were added to make the
panelIDandclusterUDvariables a sequentially increasing numeric vector and to stop the program if there are any repeated IDs in these variables. - A patch was added to address a bug in the computation of clustered errors where the data in clusters of size 1 needed to be forced into a matrix with correct dimensions.
logitr 0.7.1
- A patch was added to make the
obsIDvariable a sequentially increasing numeric vector (this was previously done but was accidentally removed in prior updates). - A patch was added to pass the
modelSpacevariable along inside thevcov()method.
logitr 0.7.0
CRAN release: 2022-06-16
- A new vignette on benchmarking was added which tests the package speed against other similar packages.
- A new data set,
runtimes, was included, which is exported from the colab notebook used for benchmarking here: https://colab.research.google.com/drive/1vYlBdJd4xCV43UwJ33XXpO3Ys8xWkuxx?usp=sharing - Sobol draws are supported via a new
drawTypeargument. - A warning is displayed against using Halton draws after 5 random variables have been specified in a mixed logit model. Users are encouraged to switch to using Sobol draws and increasing the number of draws to at least 200.
- Changed the argument name
pricetoscaleParto be more general. - Changed the argument name
randPricetorandScaleto be more general. - The
modelSpaceargument is no longer required for specifying a WTP space model as it is redundant. Including ascaleParargument is enough to determine that it is a WTP space model.
logitr 0.6.1
CRAN release: 2022-06-12
- Fixes error on some of the gradient tests from 0.6.0 release. The gradient tests were sensitive to the random starting parameters, so I modified how the starting parameters were set for the first iteration of a multistart loop such that they would be more consistent.
logitr 0.6.0
CRAN release: 2022-06-11
- Added the
correlationargument to include correlated heterogeneity. - Added support for new mixed logit distributions: zero-censored normal
- Added new input checks for the
obsIDandoutcomearguments. -
vcov.logitr()method now returnsobject$vcovif the user setvcov = TRUEduring estimation (avoids a redundant calculation ofvcov, which is more efficient). - Added new datasets:
apolloModeChoiceData,electricity
logitr 0.5.1
- Patched a bug in how standard errors were being computed when clustering. The source of the error was in re-scaling results post-estimation.
logitr 0.5.0
CRAN release: 2022-01-04
- The multistart optimization loop is now parallelized.
- Exported the
fquantile()function, which is a faster implementation of thestats::quantile()function.
logitr 0.4.0
CRAN release: 2021-10-25
Larger changes:
- A new
predict.logitr()method was added for making probability and choice predictions from logitr class objects. - The
predictProbs()andpredictChoices()functions were depreciated. - Added new
fitted.logitr()andresiduals.logitr()methods. - Added optional
predictargument to the mainlogitr()function which controls whether predicted probabilities, fitted.values, and residuals are included in the returned object. Default setting is TRUE. - Changed the name of the coefficients vector in the returned object from “coef” to “coefficients” to be consistent with other packages.
- Changed the argument name from “choice” to “outcome” to be more general
logitr 0.3.1
- Bug fix: Cast X object to matrix for single-parameter models
- Updated the logic for clustering with and without panel data
- Added the
se.logitr()method. - Added the
vcovargument to thelogitr()function. - Improved vignette on interaction models with individual-specific variable interactions.
logitr 0.3.0
CRAN release: 2021-08-13
Breaking changes with v0.2.0:
- Several arguments were moved out of the previous
optionsargument and are now passed directly as arguments tologitr(). These include:numMultiStarts,useAnalyticGrad,scaleInputs,startParBounds,standardDraws,numDraws,startVals. Theoptionsargument is now only used for options to control the optimization handled bynloptr(). - Options for keeping all model outputs on a multistart were removed.
Summary of larger updates:
- Added support for panel data in the log-likelihood function and gradients.
- Several argument names in the
logitr()function were changed to make them easier to understand:choiceNamebecamechoice,obsIDNamebecameobsID,parNamesbecamepars,priceNamebecameprice,weightsNamebecameweights,clusterNamebecamecluster. If used, old names will be passed to the new argument names and a warning will be displayed. - The log-likelihood and gradient functions were overhauled to improve computational efficiency, resulting in substantially faster estimation for all models.
- The following new methods were introduced:
print.logitr(),logLik.logitr(),coef.summary.logitr(),vcov.logitr(),terms.logitr()
Summary of smaller updates:
- Improved
summary.logitr()andcoef.logitr()methods for better printing, now usingprintCoefmat(). - Added input checks for
wtp()andwtpCompare()functions - Fixed some errors in some of the documentation examples and removed the dontrun commands on all of them.
- Added the
altIDNameargument topredictChoices()andpredictProbs()to preserve the row order of predictions for each alternative in each set of alternatives. Closes issue #13. - Fixed bug in data encoding where random parameter names were not aligned with encoded data.
- Added input checks for all predict functions.
logitr 0.2.6
Major changes were made to the gradient functions, which dramatically improved computational efficiency. MNL and MXL models in either preference or WTP spaces now use the faster implementation of the logit calculations.
logitr 0.2.5
This version was the first implementation of an alternative approach for computing the logit probabilities, which increased computational speed. Specifically, the formulation was to compute P = 1 / (1 + sum(exp(V - V_chosen)))
logitr 0.2.4
The vcov() method was modified such that it computes the covariance post model estimation. Previously, the covariance matrix was being computed internally in the logitr() function, and vcov() just returned this value, which was computationally much slower.
logitr 0.2.3
Several breaking changes in this version.
- Several argument names were changed to make them easier to understand. These include:
choiceName–>choice,obsIDName–>obsID,parNames–>pars,priceName–>price,weightsName–>weights,clusterName–>cluster. - Several arguments were moved out of the previous
optionsargument and are now passed directly as arguments tologitr(). These include:numMultiStarts,useAnalyticGrad,scaleInputs,startParBounds,standardDraws,numDraws,startVals. - Some minor tweaks to printing methods.
logitr 0.2.2
- Improved
summary.logitr()andcoef.logitr()methods for better printing, usingprintCoefmat() - Added new methods:
print.logitr(),logLik.logitr(),coef.summary.logitr(),vcov.logitr() - Removed option for keeping all model outputs.
- Added input checks for
wtp()andwtpCompare()functions - Fixed some errors in some of the examples and made them all run (removed dontrun commands).
logitr 0.2.1
- Added
altIDNameargument topredictChoices()andpredictProbs()to preserve the row order of predictions for each alternative in each set of alternatives. Closes issue #13. - Fixed bug in data encoding where random parameter names were not aligned with encoded data.
- Added input checks for all predict functions.
logitr 0.2.0
CRAN release: 2021-06-14
Summary of larger updates:
- New prediction functions:
predictChoices()andpredictProbs(), and , depreciatedsimulateShares(). - Added robust covariance matrix calculations.
- Added support for clustering errors.
- Major modifications to the
recodeData()function to improve encoding efficiency. - Depreciated
dummyCode()
logitr 0.1.4
- Added
predictChoices()function. - Added
predictShares()function, depreciatingsimulateShares().
logitr 0.1.3
- Modified the
recodeData()anddummyCode()functions for improved speed. - Updated
simulateShares()to work with the automatic dummy coding from the revisedrecodeData()anddummyCode()functions. - Added support for
simulateShares()to compute shares for multiple sets of alternatives. - Added tests for encoding functions
- Added covariance matrix to model export
Bugs
- When simulating shares from a WTP model, only accepted a price named “price” rather than something else such as “Price” - fixed this.
- In
simulateShares(), the shares were not correctly computed with a WTP space model because price was still being multiplied by -1. This has been corrected. - Changes to automatic dummy coding were accidentally ignoring factor levels - that’s been fixed.
logitr 0.1.2
- Fixed bug where model with single variable would error due to a matrix being converted to a vector in the
standardDraws()function - Fixed bug in
getCatVarDummyNames()- previously used string matching, which can accidentally match with other similarly-named variables. - Fixed bug in
rowsum()where thereorderargument was set toTRUE, which resulted in wrong logit calculations unless theobsIDhappened to be already sorted.
logitr 0.1.1
- Changed how failures to converge are handled. Previously would continue to run a while loop. Now it fails and records the failure, along with appropriate changes in summary() and coef().
- Re-defined the wtp space utility models as BX - p. Before it was p + BX and p was re-defined as -1*p.
- If tidyverse library is loaded, data frames were getting converted to tibbles, which broke some things. Fixed this by forcing the input data to be a data.frame()
logitr 0.1.0
CRAN release: 2021-01-19
Summary of smaller updates:
- Reduced the length of the title in DESCRIPTION to less than 65 characters.
- Changed package names in title and description to single quotes, e.g: {nloptr} -> ‘nloptr’
- Added reference in description with doi to Train (2009) “Discrete Choice Methods with Simulation, 2nd Edition”.
- Added statements to dummyCode.Rd and statusCodes.Rd
- Added statements to dummyCode.Rd and statusCodes.Rd.
- Updated description for summary.logitr.Rd.
- Modified multiple functions to use message()/warning() instead of print()/cat().
- Added
algorithmto theoptionsinput, with the default being set to"NLOPT_LD_LBFGS".
Bugs
- Fixed tiny bug in
getParTypes()function - previously was not returning the correctparNamesfor continuous vs. discrete variables. - Added an input check to make sure the modelSpace argument is either
"pref"or"wtp". - Added an input check to make sure the
priceNameargument is only used when themodelSpaceargument is set to"wtp".
logitr 0.0.5
logitr 0.0.4
Weighted models, new dataset, new encoding features
Summary of larger updates:
- Added support for estimating weighted regressions
- Added and improved documentation for new datasets:
yogurt,cars_china,cars_us - Exported the
dummyCode()function for automatically creating dummy-coded variables in a data frame. - Added support for auto dummy-coding categorical variables prior to model estimation
- Major overhaul of documentation using {pkgdown}
logitr 0.0.3
New simulation functionality
Summary of larger updates:
- Added support for simulating shares for a set of alternatives given an estimated model:
simulateShares(). This is similar to thepredict()function in mlogit. - Removed support for using an estimated preference space model as an input in the
options()function. I found this just far too confusing, and instead encourage users to supply a WTP space model with the computed WTP from a preference space model as starting parameters.
logitr 0.0.2
Updates to options and a few small bug fixes
Summary of larger updates:
- I got rid of the
logitr.summary()function and instead added thelogitrclass to all the models and renamed the summary function tosummary.logitr(). Now you can just use the standardsummary()function to summarize model results. - I finally fixed the analytic gradient for WTP space MXL models. I tested analytic versus numeric for WTP space and Preference Space MXL models and they are all identical, including variations of using normally and log-normally distributed parameters.
- Added startParBounds as an argument in options.
Smaller updates:
- Changed the summary() function to print more digits in the summary table.
- Rounded printing of the elapsed time in the summary table.
- Forced the sigma values in MXL models to be positive using abs(). Negative values for sigma parameters should not be an issue because the standard normal is symmetric.
- Changed the summary of random parameters to show “summary of 10k draws”
- Updated hessian to always use numeric approx for SE calculation since it’s faster.
- Made scaleInputs default to
TRUE.
logitr 0.0.1
Full reboot of logitr!
Long overdue, I decided to give the logitr program a full overhaul. This is the first version that is compiled as a proper R package that can be directly installed from GitHub. This version is much more robust and flexible than the prior, clunky collection of R files that I had previously been using to estimate logit models.
