diff --git a/docs/source/forecasting.md b/docs/source/forecasting.md index 6048ad2626..bdde01ed69 100644 --- a/docs/source/forecasting.md +++ b/docs/source/forecasting.md @@ -1,6 +1,6 @@ # Time Series Forecasting -Time series forecasting models (TSFMs) predict future values of a series from its observed history. +Time series foundation models (TSFMs) predict future values of a series from its observed history. While many forecasting foundation models originally focused on predicting a single variable from its own history (**univariate forecasting**), newer models such as [Chronos-2](https://arxiv.org/abs/2510.15821) and [TimesFM-3](https://research.google/blog/timesfm-3-a-zero-shot-foundation-model-for-multivariate-forecasting) extend this paradigm to multiple targets (**multivariate forecasting**) and **covariates**: additional variables that inform the forecast (*e.g.*, historical temperature or planned promotions). These capabilities allow models to draw on relationships between targets, past observations of external factors, and known future information. @@ -39,7 +39,7 @@ We begin with a single target, the daily sales of ice cream, observed for five d -A time series is a {py:class}`~sdm.tensor.TableTensor` in which each row is one time step, sorted in time, and each column is one variable: +We represent a time series as a {py:class}`~sdm.tensor.TableTensor` with one row per time step, sorted in time, and one column per variable: ```python import sdm @@ -51,7 +51,7 @@ history = sdm.TableTensor.from_columns( ) ``` -We can forecast with any time series foundation model in [`sdm.models`](api/models). +We can forecast with any time series forecasting model in [`sdm.models`](api/models). Here, we use {py:class}`~sdm.models.TimesFM3`: ```python @@ -65,7 +65,7 @@ out = model( Note that `x_context` and `x_query` carry the covariates. Since we have none yet, both tables hold zero columns. -However, we still need to pass them to {py:meth}`~sdm.models.ICLModel.forward`, in particular because the number of rows in `x_query` define the **forecast horizon**: here, we request predictions for the next three time steps. +However, we still need to pass them to {py:meth}`~sdm.models.ICLModel.forward`, in particular because the number of rows in `x_query` defines the **forecast horizon**: here, we request predictions for the next three time steps. The forecast is returned as a {py:class}`~sdm.tensor.TableTensor` with one row per future step. Its output is model-specific, *e.g.*, {py:class}`~sdm.models.TimesFM3` outputs one column per target and quantile, from the 10th to the 90th percentile, named `"__q"`: @@ -78,7 +78,7 @@ out["ice_cream__q90"].numerical # upper end of an 80% prediction interval ## Multivariate Forecasting -Models with {py:attr}`sdm.models.ICLModel.supports_multi_target` can forecast multiple targets jointly, allowing them to exploit dependencies between them. +A model that {py:attr}`~sdm.models.ICLModel.supports_multi_target` can forecast multiple targets jointly, allowing them to exploit dependencies between them. In this case, we can simply add the daily sales of cold drinks as a second target: @@ -112,8 +112,8 @@ out = model( ## Covariates Lastly, we add known future and past-only covariates to our model. -For example, the measured **temperature** is a past covariate: its values are unavailable for the forecast horizon. -Models with {py:attr}`sdm.models.ICLModel.supports_context_only_columns` can exploit such context-only columns. +For example, the measured **temperature** is a past-only covariate: its values are unavailable for the forecast horizon. +A model that {py:attr}`~sdm.models.ICLModel.supports_context_only_columns` can exploit such past-only covariates. In contrast, **promotion** is a known future covariate that indicates whether a promotion was or is scheduled for a given day. @@ -123,10 +123,8 @@ In contrast, **promotion** is a known future covariate that indicates whether a - - @@ -142,9 +140,9 @@ history = sdm.TableTensor.from_columns( }, stypes={ "ice_cream": "numerical", - "cold_drinks": "numerical" - "temperature": "numerical" - "promotion": "numerical" + "cold_drinks": "numerical", + "temperature": "numerical", + "promotion": "numerical", }, device="cuda", ) @@ -171,7 +169,7 @@ In summary, the columns that are passed determine which covariates the model see As with any other {py:class}`~sdm.models.ICLModel`, the `num_estimators` argument controls how many ensemble members contribute to the forecast. Each member may receive a differently transformed view of the series, and their predictions are averaged into a single forecast. -For example, the default recipe for {py:class}`~sdm.models.TimesFM3` alternatives between the original series and a sign-flipped version. +For example, the default recipe for {py:class}`~sdm.models.TimesFM3` alternates between the original series and a sign-flipped version. Using two estimators includes both views: ```python @@ -186,7 +184,7 @@ Each task itself can contain multiple targets and covariates. For example, store sales can be represented in two ways: as separate univariate tasks in a batch (forecasting each store independently) or as a multivariate task (allowing the model to use relationships between stores). -To forecast a batch series in one call, stack them along a leading batch dimension. +To forecast a batch of series in one call, stack them along a leading batch dimension. All series in a batch share the same horizon and number of context rows, and shorter series should be left-padded with `NaN`. Set `num_estimators` explicitly so that the leading dimension is interpreted as a batch of independent forecasting tasks rather than as ensemble members: @@ -195,10 +193,10 @@ import torch out = model( x_context=torch.randn(64, 128, 0, device="cuda"), - x_context=torch.randn(64, 128, 2, device="cuda"), + y_context=torch.randn(64, 128, 2, device="cuda"), x_query=torch.randn(64, 32, 0, device="cuda"), num_estimators=1, ) ``` -See [`examples/timeseries/quickstart.py`](https://github.com/NVIDIA/structured-data-models/blob/main/examples/timeseries/quickstart.py) for runnable examples on real-world datasets and tasks. +See [`examples/timeseries/forecast.py`](https://github.com/NVIDIA/structured-data-models/blob/main/examples/timeseries/forecast.py) for runnable examples on real-world datasets and tasks.
ice cream4055807550???
cold drinks2530454128???
temperature2124282722
promotion00110100