Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Quantile regression predicts a selected point in the conditional distribution of a target—not just its conditional mean. In Python, use statsmodels.QuantReg for interpretable linear coefficients, scikit-learn’s QuantileRegressor for a regularized linear pipeline, and quantile-loss boosting for nonlinear predictions. You can fit lower and upper quantiles to form a nominal prediction interval, but you must check its coverage on held-out data: fitting the models does not guarantee that the interval will contain the advertised share of future outcomes.
What quantile regression predicts
Ordinary least squares (OLS) models the conditional mean, E[Y | X=x]. Quantile regression models a chosen conditional quantile, QY(τ | X=x), where 0 < τ < 1. The 90th percentile is quantile 0.90; quantiles are usually written from 0 to 1 and percentiles from 0 to 100. See the scikit-learn overview of linear models.
τ = 0.50: conditional median.τ = 0.05: conditional 5th percentile, a lower-tail estimate.τ = 0.95: conditional 95th percentile, an upper-tail estimate.
For example, a delivery-time model might estimate a conditional median of 30 minutes, a 10th percentile of 20 minutes, and a 90th percentile of 48 minutes for orders with the same modeled characteristics. The range can reflect changing spread across feature values, but it is not a guaranteed range for every order.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Quantile regression is useful when outcomes are skewed, have changing variability (heteroskedasticity), or when a decision depends on a tail or threshold rather than the average. Applications include demand, energy load, traffic, response times, salaries, house prices, and insurance claims. It is not automatically preferable to mean regression: if the decision is specifically about expected revenue, expected cost, or a mean effect, the conditional mean may be the right target.
#1 Best Overall
Pinball loss: the objective behind a quantile
For target quantile τ, quantile regression minimizes pinball loss (also called quantile or tilted absolute loss). With residual u = y − ŷ, one common form is:
ρτ(u) = τ max(u, 0) + (1 − τ) max(−u, 0)
Under-predictions and over-predictions receive different weights. At τ = 0.90, predicting too low is penalized more heavily than predicting too high; at τ = 0.10, the reverse is true. At τ = 0.50, the loss is proportional to absolute error, whose optimum is the conditional median. The scikit-learn model-evaluation guide documents pinball loss and its use for quantile predictions.
| Target quantile | Error given greater penalty |
|---|---|
| 0.10 | Prediction is too high |
| 0.50 | Under- and over-prediction are weighted equally |
| 0.90 | Prediction is too low |
Pinball loss grows linearly with the size of a residual, unlike squared error, which grows quadratically. That makes quantile regression less sensitive to extreme residual magnitudes than least squares in that specific sense. It does not make a model immune to bad data, high-leverage observations, misspecification, or sparse tails.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallChoose the Python implementation
| Need | Good starting point | Key API |
|---|---|---|
| Linear coefficients, summaries, and econometric interpretation | statsmodels |
QuantReg(y, X).fit(q=...) |
| Regularized linear model inside an ML pipeline | scikit-learn | QuantileRegressor(quantile=...) |
| Nonlinear tabular prediction and quantile bands | scikit-learn boosting | GradientBoostingRegressor(loss="quantile") or histogram boosting |
| Existing boosted-tree workflow at scale | XGBoost | reg:quantileerror; check installed-version API |
scikit-learn’s stable documentation is version 1.9.0 (retrieved August 18, 2026); the cited stable statsmodels documentation is 0.14.6. APIs and installed package versions may differ, so consult the documentation for the version in your environment rather than assuming development documentation describes a stable release.
Linear quantile regression with statsmodels
statsmodels.regression.quantile_regression.QuantReg is a natural choice when a linear specification and coefficient summaries matter. Its fitting method accepts the target quantile as q. With array or DataFrame inputs, add an intercept explicitly unless your design matrix already contains one. The estimator uses iterative reweighted least squares; inference and covariance choices are not the same as ordinary least squares. See the statsmodels QuantReg API.
python -m pip install numpy pandas statsmodels
import pandas as pd
import statsmodels.api as sm
# A small example dataset
df = pd.DataFrame({
"hours": [1, 2, 3, 4, 5, 6, 7, 8],
"score": [52, 55, 57, 63, 68, 70, 74, 80],
})
X = sm.add_constant(df[["hours"]])
y = df["score"]
model = sm.QuantReg(y, X)
median_result = model.fit(q=0.50)
print(median_result.summary())
print(median_result.params)
To compare coefficient patterns across quantiles, fit separate models:
quantiles = [0.10, 0.50, 0.90]
results = {q: sm.QuantReg(y, X).fit(q=q) for q in quantiles}
predictions = pd.DataFrame({
f"q{int(q * 100)}": results[q].predict(X)
for q in quantiles
})
print(predictions)
A formula interface is also available:
import statsmodels.formula.api as smf
result = smf.quantreg("score ~ hours", data=df).fit(q=0.50)
print(result.summary())
Interpret a coefficient as a shift in the modeled conditional quantile under the fitted specification. For instance, a coefficient of 3.2 on hours in a 90th-quantile model means that, holding included predictors constant, one additional hour is associated with a 3.2-unit increase in the modeled conditional 90th percentile. It does not say that 90% of individuals increase by 3.2 units, nor does it establish a causal effect. Tail coefficients can differ substantially from median coefficients. Very extreme quantiles need far more supporting data than the median; inference also depends on covariance and bandwidth choices.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Regularized linear quantiles with scikit-learn
QuantileRegressor minimizes pinball loss with an L1 penalty, making it useful as a regularized linear baseline in scikit-learn pipelines. Its quantile argument is named quantile, and must be strictly between 0 and 1. The separate alpha argument controls regularization; it does not select the quantile. The documented default solver is "highs", which uses SciPy’s linear-programming machinery. See the linear-model guide and QuantileRegressor API.
python -m pip install numpy pandas scipy scikit-learn
from sklearn.linear_model import QuantileRegressor
median_model = QuantileRegressor(
quantile=0.50,
alpha=0.01,
solver="highs",
)
median_model.fit(X_train, y_train)
median_prediction = median_model.predict(X_test)
For mixed numeric and categorical inputs, place preprocessing and estimation in a pipeline so transformations are learned only from the training data:
from sklearn.compose import make_column_transformer
from sklearn.linear_model import QuantileRegressor
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
numeric_features = ["age", "income"]
categorical_features = ["region"]
preprocessor = make_column_transformer(
(StandardScaler(), numeric_features),
(OneHotEncoder(handle_unknown="ignore"), categorical_features),
)
model = make_pipeline(
preprocessor,
QuantileRegressor(quantile=0.50, alpha=0.01, solver="highs"),
)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
The model remains linear in the transformed features. L1 regularization can help with expanded feature sets, but very large one-hot matrices may make solver performance a consideration. Fit separate estimators for separate quantiles; independently estimated models can cross. Tune and evaluate with pinball loss for the quantile you intend to use, not only the estimator’s default score.
Rank #3
Nonlinear quantile regression with gradient boosting
Boosted trees can model nonlinear effects and interactions without manually specifying them as in a linear model. GradientBoostingRegressor uses loss="quantile" and the parameter alpha to select the quantile. The HistGradientBoostingRegressor variant uses loss="quantile" with the parameter quantile instead. Do not confuse either API with QuantileRegressor, where alpha is the regularization strength. scikit-learn describes histogram boosting as a faster variant for intermediate and large datasets; whether it is faster for a particular workload depends on data, hardware, and configuration. See the GradientBoostingRegressor API and official quantile interval example.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsfrom sklearn.ensemble import GradientBoostingRegressor
common_params = {
"learning_rate": 0.05,
"n_estimators": 200,
"max_depth": 2,
"min_samples_leaf": 9,
"min_samples_split": 9,
"random_state": 42,
}
models = {
q: GradientBoostingRegressor(
loss="quantile",
alpha=q,
**common_params,
).fit(X_train, y_train)
for q in [0.05, 0.50, 0.95]
}
predictions = {q: model.predict(X_test) for q, model in models.items()}
lower = predictions[0.05]
median = predictions[0.50]
upper = predictions[0.95]
For histogram boosting, the corresponding parameter is named quantile:
from sklearn.ensemble import HistGradientBoostingRegressor
models = {
q: HistGradientBoostingRegressor(
loss="quantile",
quantile=q,
max_iter=300,
learning_rate=0.05,
max_leaf_nodes=31,
random_state=42,
).fit(X_train, y_train)
for q in [0.05, 0.50, 0.95]
}
Separate quantiles can need different hyperparameters: a configuration that works for the median may not work well for a tail. Tune models against quantile-specific validation loss and inspect their calibration rather than assuming one setting is optimal for all three.
Building and evaluating an interval
Predictions from the 5th- and 95th-quantile models define a nominal 90% conditional quantile interval when the lower prediction is below the upper prediction. The word “nominal” matters: the quantile targets describe what the models are trained to estimate, not a coverage guarantee for new observations.
For each quantile, evaluate pinball loss using that same quantile value:
Rank #4
import numpy as np
from sklearn.metrics import mean_pinball_loss
for q in [0.05, 0.50, 0.95]:
loss = mean_pinball_loss(
y_test,
predictions[q],
alpha=q,
)
print(f"q={q:.2f}: {loss:.4f}")
For a nominal central 90% interval, measure empirical coverage and width on held-out data:
coverage = np.mean((y_test >= lower) & (y_test <= upper))
mean_width = np.mean(upper - lower)
median_width = np.median(upper - lower)
print(f"Empirical coverage: {coverage:.1%}")
print(f"Mean width: {mean_width:.3f}")
print(f"Median width: {median_width:.3f}")
Coverage should be near the nominal target over an appropriate evaluation population, subject to finite-sample variation; it need not equal 90% exactly. Interpret it together with width: an extremely wide interval may cover many outcomes but be unhelpful, while a narrow one can under-cover. R² and RMSE may be useful for other goals, but neither directly evaluates the quality of a particular quantile estimate.
Overall coverage can hide failures. Check it across important categories, time periods, geographies, volume bands, or bins of predicted median and risk features. Also check quantile calibration: on held-out data, approximately a fraction q of outcomes should fall below predictions from a q-quantile model. Sampling variation, misspecification, and distribution changes can make the observed fraction differ.
A confidence interval commonly describes uncertainty about an estimated parameter or mean function; a prediction interval concerns a future outcome. Quantile models estimate conditional quantiles and can be used to construct predictive ranges, but independent fitted quantiles do not automatically form a formally calibrated prediction interval. In scikit-learn’s demonstration, the displayed interval undercovers its nominal 90% target on the example test set. That result illustrates a possible failure, not a universal benchmark.
Free tools Windows power users keep installed
One-click scans. No signup required.
Detect and address quantile crossing
Conditional quantiles must be ordered, but independently fitted models can violate that order for some feature values. For example, a predicted 5th percentile can exceed the predicted 95th percentile, or a median can fall outside the lower and upper predictions.
Best Value
- Use scikit-learn to track an example ML project end to end
- Explore several models, including support vector machines, decision trees, random forests, and ensemble methods
- Exploit unsupervised learning techniques such as dimensionality reduction, clustering, and anomaly detection
- Dive into neural net architectures, including convolutional nets, recurrent nets, generative adversarial networks, autoencoders, diffusion models, and transformers
- Use TensorFlow and Keras to build and train neural nets for computer vision, natural language processing, generative models, and deep reinforcement learning
crossing_lower_median = np.mean(lower > median)
crossing_median_upper = np.mean(median > upper)
crossing_any = np.mean((lower > median) | (median > upper))
print(crossing_lower_median, crossing_median_upper, crossing_any)
One pragmatic display-time repair is to sort the predicted quantiles for each row:
ordered = np.sort(np.column_stack([lower, median, upper]), axis=1)
lower_fixed, median_fixed, upper_fixed = ordered.T
Sorting enforces order, but it does not retrain the models, preserve their original quantile identities, or guarantee calibration. Treat it as post-processing, then evaluate the repaired predictions. More principled options include jointly trained quantile models with non-crossing constraints, rearrangement methods, a suitable location-scale model, or conformal calibration.
XGBoost’s quantile-regression documentation describes the reg:quantileerror objective and QuantileDMatrix, notes that the feature was added in XGBoost 2.0.0, and warns that crossing can occur. Its example is version-sensitive; check the installed version and API before adapting it, and do not assume identical support across language bindings.
Conformalized quantile regression for calibration
When empirical coverage is too low, conformalized quantile regression (CQR) combines fitted lower and upper quantiles with a separate calibration set. In broad terms, train the quantile models on training data, score how calibration observations fall outside their predicted intervals, use an appropriate finite-sample quantile of those scores to choose an expansion, and apply it to future intervals. Reserve a final test set to assess the complete procedure. The method was introduced by Romano, Patterson, and Candès.
Under exchangeability, conformal methods can provide finite-sample marginal coverage without requiring a correctly specified outcome distribution. This is not a guarantee of coverage conditional on every feature value or subgroup. Temporal dependence, grouped observations, and distribution shift can violate the assumptions; calibration may consume data and widen intervals. Time-series and grouped settings need validation designs and methods that account for their structure. A hand-written calibration routine also needs careful finite-sample indexing and handling of ties and missing values.
Forecasting, validation, and data leakage
If observations are time ordered and deployment predicts the future, do not use a random train/test split. Use a chronological holdout or a suitable time-series cross-validation design, and construct lagged features without access to future values. The scikit-learn lagged-feature forecasting example illustrates quantile boosting in a forecasting context.
Leakage can make intervals seem far better calibrated than they will be in deployment. Watch for future information in lag features, aggregations computed across the full dataset, target-derived categories, or variables recorded only after the outcome. For repeated observations from the same customer, patient, device, or location, split and evaluate by group when that matches deployment; ordinary random splitting can leak group-specific information and invalidate simple independence assumptions. Recheck calibration over time when the data-generating process may drift.
Common modeling edge cases
- Extreme tails: A 99th-quantile model relies on relatively few tail observations. Its estimates can be unstable or dominated by a handful of cases. Choose a quantile that fits the decision and the available tail data.
- Unobserved uncertainty drivers: Quantile regression can reflect changing spread when features explain it, but it cannot discover uncertainty sources absent from the inputs. Missing drivers can make intervals too narrow.
- Nonnegative outcomes: An unconstrained model can predict a negative lower bound for demand, claims, or other nonnegative quantities. Consider a transformation, a distribution-aware model, or justified domain-aware post-processing; assess the effect on decision-relevant quantiles.
- Transformed targets: A log transform may help with positive skew, but transform predictions back consistently. Quantiles transform differently from means under nonlinear transformations, and naive inverse transformations can mislead.
- Censoring or truncation: If observations are capped, censored, or systematically absent beyond a threshold, ordinary quantile regression on recorded values may be inappropriate. Consider methods designed for censored outcomes or survival analysis.
Which model should you use?
| Choose | When it fits | Trade-off to remember |
|---|---|---|
statsmodels.QuantReg |
Linear coefficients, summaries, and inference matter; a linear conditional-quantile specification is plausible. | Inference depends on covariance choices; it is not a high-capacity nonlinear predictor. |
sklearn.QuantileRegressor |
You need a regularized linear baseline, sparse or encoded features, and pipeline or cross-validation integration. | Solver performance can matter for very large expanded designs; separate quantiles can cross. |
| scikit-learn gradient boosting | Tabular relationships are nonlinear or interactions matter and prediction is the priority. | Fit and tune quantiles separately unless using a joint method; validate tails and crossing. |
| XGBoost quantile objective | Your workflow already uses XGBoost or benefits from its optimized boosted-tree ecosystem. | Confirm version-specific arguments and check crossing and calibration. |
The right choice follows the decision: select a quantile that represents the operational target, a model class that matches the relationship, and a validation and calibration strategy that resembles deployment.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

