Downloads · 30 days
0
imvetri/afno-v4-pm25
afno-v4-pm25 is a time series forecasting model from imvetri. Use it for the time series forecasting task on the model card, and read the license before you ship it in a product. It is set up for pytorch. The card lists the license as apache-2.0.
A neural-operator model that forecasts PM2.5 over India for the next 16 hours from the previous 10 hours of gridded meteorology and pollution data (140x124 grid, ~25 km resolution, hourly). Built for the ANRF AISEHack…
Downloads · 30 days
0
Access
Public
Updated Jul 15, 2026
Repo size
59.5 MB
Likes
0
Public
Click a slice to open those files.
.pt56 MB · 94%
From the Hugging Face model README
A neural-operator model that forecasts PM2.5 over India for the next 16 hours from the previous 10 hours of gridded meteorology and pollution data (140x124 grid, ~25 km resolution, hourly). Built for the ANRF AISEHack Phase 2, Theme 2 pollution-forecasting competition (IIT Delhi). ~7M parameters, trained from scratch.
Metric: w1*NormGlobalSMAPE + w2*NormEpisodeCorr + w3*NormEpisodeSMAPE (weights
undisclosed by the organizers).
Input tensor: (batch, 20 channels, 10 time steps, 140, 124).
output = last_observed_frame + delta.All channels are derived from the competition data - no external or pretrained inputs.
s42_phaseA_best.pt, s1337_phaseA_best.pt - EMA (eval) weights for the two
seeds, each {'model': state_dict, 'metrics': {...}} for AFNOv4.horizon_scales.npy - 16 per-horizon multiplicative calibration factors.stats.npz - per-pixel normalization stats.afno_v4.py - full model, data, and inference code.import ast, torch, torch.nn as nn, torch.nn.functional as F, numpy as np, os
from huggingface_hub import hf_hub_download
repo = "imvetri/afno-v4-pm25"
src = open(hf_hub_download(repo, "afno_v4.py")).read()
ns = {"os": os, "torch": torch, "nn": nn, "F": F, "np": np}
blocks = "".join(ast.get_source_segment(src, n) + "\n" for n in ast.parse(src).body
if isinstance(n, ast.ClassDef) and n.name in
{"C","AFNO2D","AFNOBlock","ConvBlock","Incep1D","Translator","AFNOv4"})
exec(blocks, ns)
model = ns["AFNOv4"]().eval()
ck = torch.load(hf_hub_download(repo, "s42_phaseA_best.pt"), map_location="cpu", weights_only=False)
model.load_state_dict(ck["model"])
# x: (B, 20, 10, 140, 124) normalized inputs (build with stats.npz as in PM25Test)
# last_log: (B, 140, 124) log1p of the last observed PM2.5 frame
# with torch.no_grad(): pred_log = model(x, last_log) # -> (B, 16, 140, 124)
Inference used to reproduce the competition result: average the two seeds'
predictions and multiply by horizon_scales per forecast hour.
The biggest gain came from fixing a validation data leak (random splits over overlapping windows) that had been masking real progress. On trustworthy leak-free validation, the model then adds atmospheric-physics features, multiscale spectral mixing, a 2-seed ensemble, and per-horizon calibration.
This model is trained on 2016 WRF-Chem simulation data with competition-specific inputs. It is a research / benchmark artifact, not an operational real-world forecaster - it cannot ingest live observations as-is. A real-world version would require retraining on reanalysis inputs (ERA5 / MERRA-2 / CAMS) with ground-truth validation (OpenAQ / CPCB).