Library / SDK
zillow/luminaire avatar
zillow/luminaire

Luminaire tunes the anomaly detector for you, then profiles the series

Luminaire is a python package that provides ML driven solutions for monitoring time series data.

812 stars66 forksPythonApache-2.0

At a glance

What is it?
Luminaire is Zillow's Python package for monitoring time series data, built around a three part workflow of preprocessing and profiling, model training, and hyperparameter optimisation, with a separate path for high frequency and streaming series. It suits data teams that want anomaly detection to work without a hand tuned model for every metric.
Who is it for?
Adopt Luminaire when you monitor many time series and cannot tune a detector per metric by hand, since the optimisation component picks a model and its configuration for you and the profiling step feeds the training data. Do not adopt it in an environment that cannot accept the pinned dependency versions, because the requirements file caps numpy, pandas and statsmodels at specific older releases, which will conflict with a modern stack.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 143 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The pitch is hands-off anomaly detection

Luminaire is described as a Python package that provides ML-driven solutions for monitoring time series data, and the README's strapline is a hands-off anomaly detection library. The substance is in the capabilities it lists: several anomaly detection and forecasting capabilities that incorporate correlational and seasonal patterns as well as uncontrollable variations in the data over time. That phrase is doing the work. A detector that only reacts to the current point misses the fact that this Tuesday's value is low for this Tuesday, and a detector that ignores seasonality flags every Monday. Luminaire is built to hold both of those in view, and the design consequence is that more of the decision about what counts as anomalous is made inside the library rather than in the calling code. The package is published on PyPI, documented at zillow.github.io/luminaire, and the author of record is the Zillow Group A.I. team.

Three components, and the order they run in

The outlier detection workflow is described as three major components, and the order is the design. The first is data preprocessing and profiling, which prepares a series before a model is trained on it. The second is modeling, which performs time series model training based on either a user-specified configuration or an optimised one, and the README notes that training is integrated with structural time series models as well as filtering based models. The third is configuration optimisation, and this is the component that produces the hands-off behaviour, since its integration with configuration optimisation enables a process where the user needs to provide very minimal configuration for monitoring any type of time series data. The modelling step can be called after preprocessing and profiling, and the optimisation step can be combined with the other two for any auto-configured use case, which the documentation describes as fully automatic outlier detection.

Preprocessing and profiling do the unglamorous work

The first component applies a number of methods whose purpose is to make anomaly detection more accurate and reliable. They are listed as missing data imputation, identifying and removing recent outliers from the training data, necessary mathematical transformations, and data truncation based on recent change points. It also generates profiling information, such as historical change points and trend changes, that is considered in the training process. The README adds the reason profiling exists beyond cleanup, saying that profiling information for time series data can be used to monitor data drift and irregular long-term swings. That is the part that generalises beyond a single alert. A detector that reports only point anomalies will fire constantly on a series whose level has legitimately shifted, and a change point is the signal that says the series is no longer the series the model was trained on.

The batch path, as the example shows it

The README's batch example is worth reading in full because it shows the shape of the API. The input is a dataframe whose index is a time column and whose value column is named `raw`. The optimisation step comes first, and the profiling step that follows builds a DataExploration object from the optimised configuration and returns both the training data and the pre-processing context:

python
# Optimization
hopt_obj = HyperparameterOptimization(freq='D')
opt_config = hopt_obj.run(data=data)

The optimised configuration then names the model class, which is imported dynamically, and the model is trained with the configuration and the profiling context, after which it scores a window of data:

python
# Identify Model
model_class_name = opt_config['LuminaireModel']
module = __import__('luminaire.model', fromlist=[''])
model_class = getattr(module, model_class_name)

# Scoring
trained_model.score(100, '2021-01-01')

Three details are worth noting. The frequency is given explicitly as a daily cadence, the profiling result `pre_prc` is passed into training alongside the configuration, and training returns a success flag together with the model date and the trained model, so a caller can tell whether the fit worked before scoring anything.

Streaming series are scored over a window, not a point

