mlforecast

repository·main·Indexed 22 days ago

https://github.com/nixtla/mlforecast

A scalable machine learning framework for time series forecasting (version 1.1.0). It enables efficient feature engineering and supports training any scikit-learn compatible regressor on massive datasets. Key features include the MLForecast object for automated feature engineering, AutoMLForecast for automated model selection and tuning, and DistributedMLForecast for distributed computing with pandas, polars, spark, dask, and ray. It also provides support for probabilistic forecasting via conformal prediction and transfer conformal methods.

Tokens
49K
Snippets
83
Records
234
Agent score
76%

What's inside mlforecast

  1. MLForecast Features and Capabilities

    main

    Core Features

    • Fast Feature Engineering: Optimized implementations for time series features.
    • Scalability: Out-of-the-box compatibility with pandas, polars, spark, dask, and ray for distributed training.
    • Probabilistic Forecasting: Support for prediction intervals via Conformal Prediction.
    • Covariates: Support for both exogenous variables and static covariates.
    • API Consistency: Uses familiar sklearn syntax (.fit and .predict).
  2. Available lag transformation families

    main

    The mlforecast.lag_transforms module provides several families of transformations:

    • Rolling: Fixed-window statistics over lagged target.
      • RollingMean, RollingStd, RollingMin, RollingMax, RollingQuantile
    • Seasonal rolling: Rolling statistics computed across same-position observations in successive seasons (e.g., last 4 Mondays).
      • SeasonalRollingMean, SeasonalRollingStd, SeasonalRollingMin, SeasonalRollingMax, SeasonalRollingQuantile
    • Expanding: Statistics over all observations up to the lag.
      • ExpandingMean, ExpandingStd, ExpandingMin, ExpandingMax, ExpandingQuantile
    • Exponentially weighted: A weighted mean emphasizing recent observations.
      • ExponentiallyWeightedMean

    Combinators:

    • Offset: Applies a transformation at a shifted lag.
    • Combine: Joins two transformations with a binary operator (e.g., a ratio of two rolling means).
  3. Optimize memory with keep_last_n in TimeSeries.fit_transform

    main

    When working with very long time series, you can use the keep_last_n parameter in TimeSeries.fit_transform. This tells the system to keep only the last n samples of each time series for computing updates, saving both memory and time.

    How to choose n: Set n to the minimum number of samples required to compute your transformations. For example, if you have a RollingMean(window_size=14) applied to a lag 2, you need at least 15 samples (the 14 for the window plus the lag offset) to ensure the first update can be computed correctly.

    # Example: keeping only the last 15 samples to save memory
    keep_last_n = 15
    ts = TimeSeries(**flow_config)
    df = ts.fit_transform(
        series, 
        id_col='unique_id', 
        time_col='ds', 
        target_col='y', 
        keep_last_n=keep_last_n
    )
  4. Configure pooled mode for lag transformations

    main

    Pooled mode allows computing statistics across multiple series at once. Built-in rolling, expanding, seasonal-rolling, and exponentially weighted transforms support three pooling parameters:

    • global_: bool: When True, the statistic is computed across all series aggregated by timestamp. Every series receives the same feature value at each timestamp.
    • groupby: Sequence[str]: Column names to group by before computing the statistic. These columns must be declared as static features during fit or preprocess. Series in the same group share the feature value; different groups get different values.
    • partition_by: Sequence[str]: Column names to partition further along a dynamic (time-varying) key (e.g., promo or regime).

    Rules and Composition:

    • global_ and groupby are mutually exclusive.
    • partition_by can compose with global_, groupby, or stand alone (local mode).
    • All pooled modes require every series to end at the same timestamp.
    • RANGE semantics: Pooled transforms use SQL-style RANGE BETWEEN ... PRECEDING windows over actual timestamps. They assume a continuous, gap-free time grid within each series. Combining validate_data=False with a pooled transform will raise a UserWarning.
  5. Understand min_samples behavior in pooled mode

    main

    The min_samples parameter behaves differently depending on whether you are in local or pooled mode:

    • Local (per-series) mode: min_samples is capped at window_size.
    • Pooled mode: min_samples counts the total non-NaN observations across all series in the bucket within the rolling window, with no capping.

    This allows min_samples to act as a coverage threshold. For example, RollingMean(window_size=1, min_samples=2, groupby=['brand']) will only produce a non-null value at timestamps where at least two series within that brand contribute observations.

  6. Use MLForecast for time series forecasting

    main

    The MLForecast object follows the scikit-learn API pattern (.fit() and .predict()). It automates feature engineering (lags, transformations, date features) and trains multiple models simultaneously.

    Workflow:

    1. Define Models: Provide a list of regressors that implement the scikit-learn API (e.g., LGBMRegressor, LinearRegression).
    2. Instantiate MLForecast: Specify the models, frequency (freq), lags, lag transformations, date features, and target transformations.
    3. Fit: Call .fit(series) to compute features and train models.
    4. Predict: Call .predict(n) to generate forecasts for the next n steps using a recursive strategy.
    import lightgbm as lgb
    from sklearn.linear_model import LinearRegression
    from mlforecast import MLForecast
    from mlforecast.lag_transforms import ExpandingMean, RollingMean
    from mlforecast.target_transforms import Differences
    
    # 1. Define models
    models = [
        lgb.LGBMRegressor(random_state=0, verbosity=-1),
        LinearRegression(),
    ]
    
    # 2. Instantiate MLForecast
    fcst = MLForecast(
        models=models,
        freq='D',
        lags=[7, 14],
        lag_transforms={
            1: [ExpandingMean()],
            7: [RollingMean(window_size=28)]
        },
        date_features=['dayofweek'],
        target_transforms=[Differences([1])],
    )
    
    # 3. Training
    fcst.fit(series)
    
    # 4. Predicting
    predictions = fcst.predict(14)
  7. Use AutoMLForecast for automated model selection and tuning

    main

    AutoMLForecast is a high-level class that automates the process of selecting and tuning multiple forecasting models. It allows you to pass a dictionary of models (including specialized Auto versions of models like AutoLightGBM or AutoXGBoost) and automatically optimizes them using hyperparameter tuning.

    Key features include:

    • Model Ensemble/Selection: Pass multiple models to the models argument.
    • Hyperparameter Tuning: Use fit_config to define tuning logic (e.g., specifying static features).
    • Backtesting: Use n_windows in .fit() to perform cross-validation/backtesting.
    • Prediction Intervals: Integrate PredictionIntervals to generate uncertainty bounds.
    • Data Support: Works with both pandas and polars DataFrames.
    from mlforecast.auto import AutoMLForecast, AutoLightGBM, AutoRidge
    from mlforecast.utils import PredictionIntervals
    
    # Initialize AutoMLForecast
    auto_mlf = AutoMLForecast(
        freq=1,
        season_length=season_length,
        models={
            'lgb': AutoLightGBM(),
            'ridge': AutoRidge(),
        },
        fit_config=lambda trial: {'static_features': ['unique_id']},
        num_threads=2,
    )
    
    # Fit with backtesting and prediction intervals
    auto_mlf.fit(
        df=train,
        n_windows=2,
        h=h,
        num_samples=2,
        optimize_kwargs={'timeout': 60},
        fitted=True,
        prediction_intervals=PredictionIntervals(n_windows=2, h=h),
    )
    
    # Predict future values
    forecast = auto_mlf.predict(h, level=[80])
  8. Use built-in lag transformations in MLForecast

    main

    Lag transformations compute statistics over lagged values of the target to be used as features. You configure them in the MLForecast constructor using the lag_transforms argument. This argument is a dictionary where:

    • Keys are the lags (integers) to apply the transformation to.
    • Values are lists of transformation instances.

    Transformations are computed per-series by default.

    from mlforecast import MLForecast
    from mlforecast.lag_transforms import ExpandingStd, RollingMean
    
    fcst = MLForecast(
        models=[...],
        freq='D',
        lag_transforms={
            1: [ExpandingStd()],
            7: [RollingMean(window_size=7), RollingMean(window_size=28)],
        },
    )
  9. Prepare data for MLForecast

    main

    MLForecast requires a pandas DataFrame with specific columns to represent time series data. The minimum required columns are:

    • unique_id: A unique identifier for each individual time series.
    • ds: The datestamp column.
    • y: The target values (the values of the series).

    Any additional columns in the DataFrame are automatically treated as static features (features that do not change over time for a given unique_id) unless otherwise specified during the TimeSeries.fit_transform process.

  10. Use LightGBMCV for time series cross-validation

    main

    The LightGBMCV class emulates LightGBM's cv function by training several Boosters simultaneously on different data partitions. This allows for estimating error by iteration, which is useful for early stopping and finding the optimal number of boosting iterations.

    Key features include:

    • Error Estimation: Computes predictions for the whole test period to report error.
    • Early Stopping: Supports stopping training if performance doesn't improve.
    • Ensemble Predictions: predict() returns predictions from every model trained across the windows.
    • CV Predictions: Access validation fold predictions via the cv_preds_ attribute.

    To use it, initialize LightGBMCV with your frequency, lags, and transforms, then call .fit() with configuration parameters like n_windows and h (horizon).

    from mlforecast.models import LightGBMCV
    
    # Configuration for fitting
    static_fit_config = dict(
        n_windows=2,
        h=horizon,
        params={'verbose': -1},
        compute_cv_preds=True,
    )
    
    # Initialize
    cv = LightGBMCV(
        freq=1,
        lags=[24 * (i+1) for i in range(7)],
    )
    
    # Fit the model
    hist = cv.fit(train, **static_fit_config)
    
    # Get predictions from all trained boosters
    preds = cv.predict(horizon)
  11. Use partial_fit with LightGBMCV for hyperparameter tuning

    main

    For efficient hyperparameter tuning (e.g., with Optuna), you can use the setup and partial_fit methods to avoid training the full model if a configuration is unpromising.

    1. Call .setup(train, ...) to prepare the LightGBM datasets and internal features.
    2. Call .partial_fit(n_iterations) to train for a specific number of iterations and return the current score.

    This allows you to prune trials early based on initial performance.

    cv4 = LightGBMCV(
        freq=1,
        lags=[24 * (i+1) for i in range(7)],
    )
    cv4.setup(
        train,
        n_windows=2,
        h=horizon,
        params={'verbose': -1},
    )
    
    # Train for 10 iterations and get the score
    score = cv4.partial_fit(10)