functime Documentation

repository·main·Indexed 22 days ago

https://github.com/functime-org/functime

A high-performance Python library for global forecasting and time-series feature extraction on large panel datasets. It leverages Polars for parallelized processing and provides a custom `.ts` namespace with over 100 feature extractors. The library includes a functional API for forecasting, support for target and feature transformations, and auto-forecasters using FLAML for hyperparameter and lag tuning. It supports various models including linear models, CatBoost, XGBoost, and LightGBM.

Tokens
31.9K
Snippets
129
Records
147
Agent score
78%

What's inside functime

  1. Overview of forecasting capabilities in functime

    main

    The functime forecasting API supports the full machine learning lifecycle for time-series:

    • Forecast Types: Supports both point and probabilistic forecasts (via quantile regression and conformal prediction).
    • Features: Supports exogenous features and seasonality effects (using calendar, Fourier, and holiday features).
    • Validation: Includes backtesting utilities with expanding window and sliding window splitters.
    • Automation: Uses FLAML for automated lags and hyperparameter tuning.
    • Strategies: Supports both recursive and direct forecast strategies.
    • Metrics: Provides parallel scoring for metrics like MASE, SMAPE, and CRPS.
  2. Choose a forecast strategy

    main

    The functime forecasting module supports three distinct strategies for multi-step forecasting:

    1. Recursive (Default): Predicts the next step and uses that prediction as an input for the subsequent step.
    2. Direct: Fits a separate model for each specific forecast horizon. Requires max_horizons and freq to be specified.
    3. Ensemble: A combination of both recursive and direct strategies.

    When using direct or ensemble, you must provide max_horizons (the number of models to fit) and the frequency freq.

    from functime.forecasting import linear_model
    
    # Recursive (Default)
    recursive_forecaster = linear_model(strategy="recursive")
    y_pred_rec = recursive_forecaster(y_train, fh)
    
    # Direct
    max_horizons = 12
    direct_forecaster = linear_model(strategy="direct", max_horizons=max_horizons, freq="1mo")
    y_pred_dir = direct_forecaster(y_train, fh)
    
    # Ensemble
    ensemble_forecaster = linear_model(strategy="ensemble", max_horizons=max_horizons, freq="1mo")
    y_pred_ens = ensemble_forecaster(y=y_train, fh=3)
  3. How global forecasting works in functime

    main

    Unlike local forecasters (e.g., ARIMA, ETS) that fit one model per time series, functime only supports global forecasters. A global forecaster fits and predicts a collection of time series (panel data) using a single model. This approach is generally more efficient and often more accurate for large collections of similar series (e.g., sales across products, sensor data across devices).

    All forecasters in functime are designed to operate globally across collections of time series using polars for high-performance, multi-threaded parallelism.

  4. Extract time-series features using the `ts` Polars namespace

    main

    functime provides over 100+ time-series feature extractors (such as binned_entropy or longest_streak_above_mean).

    Key Features:

    • Namespace: All features are registered under a custom ts Polars namespace.
    • Performance: Approximately 85% of implementations are optimized lazy queries that work on both polars.Series and polars.Expr.
    • Scalability: Supports univariate extraction, extraction across many time-series (via group_by), and extraction across windows (via group_by_dynamic).
    • Efficiency: Offers significant speed-ups compared to tsfresh, especially for group-by operations.
  5. Understand functime's lazy evaluation model

    main

    Many components in functime (transformers, splitters, etc.) are lazy. When you call them, they return a polars.LazyFrame representing a computation graph rather than executing the operation immediately.

    Key implications:

    • Performance: Lazy evaluation allows polars to optimize the entire query plan (e.g., combining multiple group_by operations into one) before execution.
    • Execution: No computation is performed until you call .collect() on the resulting LazyFrame.
    • Best Practice: Preprocess your X and y datasets lazily using .pipe() to ensure optimal multi-threaded parallelism and efficient memory usage.
  6. How the `ts` Polars namespace works

    main

    The ts namespace is a custom extension for Polars that provides access to over 100 time-series feature extractors. It is designed to work seamlessly with Polars Series, Expressions, and LazyFrames.

    Crucial Requirement: The .ts namespace is only available if you import functime in your script. Once imported, you can call features directly on columns within select, agg, or with_columns contexts, allowing for highly optimized, parallelized feature engineering on large datasets via group_by or group_by_dynamic operations.

  7. Understand supported data schemas for panel and time-series data

    main

    Depending on the operation, functime expects different DataFrame structures:

    Panel Data

    Used by forecasters, preprocessors, and splitters. A panel dataset contains multiple entities.

    • Structure: The first two columns must represent the entity (e.g., commodity name) and time (e.g., date). Subsequent columns represent observed values (e.g., price).
    • Requirement: The DataFrame must be sorted by entity, then by time.

    Time Series Data

    Used by feature extractors. A time-series DataFrame represents the measurements for a single entity.

    • Structure: Contains columns for time and the observed values (e.g., price).
    ### Panel Data Example
    # shape: (47_583, 3)
    commodity_type   time         price
    ------------------------------------
    Aluminum         1960-01-01    511.47
                     1960-02-01    511.47
                     ...
    Zinc             2022-11-01   2938.92
                     2022-12-01   3129.48
    
    ### Time Series Example
    # shape: (756, 3)
    time         price
    ------------
    1960-01-01    511.47
    1960-02-01    511.47
    ...
  8. How preprocessing works in functime

    main

    All functime preprocessors use Polars for parallelized time-series preprocessing. They operate on a panel DataFrame by applying transformations to each time-series locally (i.e., as a parallelized group_by operation).

    Transformations are used to stabilize variance (e.g., boxcox) or achieve stationarity (e.g., diff or detrend). Many transformations are invertible, allowing you to convert forecasts from the transformed scale back to the original scale using the .invert() method.

  9. Use auto-forecasters for automated hyperparameter and lag tuning

    main
    Auto-forecasters (such as auto_lasso or auto_xgboost) use the FLAML library to automatically optimize both hyperparameters and the number of lagged dependent variables. This is useful when you want to find the best performing model configuration without manual tuning. FLAML utilizes the CFO (Frugal Optimization for Cost-related Hyperparameters) algorithm for efficient optimization.
  10. Develop and test functime contributions

    main

    When working on an issue, create a new git branch from main.

    • Code Locations: Rust code is in src/; Python code is in functime/.
    • Testing: Run tests using rye test.
    • Formatting and Linting: Use rye fmt and rye lint. Note that code cannot be merged if these checks fail.
    • Requirements:
      • Add tests for your new code.
      • If you change the public API, you must update the documentation.
      • pre-commit checks will run automatically before any commit.
    rye test
    rye fmt
    rye lint
  11. Perform time-series preprocessing with Polars LazyFrames

    main

    Preprocessors in functime are designed to work with polars.DataFrame or polars.LazyFrame.

    Key Behavior:

    • Preprocessors always return a polars.LazyFrame.
    • No computation is performed immediately. This allows Polars to optimize the entire query plan.
    • You must call .collect() (optionally with streaming=True) to execute the operations and return a polars.DataFrame.
    • It is recommended to use df.pipe() to chain multiple preprocessing steps together.
    from functime.preprocessing import boxcox, impute
    
    # Use df.pipe to chain operations together
    X_new: pl.LazyFrame = (
        X.pipe(boxcox(method="mle"))
        .pipe(detrend(method="linear"))
    )
    
    # Call .collect to execute query
    X_new: pl.DataFrame = X_new.collect(streaming=True)