Luminaire can also monitor a set of data points over windows of time instead of tracking individual data points, and the README says this approach is well suited to streaming use cases where sustained fluctuations are of greater concern than individual fluctuations. The streaming example uses the window density model, and the shape of the code differs from the batch path in a way that explains the design. Profiling is done with `stream_profile` rather than `profile`:

python
# Configuration Specs and Profiling
config = WindowDensityHyperParams().params
data, pre_prc = de_obj.stream_profile(df=data)
config.update(pre_prc)

# Training
wdm_obj = WindowDensityModel(hyper_params=config)
success, training_end, model = wdm_obj.train(data=data)

The scoring call is where the difference shows, since it takes a window of data rather than a single point, and the README comments that the scoring data is data over a time-window instead of a datapoint. A window density model asks a different question from a point model, and it answers the question that a monitoring system on a high frequency feed actually needs to ask.

Installing it, and the dependency floor you inherit

Installation from PyPI is a single command:

bash
pip install luminaire

and the module is imported as `luminaire`. The requirements file is where a team should look before committing, because the pins are narrow. numpy is capped at 1.22.4, pandas at 2.0.3 and statsmodels at 0.13.5, while hyperopt, changepy, bayescd, pykalman, scipy, scikit-learn and decorator carry lower bounds only. The `setup.py` reads that file and passes it through as `install_requires`, and it declares `python_requires='>=3.7'` with classifiers for Python 3.7 through 3.10 and a development status of 4 - Beta. The upper bounds are the interesting part. A modern analytics environment usually has a newer pandas and numpy already, and an install that resolves those pins in a fresh virtual environment is not the same as installing into an environment you already have.

Licence, citation and the pace of releases

The licence is Apache 2.0, recorded in `LICENSE.txt` and in the `setup.py` metadata, and the package is distributed under the Zillow Group A.I. team with a development contact address in the project metadata. If you use it in research, the README asks you to cite a specific paper, Building an Automated and Self-Aware Anomaly Detection System, by Chakraborty, Shah, Soltani, Swigart, Yang and Buckingham, published in the 2020 IEEE International Conference on Big Data, with an arXiv link. The release history is slow. The listed versions are 0.4.1 from October 2022, 0.4.2 from November 2022 and 0.4.3 from 2024-01-31, and the last push to the repository was on 2026-06-02, with the repository not archived. The practical reading is that this is a library from a company team, stable in shape but not actively releasing, so the version you install matters more here than in a project with a monthly cadence.

Editorial conclusion

Adopt Luminaire when you monitor many time series and cannot tune a detector per metric by hand, since the optimisation component picks a model and its configuration for you and the profiling step feeds the training data. Do not adopt it in an environment that cannot accept the pinned dependency versions, because the requirements file caps numpy, pandas and statsmodels at specific older releases, which will conflict with a modern stack. Verify first that your data shape matches the input contract, since the examples expect a time column as the dataframe index and a value column named `raw`, and check the Python version, since the package declares support for 3.7 and above.

Frequently asked questions

How do I install Luminaire and run a first detection?

Install it with `pip install luminaire` and import the module. The README's batch example optimises the configuration with `HyperparameterOptimization`, profiles the data with `DataExploration`, identifies the model class from the optimised configuration, trains it, and then scores it with `trained_model.score(100, '2021-01-01')`.

What shape must the input data have?

The examples read a CSV into a pandas dataframe where the time column is set as the index column and the value column is named `raw`. The frequency is passed separately, for example `freq='D'`.

What is the difference between the batch and streaming workflows?

The batch path profiles with `profile` and scores individual points, while the streaming path uses the window density model, profiles with `stream_profile`, and scores a window of data, which the README says suits cases where sustained fluctuations matter more than individual ones.

Which dependency versions does Luminaire require?

The requirements file pins numpy to at most 1.22.4, pandas to at most 2.0.3 and statsmodels to at most 0.13.5, with hyperopt, changepy, bayescd, pykalman, scipy, scikit-learn and decorator listed with lower bounds. The package declares Python 3.7 and above.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. zillow/luminaire on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zillow-luminaire.svg)](https://hysenlabs.com/projects/zillow-luminaire)

Was this useful?