NGBoost: gradient boosting that returns a distribution instead of a point
Natural Gradient Boosting for Probabilistic Prediction
At a glance
- What is it?
- NGBoost swaps the usual point prediction for a full conditional distribution by boosting in natural-gradient space. It is a scikit-learn-shaped library for regression and classification where the uncertainty matters as much as the prediction.
- Who is it for?
- Adopt NGBoost if you need a conditional distribution over the target and you already work inside scikit-learn, since NGBRegressor and NGBClassifier expose fit, predict and pred_dist in the familiar shape. Do not adopt it if a point estimate is all you report, or if you need a probability calibration story the library does not document.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 14 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The prediction a point estimate throws away
Most gradient boosting libraries answer one question: what is the expected value of the target given these features. NGBoost answers a different one. The README describes it as a Python library implementing Natural Gradient Boosting for probabilistic prediction, and the example shows the difference directly. After fitting, you call ngb.predict(X_test) to get point predictions and ngb.pred_dist(X_test) to get a distribution object. The README then scores both: mean_squared_error against the point predictions, and -Y_dists.logpdf(Y_test).mean() as a negative log likelihood. That second call is the reason the library exists. A downstream consumer that needs to know how confident the model is, not just what it thinks, has something to consume.
The intended audience is narrower than the install count suggests. It is for people doing regression or classification where the spread of the prediction carries information: a forecast where the interval matters, a model whose output feeds a decision rule that penalises confident errors. If your report is a single number per row, the extra machinery buys you nothing.
Boosting the parameters of a distribution, not the mean
The mechanism follows from the paper the README cites, Duan et al. 2019. Instead of boosting a scalar output, the model boosts the parameters of a conditional distribution. Each base learner contributes an update, and those updates are combined in natural-gradient space rather than ordinary gradient space. The README frames the design as scalable and modular with respect to three things: the choice of proper scoring rule, the distribution, and the base learner. Those three axes are the architecture. A scoring rule defines what the model is optimising. A distribution defines the shape of the output. A base learner defines the weak learner being stacked.
The practical consequence is that the output object is not a number. pred_dist returns something you call logpdf on, which means the library has to carry a distribution family through training and expose it at inference. That is a heavier contract than returning an array, and it is why the user guide the README points to spends its length on available distributions and scoring rules rather than on tuning knobs. The modularity is real, but it moves the burden onto you: the library gives you a slot for the distribution, and you have to fill it with something defensible for your problem.
Install and the two-call API
Installation is conventional. The README gives two routes: pip install --upgrade ngboost, or conda install -c conda-forge ngboost. There is no separate build step documented and no compiled extension mentioned in the installation section.
The usage example is short enough to reproduce the shape of it. You import NGBRegressor from ngboost, load a dataset, split it, and call NGBRegressor().fit(X_train, Y_train). From the fitted object you take Y_preds = ngb.predict(X_test) and Y_dists = ngb.pred_dist(X_test). The README scores the result two ways, with mean_squared_error on the point predictions and with the mean negative log likelihood on the distribution. The classification counterpart, NGBClassifier, is referenced in the README's pointer to the user guide rather than shown inline, so anyone needing classification should read the guide before assuming the regressor example transfers unchanged.
What the README does not show is the constructor surface. Distribution, scoring rule and base learner are described as modular, which implies constructor arguments or subclassing, but the inline example uses NGBRegressor() with no arguments at all. Anyone evaluating this library should treat the defaults as a starting point and go to the user guide for the configuration surface.
Where the defaults stop being enough
The README example uses NGBRegressor() bare. That tells you a default distribution and a default scoring rule exist, but not which ones, and not how they were chosen. This is the first thing to verify against your own data, because a distribution that is wrong for your target will produce a negative log likelihood that looks fine in aggregate and misleads per-row. Counts, strictly positive quantities and bounded targets do not share a distribution family, and the library's modularity means it will happily fit one that does not match.
The second limitation is structural. Probabilistic output is only as good as the uncertainty it expresses, and nothing in the README describes a calibration check, a coverage diagnostic, or a reliability plot. You get logpdf and you get point predictions. Whether the intervals mean what they claim is left to you. A model that returns a distribution is not automatically a model whose distribution is correct, and the README offers no tooling to tell the difference.
The third is documentation depth. The README is a pointer, not a manual. It sends you to an external user guide for distributions, scoring rules, learners, tuning and interpretation. If you cannot read that guide, you cannot configure this library beyond the default path.
Against LightGBM and quantile regression
The obvious comparison is a standard gradient boosting library. LightGBM and XGBoost predict a point, and if you want uncertainty you either fit quantile objectives at several quantiles or wrap the model in conformal prediction. That approach is well trodden and the tooling around it is mature. The difference in method is what gets boosted: quantile boosting fits a separate model per quantile and gives you a set of curves that need not be consistent with any single distribution, while NGBoost fits one model over distribution parameters and derives every quantile from that one object. The NGBoost output is internally coherent by construction. The quantile approach makes fewer assumptions about the shape of the conditional distribution.
The second alternative is a Bayesian treatment, a Gaussian process or a Bayesian neural network. Those give you a posterior over parameters and a principled way to separate epistemic from aleatoric uncertainty. NGBoost does not claim that separation in the README, and its output is a single conditional distribution. If the question is how much of the uncertainty would shrink with more data, NGBoost is the wrong instrument. If the question is what distribution the target follows given these features, it is the right one, and it scales to tabular data in a way Gaussian processes generally do not.
Release cadence, licence and the upgrade bill
The repository is active and not archived. Recent releases show a steady cadence: v0.5.9 in February 2026 labelled Sympy Factory and Python 3.14, v0.5.10 in March 2026 labelled Backwards Compatability, and v0.5.11 in June 2026 labelled Bug Fixes in APIs. Two of those three release titles concern compatibility or API surface rather than new modelling capability. That is a reasonable signal for a library at this stage, and it is also a warning: if your code depends on internal behaviour rather than the documented fit, predict and pred_dist calls, minor releases have been touching APIs.
The Python 3.14 note in v0.5.9 and the Sympy reference in the same release suggest the dependency footprint includes SymPy, which matters if you are pinning a minimal environment. The README does not list dependencies, so check the package metadata before assuming a light install. Version pinning is the cheap insurance here: a constraint on ngboost in your requirements file costs nothing and protects you from an API-touching minor release.
Licensing is Apache-2.0, stated in the README and in the repository badge. That is a permissive licence with an explicit patent grant, which is generally the friendlier option for commercial use than a copyleft licence. It is not legal advice and the terms should be read in full, particularly the patent termination clause, before it goes into a product.
Who this fits
NGBoost occupies a specific slot: tabular data, scikit-learn conventions, and a requirement that the model express uncertainty as a distribution rather than as a set of separately fitted quantiles. The API is small enough to learn in an afternoon, and the modular design means the distribution choice is a configuration decision rather than a rewrite.
It does not fit every probabilistic problem. If you need a posterior over parameters, look elsewhere. If you need calibration guarantees, the library does not advertise them. If your team already runs LightGBM in production and only occasionally needs intervals, adding a second boosting stack for that occasional need is hard to justify. The honest test is whether pred_dist is something your downstream code actually consumes. If it is, the library earns its place. If it is not, you are paying the complexity cost of a distribution you never read.
Editorial conclusion
Adopt NGBoost if you need a conditional distribution over the target and you already work inside scikit-learn, since NGBRegressor and NGBClassifier expose fit, predict and pred_dist in the familiar shape. Do not adopt it if a point estimate is all you report, or if you need a probability calibration story the library does not document. Before committing, run the README example against your own data and check the negative log likelihood your chosen distribution produces, because the distribution choice is the part the library cannot make for you.
Community notes