加载中…
加载中…
This repository contains an unsupervised graph autoencoder. The model was trained on QCD background events from the LHC Olympics 2020 R&D dataset.
The repository gives a reference for a known failure. For the W′ → XY signal of the dataset, the anomaly scores of the model are inverted: their ROC AUC is below 0.5. A simple variable without labels, the mean pT per particle, gets an AUC of 0.81.
Do not use this model as an anomaly detector. Use it for these tasks:
| Path | Contents |
|---|---|
seed{0,1,2}/model.safetensors |
Model weights and the feature normalization of the training set (feature_mean, feature_std) |
seed{0,1,2}/config.json |
Data, split, model, training and scorer settings |
seed{0,1,2}/latents_fit.npy |
Latents (16 values) of the 180,000 training events. Use them to fit the kNN and GMM scorers again. |
seed{0,1,2}/training_history.json |
Training loss, validation loss and latent spread for each epoch |
seed{0,1,2}/test_scores.parquet |
Scores of the 10,000 events of the frozen test set, with the HDF5 row of each event |
hv_event_ae/ |
PyTorch code (model, features, loss) to load and run the checkpoints. It does not need the code repository. |
metrics.json |
AUCs, and a check that the published weights reproduce the stored scores |
| Checkpoint | Chamfer | kNN | GMM | Epochs | Best validation loss |
|---|---|---|---|---|---|
| seed0 | 0.419 | 0.405 | 0.448 | 30 | 0.131 |
| seed1 | 0.433 | 0.397 | 0.427 | 30 | 0.119 |
| seed2 | 0.432 | 0.401 | 0.434 | 30 | 0.132 |
Simple variables on the same events, without labels and without training:
| Variable | AUC |
|---|---|
| Mean pT per particle (HT/N) | 0.811 |
| −τ21 | 0.801 |
| HT | 0.792 |
| mjj | 0.788 |
An AUC of 0.40 to 0.44 means that the autoencoder gives background events higher scores than signal events. In this dataset, the signal events have fewer particles, and their particles have higher pT. Thus, the model reconstructs them more easily. For the details, see Section 4 of the paper.
These checkpoints come from a new training run with the configuration and the seeds of the paper. The AUC of
each seed is the same as in the paper. The published weights reproduce the stored Chamfer scores of the test
events with a maximum difference of 1e-5 (see metrics.json).
from huggingface_hub import snapshot_download
import sys
path = snapshot_download("Viverun/lhco-rnd-event-gae")
sys.path.insert(0, path)
from hv_event_ae import load, score
model, ctx = load(f"{path}/seed0")
# particles: float32 [N, P, 3] = (pT [GeV], eta, phi) of each particle,
# sorted by pT in decreasing sequence, with zeros in empty slots.
# P must be 48 or more. The paper used P = 350.
# A row of the R&D HDF5 file (columns 0 to 2099) gives an array of shape [700, 3].
chamfer, z = score(model, ctx, particles) # a higher Chamfer value means "more anomalous"
The code needs torch, numpy and safetensors.
To calculate the kNN and GMM scores, fit the scorers on latents_fit.npy:
latents_fit.npy.NearestNeighbors).GaussianMixture(8, covariance_type='full', reg_covar=1e-4, max_iter=200, random_state=seed).The code repository has this procedure in src/utils/latent_scores.py.
The column h5_row gives the row in the file events_anomalydetection_v2.h5. The paper used this file. Its
rows are sorted: rows 0 to 999,999 are background, and rows 1,000,000 and higher are signal. The test background
events are rows 40,000 to 44,999. The test signal events are rows 1,000,000 to 1,004,999.
@misc{khan2026gae,
author = {Khan, Jamil},
title = {When Graph Autoencoders Look the Wrong Way: Complexity Bias and Simple Baselines in
Unsupervised Anomaly Detection on the LHC Olympics 2020 Dataset},
year = {2026},
doi = {10.5281/zenodo.23432779}
}
Also cite the dataset: G. Kasieczka, B. Nachman, D. Shih, R&D Dataset for LHC Olympics 2020 Anomaly Detection Challenge, Zenodo (2019), doi:10.5281/zenodo.2629072 (CC BY 4.0).