forelint
Lint your forecast backtests before you trust a score.
forelint checks the things a backtest score hides: leakage between related series, the run-to-run noise floor, whether model A is really better than model B, and which items carry the bias and the error. It works on the long-format tables that statsforecast, mlforecast and most forecasting code already produce, and on any scikit-learn estimator.
pip install forelint
What it checks
| Question | Function |
|---|---|
| Does my validation leak through related stores, products or regions? | split_optimism, GroupTimeSplit |
| Is this improvement bigger than seed-to-seed noise? | noise_floor |
| Is model A really better than B across many series? | dm_test, diebold_mariano, model_confidence_set |
| Which items are always over or under forecast? Does the model beat a naive forecast? Where does the error live? | audit |
Quickstart
import forelint as fl
# df: one row per item and date, the actual in "y", one column per model,
# e.g. the output of statsforecast's cross_validation()
report = fl.audit(df, models=["LightGBM", "ETS"], baseline="SeasonalNaive")
print(report)
# Is LightGBM really better than the seasonal naive, or is it noise?
print(fl.dm_test(df, "LightGBM", "SeasonalNaive"))
# How much does random K-fold flatter the model, compared with holding out
# the future of entities the model never saw?
fl.split_optimism(model, X, y, groups=store_ids, time=dates)
# What difference between two runs is just noise?
nf = fl.noise_floor(lambda seed: train_and_score(seed), seeds=range(10))
nf.is_meaningful(new_mae - old_mae)
On real data: one Walmart store in M5
benchmarks/m5_benchmark.py runs every check on the public M5 data: store
CA_1, department FOODS_3, 823 items, the last 365 days, a direct 28-day-ahead
gradient-boosting model from scikit-learn, scored on the final 28 days.
Measured, not assumed:
- The model added nothing over a 28-day moving average. Forecast value added was −0.1% on MAE, the model was worse than the moving average on 49% of items, and Diebold-Mariano gives p = 0.31. The model confidence set keeps both. An average-MAE table alone would not show this.
- It under-forecasts by 9.3% of actual sales.
- 10% of items hold 73% of the squared error.
- The noise floor is small here: over 10 seeds the MAE sd is 0.0014, so any change under 0.0045 is noise.
- Splitting barely mattered for this data: random K-fold was 1% optimistic against a time split. Leakage depends on the features; forelint measures it rather than assuming it.
The model is deliberately plain (six features, no tuning). The point is the audit, not the model.
Why
In an international machine-learning competition on well-geology prediction, validation ranked five builds against the hidden leaderboard with a correlation of −0.745: the build it liked most scored worst, and identical code scored 6.241, 6.259 and 6.368 on three runs. Both failures were measurable before the deadline with the right checks. forelint is those checks, packaged.
Background: My validation ranked five models backwards.
Conventions
- Error is forecast − actual. Positive bias means over-forecasting.
- Tracking signal is the sum of errors divided by the mean absolute error; the default alarm level is ±4.
dm_testaverages the loss difference across series at each time stamp, then applies Diebold-Mariano with the Harvey-Leybourne-Newbold correction.model_confidence_setfollows Hansen, Lunde and Nason (2011) with the T_max statistic and a moving-block bootstrap. Its kept set matchesarch.bootstrap.MCSin the test suite.
Status
Alpha. The API may change before 1.0. Issues and pull requests are welcome.
Author
David Mashiah. MIT licensed.
Metadata
Release files for forelint 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| forelint-0.1.0.tar.gz | 14.4 kB | Without provenance | Details for forelint-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| forelint-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for forelint-0.1.0-py3-none-any.whl |
Total release size: 28.2 kB
Release files / forelint-0.1.0.tar.gz
| Download URL | forelint-0.1.0.tar.gz |
|---|---|
| Size | 14.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e43134ef1753cdd90d23069f163f5fb7014e908fc217a2e7f654ace5196c5403
|
|
BLAKE2b-256 checksum How to use checksums |
d67af45afad0cf698e2d5962d9a8682559f1fee9327e2598313e1c7d00f659fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / forelint-0.1.0-py3-none-any.whl
| Download URL | forelint-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e1ecde901f9985f66452d3189ca0519f109c0e99971d2d65f851137f055bf253
|
|
BLAKE2b-256 checksum How to use checksums |
ab8fbef2cb8e1bbf3cfd11ba7ea74bfd114f1c38b7cf2bcc1f0b88b2cee963df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Security for forelint 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.