Fitting Quantile Regression Models
QuantReg.jl currently contains three methods for fitting quantile regression models: (1) the Barrodale-Roberts simple algorithm, (2) the Frisch-Newton algorithm, and (3) via the industrial solver Gurobi. The first two methods leverage FORTRAN code originally written for the R quantreg package. The third method was developed specifically for this package and only works if Gurobi is already installed on the user's machine.
Generic functions
A QuantRegModel
object, named model
, can be fit using the generic fit!()
function, and indeed, this is the function that most end users will leverage. This functions fits the object in place, modifying the QuantRegFit
object stored at model.fit
. For example,
julia> model = QuantRegModel(@formula(Y ~ X1 + X2 + X3), df; τ=0.80, fitmethod="fn")
creates an unfitted a quantile regression model at the 0.80th quantile and specifies for it to be fit via the Frisch-Newton. Then,
julia> fit!(model)
fits the model in-place via the specified method.
Additionaly, there is a fit()
method that creates a deep copy of the passed model, fits that copy, and returns the new, fitted model.
StatsBase.fit!
— Methodfit!(model::QuantRegModel)
Fit model
in-place according to model.fitmethod
.
QuantReg.fit
— Functionfit(model::QuantRegModel)
Deep copy model
and fit according to model.fitmethod
.
Ultimately, these two functions simply serve as a one-stop wrapper for fitting a model and calling different subroutines depending on the value of model.fitmethod
.
Choosing a fitting method
Choosing the best fit method for a quantile regression model largely depends upon the size of the dataset that you are attempting to fit.
- For very small datasets (both in number of observations and number of predictors) the Barrodale-Roberts simplex tended to outperform other fitting methods in limited simulations. The speed difference between the Barrodale-Roberts simplex algorithm and the Frisch-Newton algorithm, however, was negligible (both returned a model well within one second), so either method seems like a good choice. Using Gurobi, however, imposes a signficant speed penalty, mainly due to the fixed cost of initializing a Gurobi environment. While the method still produces results relatively quickly (sub-two seconds), this is substantially slower than the other algorithms.
- As datasets grow in size, the Frisch-Newton algorithm and Gurobi catch-up to and substantially overtake the Barrodale-Roberts simplex algorithm in speed. With the exception of extremely large datasets, the Frisch-Newton algorithm still tends to outperform the Gurobi algorithm due to the latter's fixed start-up costs. The speed of the two methods is relatively similar in scale, however.
Going forward in development, the goal for the Gurobi solving method should be to produce a reusable Gurobi environment upon load to eliminate the fixed start-up costs.
Barrodale-Roberts Simplex Method
The Barrodale-Roberts simplex algorithm implemented can be used for both fitting a model and for computing inference via a rank test inversion. When fitting, the following method is called with the keyword argument, ci
, set to its default value of false.
To select this method when specifying a quantile regression model, set the keyword argument fitmethod="br"
in either the rq
function or the QuantRegModel
constructor.
QuantReg.fitbr!
— Functionfitbr!(model::QuantRegModel; ci::Bool=false),
Fit model
using the Barrodale-Roberts method.
If ci is false, model.fit
is updated in place to reflect the fit produced by running the Barrodale-Roberts simplex and confidence intervals are not computed. Otherwise, confidence intervals are computed, and model.inf
is updated in place to reflect the confidence invervals produced by this method but model.fit
is not updated.
This fitting method leverages public domain FORTRAN code written by Roger Koenker for the R quantreg
package.
This method relies on a subroutine, fitbrfortran
, that handles the FORTRAN call.
QuantReg.fitbrfortran
— Functionfitbrfortran(n::Integer, k::Integer, X::Matrix{Number}, y::Vector{Number},
τ::Number, nsol::Integer, ndsol::Integer, qn::Vector{Number},
cutoff::Number, lci1::Bool)
Wraps call to the public domain Barrodale-Roberts simplex FORTRAN routine.
Arguments
n
: number of observationsk
: number of parametersX
: x matrixy
: y vectorτ
: the desired quantilensol
: an estimated (row) dimension of the primal solution arrayndsol1
: an estimated (row) dimension of the dual solution arrayqn
: residuals variances from the projection of each column of X on remaining columnscutoff
: the critical point for testinglci1
: whether to calculate CI
Frisch-Newton Algorithm
The Frisch-Newton algorithm implemented is an interior point method that can be used to solve quantile regression problems. Unlike the other two methods in this package, this method does not produce solutions to the dual problem.
To select this method when specifying a quantile regression model, set the keyword argument fitmethod="fn"
in either the rq
function or the QuantRegModel
constructor.
QuantReg.fitfn!
— Functionfitfn!(model::QuantRegModel)
Fit model
using the Frish-Newton algorithm.
Fitting with this method does not produce solutions to the dual problem.
This fitting method leverages public domain FORTRAN code written by Roger Koenker for the R quantreg
package. In the quantreg
package, this is equivalent to the fn
and fnb
methods.
Gurobi
The only fitting method available via this package that is not available via the R quantreg package is fitting via Gurobi. This fitting method is only available to users who already have a licensed version of Gurobi installed on their machine and the Gurobi.jl package added in Julia. Even if an active Gurobi license is installed on the user's machine, the GUROBI_HOME
environmental variable must be properly set for the Gurobi fitting method to be available.
To select this method when specifying a quantile regression model, set the keyword argument fitmethod="gurobi"
in either the rq
function or the QuantRegModel
constructor.
QuantReg.fitgurobi!
— Functionfitgurobi(model::QuantRegModel)
Fit model
using Gurobi via Julia's JuMP library.
This algorithm has been tailored specifically to work with Julia (hence the use of direct) mode. Some time was spent researching the use of open-source solvers such as GLPK, but they proved to be too slow. Extending this method to work with other solvers, such as CPLEX could be accomplished by switching the optimizer and creating the model in automatic mode, but this may leave some small efficiency gains on the table.