Utah PM2.5 forecasting models

Hourly PM2.5 (µg/m³) forecasts 24, 48, and 72 hours ahead for Utah's regulatory air quality monitors. These are the current champions of a weekly retraining job with a promotion gate. They're used in batch every few hours, and the forecasts are published to itstheryguy/aq-utah-forecasts and shown in the Utah PM2.5 Forecast Space. Code and design: github.com/itstheryguy/aq_utah_project.

Folder Model
lightgbm/ LightGBM, one gradient-boosted model per horizon (Tweedie objective)
gru/ GRU trained from scratch in PyTorch: the last 72 h as a sequence, plus forecast weather, three outputs
linear/ Ridge regression per horizon on five inputs: current and 24 h mean PM2.5, forecast inversion, wind, precipitation

Each folder is an MLflow pyfunc model (MLmodel, model files under artifacts/, model code under code/):

import mlflow
model = mlflow.pyfunc.load_model("lightgbm")   # a local copy of the folder
forecasts = model.predict(gold_rows)           # station_id, hour_utc, pred_t24, pred_t48, pred_t72

The input is rows of the project's gold_features table, one per station-hour: recent PM2.5 and NO₂, rolling statistics, a regional mean, calendar features, and weather forecasts as issued 1–3 days ahead (Open-Meteo, gfs_seamless), including a valley-minus-ridge temperature inversion proxy.

Evaluation

Promotion gate for the current versions: mean absolute error (µg/m³) on the 28 most recent days with labels, which neither the new version nor the previous champion was trained on.

Model Version Trained through 24 h 48 h 72 h Persistence 24 h 48 h 72 h
lightgbm v1 2026-10-02 1.83 1.80 1.90 2.44 2.93 3.19
gru v2 2026-10-06 1.85 1.95 2.14 2.52 2.96 3.23
linear v2 2026-10-06 2.08 2.28 2.37 2.52 2.96 3.23

Backtest (trained through Oct 2025, scored on Nov 2025 → Oct 2026), MAE in µg/m³, all stations:

Model 24 h 48 h 72 h Winter 72 h Summer 72 h
Persistence 3.30 3.80 4.07 5.20 4.89
LightGBM 2.50 2.66 2.80 3.19 3.74
GRU 2.57 2.67 2.78 3.05 3.70
Ridge, 5 inputs 2.78 3.02 3.11 4.00 3.84

Training data

2024-01-22 onward: AirNow PM2.5 and NO₂ history via OpenAQ, with hours removed by EPA quality review (EPA AirData) excluded from the labels; Utah DAQ's live feed after that; Open-Meteo forecasts as issued (Previous Runs API). 26 stations, ~635k station-hours.

Limitations

  • Spikes aren't predicted. On hours ≥ 35.5 µg/m³, every model (and persistence) is off by ~30–35, almost all underprediction. Fireworks and wildfire smoke from outside the region aren't visible in the features.
  • Labels from the last few months are provisional: EPA's quality review lags by about half a year.
  • Trained on Utah's monitors only. Not an official forecast.

Published 2026-11-09 13:53 UTC from Unity Catalog @champion aliases.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Space using itstheryguy/aq-utah-models 1