Skip to content

Commit 77def86

Browse files
docs: enhance conformal prediction tutorial for SEO (#1053)
1 parent 748f71e commit 77def86

File tree

1 file changed

+109
-35
lines changed

1 file changed

+109
-35
lines changed

nbs/docs/tutorials/ConformalPrediction.ipynb

Lines changed: 109 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,61 +28,96 @@
2828
"source": [
2929
"# Conformal Prediction\n",
3030
"\n",
31-
"> In this example, we'll implement conformal prediction"
31+
"> Learn how to generate calibrated prediction intervals for any forecasting model using conformal prediction, a distribution-free method for uncertainty quantification in Python."
3232
]
3333
},
3434
{
3535
"cell_type": "markdown",
3636
"metadata": {},
3737
"source": [
38-
"::: {.callout-warning collapse=\"true\"}\n",
38+
"## What You'll Learn\n",
3939
"\n",
40-
"## Prerequisites\n",
40+
"In this tutorial, you'll discover how to:\n",
41+
"\n",
42+
"- Generate **calibrated prediction intervals** without distributional assumptions\n",
43+
"- Apply conformal prediction to any forecasting model in Python\n",
44+
"- Implement uncertainty quantification with StatsForecast's `ConformalIntervals`\n",
45+
"- Compare conformal prediction with traditional uncertainty methods\n",
46+
"- Evaluate prediction interval coverage and calibration\n",
4147
"\n",
42-
"This tutorial assumes basic familiarity with StatsForecast. For a minimal example visit the [Quick Start](../getting-started/1_Getting_Started_short)\n",
48+
"## Prerequisites\n",
4349
"\n",
44-
":::"
50+
"This tutorial assumes basic familiarity with StatsForecast. For a minimal example visit the [Quick Start](../getting-started/1_Getting_Started_short)"
4551
]
4652
},
4753
{
4854
"cell_type": "markdown",
4955
"metadata": {},
5056
"source": [
51-
"## Introduction \n",
57+
"## What is Conformal Prediction?\n",
58+
"\n",
59+
"**Conformal prediction** is a distribution-free framework for generating prediction intervals with guaranteed coverage properties. Unlike traditional methods that assume normally distributed errors, conformal prediction works with any forecasting model and provides **well-calibrated uncertainty estimates** without making distributional assumptions.\n",
60+
"\n",
61+
"### Why Use Conformal Prediction for Time Series?\n",
62+
"\n",
63+
"When generating forecasts, a point forecast alone doesn't convey uncertainty. **Prediction intervals** quantify this uncertainty by providing a range of values where future observations are likely to fall. A properly calibrated 95% prediction interval should contain the actual value 95% of the time.\n",
64+
"\n",
65+
"The challenge: many forecasting models either don't provide prediction intervals, or generate intervals that are poorly calibrated. Traditional statistical methods also assume normality, which often doesn't hold in practice.\n",
5266
"\n",
53-
"When we generate a forecast, we usually produce a single value known as the point forecast. This value, however, doesn't tell us anything about the uncertainty associated with the forecast. To have a measure of this uncertainty, we need **prediction intervals**. \n",
67+
"**Conformal prediction solves this by:**\n",
5468
"\n",
55-
"A prediction interval is a range of values that the forecast can take with a given probability. Hence, a 95% prediction interval should contain a range of values that include the actual future value with probability 95%. Probabilistic forecasting aims to generate the full forecast distribution. Point forecasting, on the other hand, usually returns the mean or the median or said distribution. However, in real-world scenarios, it is better to forecast not only the most probable future outcome, but many alternative outcomes as well. \n",
69+
"- Working with any forecasting model (model-agnostic)\n",
70+
"- Requiring no distributional assumptions\n",
71+
"- Using cross-validation to generate calibrated intervals\n",
72+
"- Providing theoretical coverage guarantees\n",
73+
"- Treating the forecasting model as a black box\n",
5674
"\n",
57-
"The problem is that some timeseries models provide forecast distributions, but some other ones only provide point forecasts. How can we then estimate the uncertainty of predictions? "
75+
"### Conformal Prediction vs. Traditional Methods\n",
76+
"\n",
77+
"| Method | Distributional Assumption | Model-Agnostic | Calibration Guarantee |\n",
78+
"|--------|---------------------------|----------------|----------------------|\n",
79+
"| **Conformal Prediction** | None | ✓ | ✓ |\n",
80+
"| Bootstrap | Parametric assumptions | ✓ | ~ |\n",
81+
"| Quantile Regression | None | ✓ | ~ |\n",
82+
"| Statistical Models (ARIMA, ETS) | Normal errors | ✗ | ~ |\n",
83+
"\n",
84+
"<Note>For a video introduction, see the [PyData Seattle presentation](https://www.youtube.com/watch?v=Bj1U-Rrxk48). More resources available in [Valery Manokhin's curated list](https://github.com/valeman/awesome-conformal-prediction).</Note>"
5885
]
5986
},
6087
{
6188
"cell_type": "markdown",
6289
"metadata": {},
6390
"source": [
64-
"::: {.callout-important}\n",
65-
"## Prediction Intervals\n",
66-
"For models that already provide the forecast distribution, check [Prediction Intervals](./UncertaintyIntervals).\n",
91+
"## Models with Native Prediction Intervals\n",
6792
"\n",
68-
":::"
93+
"For models that already provide forecast distributions (like AutoARIMA, AutoETS), check [Prediction Intervals](./UncertaintyIntervals). Conformal prediction is particularly useful for models that only produce point forecasts, or when you want distribution-free intervals."
6994
]
7095
},
7196
{
7297
"cell_type": "markdown",
7398
"metadata": {},
7499
"source": [
75-
"### Conformal Prediction\n",
100+
"## How Conformal Prediction Works\n",
101+
"\n",
102+
"Conformal prediction uses **cross-validation** to generate prediction intervals:\n",
76103
"\n",
77-
"For a video introduction, see the [PyData Seattle presentation](https://www.youtube.com/watch?v=Bj1U-Rrxk48).\n",
104+
"1. **Split the training data** into multiple windows\n",
105+
"2. **Train the model** on each window and forecast the next period\n",
106+
"3. **Calculate residuals** (prediction errors) on the held-out data\n",
107+
"4. **Construct intervals** using the distribution of these residuals\n",
78108
"\n",
79-
"Multi-quantile losses and statistical models can provide provide prediction intervals, but the problem is that these are uncalibrated, meaning that the actual frequency of observations falling within the interval does not align with the confidence level associated with it. For example, a calibrated 95% prediction interval should contain the true value 95% of the time in repeated sampling. An uncalibrated 95% prediction interval, on the other hand, might contain the true value only 80% of the time, or perhaps 99% of the time. In the first case, the interval is too narrow and underestimates the uncertainty, while in the second case, it is too wide and overestimates the uncertainty. \n",
109+
"The key insight: by studying how the model performs on historical data through cross-validation, we can quantify uncertainty for future predictions without assuming any particular error distribution.\n",
80110
"\n",
81-
"Statistical methods also assume normality. Here, we talk about another method called conformal prediction that doesn't require any distributional assumptions. More information on the approach can be found in [this repo owned by Valery Manokhin](https://github.com/valeman/awesome-conformal-prediction).\n",
111+
"### Real-World Applications\n",
82112
"\n",
83-
"Conformal prediction intervals use cross-validation on a point forecaster model to generate the intervals. This means that no prior probabilities are needed, and the output is well-calibrated. No additional training is needed, and the model is treated as a black box. The approach is compatible with any model.\n",
113+
"Conformal prediction is particularly valuable for:\n",
84114
"\n",
85-
"[Statsforecast](../../index) now supports Conformal Prediction on all available models."
115+
"- **Demand forecasting**: Inventory planning with quantified uncertainty\n",
116+
"- **Energy prediction**: Load forecasting with reliable confidence bounds\n",
117+
"- **Financial forecasting**: Risk management with calibrated intervals\n",
118+
"- **Production models**: Any black-box forecasting model requiring uncertainty quantification\n",
119+
"\n",
120+
"[StatsForecast](../../index) implements conformal prediction for all available models, making it easy to add calibrated prediction intervals to any forecasting pipeline."
86121
]
87122
},
88123
{
@@ -282,15 +317,26 @@
282317
"cell_type": "markdown",
283318
"metadata": {},
284319
"source": [
285-
"## Train models\n",
320+
"## Implementing Conformal Prediction in Python\n",
321+
"\n",
322+
"StatsForecast makes it simple to add conformal prediction to any forecasting model. We'll demonstrate with models that don't natively provide prediction intervals:\n",
323+
"\n",
324+
"- **[SeasonalExponentialSmoothing](../models/SimpleExponentialSmoothing)**: A simple smoothing model\n",
325+
"- **[ADIDA](../models/ADIDA)**: Aggregation method for intermittent demand\n",
326+
"- **[ARIMA](../models/ARIMA)**: Traditional statistical model (to show distribution-free intervals)\n",
286327
"\n",
287-
"StatsForecast can train multiple [models](../../models/) on different time series efficiently. Most of these models can generate a probabilistic forecast, which means that they can produce both point forecasts and prediction intervals. \n",
328+
"### Setting Up Conformal Intervals\n",
288329
"\n",
289-
"For this example, we'll use [SimpleExponentialSmoothing](../models/SimpleExponentialSmoothing) and [ADIDA](../models/ADIDA) which do not provide a prediction interval natively. Thus, it makes sense to use Conformal Prediction to generate the prediction interval. \n",
330+
"The key is the `ConformalIntervals` class, which requires two parameters:\n",
290331
"\n",
291-
"We'll also show using it with [ARIMA](../models/ARIMA) to provide prediction intervals that don't assume normality.\n",
332+
"- `h`: Forecast horizon (how many steps ahead to predict)\n",
333+
"- `n_windows`: Number of cross-validation windows for calibration\n",
292334
"\n",
293-
"To use these models, we first need to import them from `statsforecast.models` and then we need to instantiate them."
335+
"### Parameter Requirements\n",
336+
"\n",
337+
"- `n_windows * h` must be less than your time series length\n",
338+
"- `n_windows` should be at least 2 for reliable calibration\n",
339+
"- Larger `n_windows` improves calibration but increases computation time"
294340
]
295341
},
296342
{
@@ -339,10 +385,14 @@
339385
"cell_type": "markdown",
340386
"metadata": {},
341387
"source": [
342-
"Now we're ready to generate the forecasts and the prediction intervals. To do this, we'll use the `forecast` method, which takes two arguments: \n",
388+
"## Generating Forecasts with Prediction Intervals\n",
389+
"\n",
390+
"The `forecast` method generates both point forecasts and conformal prediction intervals:\n",
391+
"\n",
392+
"- `h`: Forecast horizon (number of steps ahead)\n",
393+
"- `level`: List of confidence levels (e.g., `[80, 90]` for 80% and 90% intervals)\n",
343394
"\n",
344-
"- `h`: An integer that represent the forecasting horizon. In this case, we'll forecast the next 24 hours. \n",
345-
"- `level`: A list of floats with the confidence levels of the prediction intervals. For example, `level=[95]` means that the range of values should include the actual future value with probability 95%. "
395+
"The output includes columns for each model's forecast and corresponding prediction interval bounds (`model-lo-{level}`, `model-hi-{level}`)."
346396
]
347397
},
348398
{
@@ -541,16 +591,18 @@
541591
"cell_type": "markdown",
542592
"metadata": {},
543593
"source": [
544-
"## Plot prediction intervals\n",
594+
"## Visualizing Calibrated Prediction Intervals\n",
545595
"\n",
546-
"Here we'll plot the different intervals for one timeseries. "
596+
"Let's examine the prediction intervals for each model to understand their characteristics and calibration quality."
547597
]
548598
},
549599
{
550600
"cell_type": "markdown",
551601
"metadata": {},
552602
"source": [
553-
"The prediction interval with the SeasonalExponentialSmoothing seen below. Even if the model generates a point forecast, we are able to get a prediction interval. The 80% prediction interval does not cross the 90% prediction interval, which is a sign that the intervals are calibrated."
603+
"### SeasonalExponentialSmoothing: Well-Calibrated Intervals\n",
604+
"\n",
605+
"The conformal prediction intervals show proper nesting: the 80% interval is contained within the 90% interval, indicating well-calibrated uncertainty quantification. Even though this model only produces point forecasts, conformal prediction successfully generates meaningful prediction intervals."
554606
]
555607
},
556608
{
@@ -578,7 +630,9 @@
578630
"cell_type": "markdown",
579631
"metadata": {},
580632
"source": [
581-
"For weaker fitting models, the conformal prediction interval can be larger. A better model corresponds to a narrower interval."
633+
"### ADIDA: Wider Intervals for Weaker Models\n",
634+
"\n",
635+
"Models with higher prediction errors produce wider conformal intervals. This is a feature, not a bug: the interval width honestly reflects the model's uncertainty. A better-fitting model will produce narrower, more informative intervals."
582636
]
583637
},
584638
{
@@ -606,7 +660,9 @@
606660
"cell_type": "markdown",
607661
"metadata": {},
608662
"source": [
609-
"ARIMA is an example of a model that provides a forecast distribution, but we can still use conformal prediction to generate the prediction interval. As mentioned earlier, this method has the benefit of not assuming normality."
663+
"### ARIMA: Distribution-Free Alternative\n",
664+
"\n",
665+
"ARIMA models typically provide prediction intervals assuming normally distributed errors. By using conformal prediction, we get distribution-free intervals that don't rely on this assumption, which is valuable when the normality assumption is questionable."
610666
]
611667
},
612668
{
@@ -634,9 +690,9 @@
634690
"cell_type": "markdown",
635691
"metadata": {},
636692
"source": [
637-
"## StatsForecast Object\n",
693+
"## Alternative: Setting Conformal Intervals on StatsForecast Object\n",
638694
"\n",
639-
"Alternatively, the prediction interval can be defined on the StatsForecast object. This will apply to all models that don't have the `prediction_intervals` defined."
695+
"You can apply conformal prediction to all models at once by specifying `prediction_intervals` in the `StatsForecast` object. This is convenient when you want the same conformal setup for multiple models."
640696
]
641697
},
642698
{
@@ -783,11 +839,29 @@
783839
"\n",
784840
"- Exploring larger datasets\n",
785841
"- Incorporating industry-specific examples\n",
786-
"- Investigating specialized methods like the jackknife+ that are closely related to conformal prediction (for details on the jackknife+ see [here](https://valeman.medium.com/jackknife-a-swiss-knife-of-conformal-prediction-for-regression-ce3b56432f4f)).\n",
842+
"- Investigating specialized methods like the jackknife+ that are closely related to conformal prediction (for details on the jackknife+ see [here](https://valeman.medium.com/jackknife-a-swiss-knife-of-conformal-prediction-for-regression-ce3b56432f4f))\n",
787843
"\n",
788844
"If you're interested in any of these, or in any other related topic, please let us know by opening an issue on [GitHub](https://github.com/Nixtla/statsforecast/issues)\n",
789845
"\n",
846+
"## Key Takeaways\n",
847+
"\n",
848+
"### Summary: Conformal Prediction for Time Series\n",
849+
"\n",
850+
"- **Model-agnostic**: Works with any forecasting model in Python \n",
851+
"- **Distribution-free**: No normality assumptions required \n",
852+
"- **Well-calibrated**: Theoretical coverage guarantees \n",
853+
"- **Easy to implement**: Just add `ConformalIntervals` to your StatsForecast models \n",
854+
"- **Flexible**: Apply to individual models or all models at once\n",
855+
"\n",
856+
"**Next steps:**\n",
857+
"\n",
858+
"- Try conformal prediction on your own forecasting problems\n",
859+
"- Experiment with different `n_windows` values for optimal calibration\n",
860+
"- Compare with native prediction intervals from statistical models\n",
861+
"- Explore [advanced uncertainty quantification methods](./UncertaintyIntervals)\n",
862+
"\n",
790863
"## Acknowledgements\n",
864+
"\n",
791865
"We would like to thank [Kevin Kho](https://github.com/kvnkho) for writing this tutorial, and Valeriy [Manokhin](https://github.com/valeman) for his expertise on conformal prediction, as well as for promoting this work."
792866
]
793867
},

0 commit comments

Comments
 (0)