Orbit: Bayesian Time Series Modeling

repository·dev·Indexed 24 days ago

https://github.com/uber/orbit

Orbit (orbit-ml) is a Python package for Bayesian time series forecasting and inference. It provides an intuitive initialize-fit-predict interface and supports models such as Damped Local Trend (DLT), Exponential Smoothing (ETS), Local Global Trend (LGT), and Kernel Time-based Regression (KTR). The library leverages probabilistic programming languages like Pyro and CmdStanPy to perform estimation via Markov-Chain Monte Carlo (MCMC), Maximum a Posteriori (MAP), and Stochastic Variational Inference (SVI).

Tokens
8.9K
Snippets
22
Records
37
Agent score
84%

What's inside Orbit

  1. Overview of Orbit's modeling and sampling capabilities

    dev

    Orbit is a Python package for Bayesian time series modeling and inference. It follows a standard initialize-fit-predict interface.

    Supported Models

    • Damped Local Trend (DLT)
    • Exponential Smoothing (ETS)
    • Local Global Trend (LGT)
    • Kernel-based Time-varying Regression (KTR)

    Supported Sampling Methods

    Orbit uses probabilistic programming languages like pyro and cmdstanpy to perform model estimation via:

    • Markov-Chain Monte Carlo (MCMC): Full sampling method.
    • Maximum a Posteriori (MAP): Point estimate method.
    • Stochastic Variational Inference (SVI): Hybrid-sampling method on approximate distribution.
  2. Overview of Orbit models and estimation methods

    dev

    Orbit is a Python package for Bayesian time series forecasting and inference. It supports several concrete model implementations and multiple sampling/optimization methods for estimation.

    Supported Models

    • Exponential Smoothing (ETS)
    • Local Global Trend (LGT)
    • Damped Local Trend (DLT)
    • Kernel Time-based Regression (KTR)

    Estimation/Inference Methods

    • Markov-Chain Monte Carlo (MCMC): Full sampling method.
    • Maximum a Posteriori (MAP): Point estimate method.
    • Variational Inference (VI): Hybrid-sampling method providing an approximate distribution.
  3. Available forecasting models in orbit.models

    dev

    The orbit.models package provides several Bayesian forecasting model implementations. Depending on your time series characteristics, you can use one of the following submodules:

    • orbit.models.ets: Error, Trend, Seasonality (ETS) models.
    • .lgt: Local Global Trend (LGT) models.
    • .dlt: Damped Local Trend (DLT) models.
    • .ktrlite: KTRLite models.
  4. Install Orbit from source

    dev

    To install Orbit from the source code, clone the repository and install the requirements and the package using pip.

    $ git clone https://github.com/uber/orbit.git
    $ cd orbit
    $ pip install -r requirements.txt
    $ pip install .
  5. Install orbit-ml from GitHub source

    dev

    To install the latest development version from the GitHub repository, clone the repository and install the dependencies and the package locally.

    git clone https://github.com/uber/orbit.git
    cd orbit
    pip install -r requirements.txt
    pip install .
  6. Install Orbit via pip or conda

    dev

    You can install the stable release of Orbit using pip from PyPI or conda from the conda-forge channel. To install the development version, use the dev branch from GitHub.

    Note: Orbit requires cmdstanpy as a core dependency for Bayesian sampling.

  7. Quick Start with Damped-Local-Trend (DLT) Model

    dev

    Orbit provides an initialize-fit-predict interface. The following example demonstrates a full Bayesian prediction using the DLT model with regressors and seasonality.

    Key steps:

    1. Load your dataset.
    2. Split data into training and testing sets.
    3. Initialize the DLT model specifying response_col, date_col, regressor_col, and seasonality.
    4. Call .fit(df=train_df) to train the model.
    5. Call .predict(df=test_df) to generate predictions.
    6. Use plot_predicted_data to visualize the results.
    from orbit.utils.dataset import load_iclaims
    from orbit.models import DLT
    from orbit.diagnostics.plot import plot_predicted_data
    
    # log-transformed data
    df = load_iclaims()
    # train-test split
    test_size = 52
    train_df = df[:-test_size]
    test_df = df[-test_size:]
    
    dlt = DLT(
      response_col='claims', date_col='week',
      regressor_col=['trend.unemploy', 'trend.filling', 'trend.job'],
      seasonality=52,
    )
    dlt.fit(df=train_df)
    
    # outcomes data frame
    predicted_df = dlt.predict(df=test_df)
    
    plot_predicted_data(
      training_actual_df=train_df, predicted_df=predicted_df,
      date_col=dlt.date_col, actual_col=dlt.response_col,
      test_actual_df=test_df
    )
  8. How Orbit's class design works

    dev

    Orbit's architecture (as of v1.1.0) is composed of three primary interacting components:

    1. Forecaster: The top-level interface for users to perform fit and predict tasks. It handles the execution flow and supports different methodologies:
      • MAP (Maximum a posterior): Yields point posterior estimates via get_point_posterior().
      • SVI (Stochastic Variational Inference): Allows posterior sample extraction via get_posteriors().
      • Full Bayesian: Allows posterior sample extraction via get_posteriors().
      • Note: You can approximate point estimates in SVI/Full Bayesian by passing point_method='median' to the .fit() method.
    2. Model: An object inheriting from ModelTemplate. It defines the model structure, parameters, likelihoods, and inputs. It turns the logic of fit() and predict() concrete by supplying a fitter (either a file like CmdStanPy or a callable class like Pyro) and an internal predict() method.
    3. Estimator: The component that implements specific APIs for sampling or optimization (e.g., PyroEstimator or StanEstimator). It acts as the bridge between the Forecaster and the underlying probabilistic programming library.

    To use a Forecaster, you must provide it with a Model and an Estimator object.

  9. How TimeSeriesSplitter works for expanding and rolling windows

    dev

    The TimeSeriesSplitter is used to partition time-series data into training and testing sets for backtesting. It supports two primary windowing schemes:

    1. Expanding window: The training start date is fixed, and the training end date extends forward in time. This incorporates all available historical information.
    2. Rolling window: The training window has a fixed length, and the entire window moves forward in time.

    You can define the splitting logic using min_train_len (minimum training window size), forecast_len (length of the forecast window), and incremental_len (the step size for moving forward). Alternatively, you can specify a fixed number of splits using n_splits, which automatically calculates the required minimum training length.

    TimeSeriesSplitter is implemented as a generator, allowing you to iterate through splits using .split().

  10. Use BIC for feature selection with MAP estimators

    dev

    Bayesian information criterion (BIC) is used to find the optimal number of features for models using the stan-map estimator. To use BIC, fit the model using .fit() and then retrieve the value using .get_bic().

    # Example: Calculating BIC for a DLT model using MAP
    dlt_mod = DLT(
        estimator='stan-map',
        response_col=response_col,
        date_col=dt_col,
        regressor_col=regressor_col,
        seed=2022,
        level_sm_input=0.01,
        slope_sm_input=0.01,
    )
    dlt_mod.fit(df=df)
    BIC_temp = dlt_mod.get_bic()
  11. Initialize and use a Forecaster with a custom model

    dev

    Once you have defined a custom Model class, you use a Forecaster to perform the actual fitting and prediction. The choice of Forecaster depends on your model's backend (e.g., use SVIForecaster for Pyro-based models).

    Workflow

    1. Instantiate the Model: Pass configuration parameters like regressor_col.
    2. Instantiate the Forecaster: Provide the model, response_col, date_col, and the appropriate estimator_type.
    3. Fit: Call .fit(train_df).
    4. Predict: Call .predict(df) to get forecasts.
    5. Extract Posteriors: Use .get_posterior_samples() to access the sampled parameters.

    Example

    # 1. Initialize custom model
    model = BayesLinearRegression(regressor_col=['x1','x2'])
    
    # 2. Initialize Forecaster (using SVI for Pyro)
    blr = SVIForecaster(
        model=model,
        response_col='y', 
        date_col='week',
        estimator_type=PyroEstimatorSVI,
        verbose=True,
        num_steps=501,
        seed=2021,
    )
    
    # 3. Fit the model
    blr.fit(train_df)
    
    # 4. Predict
    predicted_df = blr.predict(df)
    
    # 5. Access posterior samples
    weights = blr.get_posterior_samples()['weight']
    model = BayesLinearRegression(
        regressor_col=['x1','x2'], 
    )
    
    blr = SVIForecaster(
        model=model,
        response_col='y', 
        date_col='week',
        estimator_type=PyroEstimatorSVI,
        verbose=True,
        num_steps=501,
        seed=2021,
    )
    
    blr.fit(train_df)
    predicted_df = blr.predict(df)
    estimated_weights = blr.get_posterior_samples()['weight']