Roman SN PIT β Real/Bogus Transient Classifier Ensemble
Binary real-vs-bogus classifier for difference-image cutouts from Nancy Grace Roman Space Telescope supernova simulations, developed for the Roman SN PIT (Roman Supernova Project Infrastructure Team).
Given a 64Γ64 difference-image cutout centered on a candidate detection, each model predicts the probability that the candidate is a real astrophysical transient (PSF-injected point source) as opposed to a bogus detection (subtraction artifact / noise peak from the peak-finder).
Ensemble structure
6 architecture families Γ 4 independently-trained members = 24 models. Each family lives in its own subfolder, with its own model card describing that architecture and its 4 members:
| Folder | Backbone | Pretrained | Mean val. balanced acc. (4 members) |
|---|---|---|---|
DenseNet169/ |
Custom from-scratch DenseNet (growth_rate=32, blocks=6-12-32-32) | No | 96.06% |
ResNeXt50/ |
timm resnext50_32x4d |
ImageNet | 96.72% |
RegNetY016/ |
timm regnety_016 |
ImageNet | 97.21% |
EfficientNetB0/ |
timm efficientnet_b0 |
ImageNet | 97.69% |
ConvNeXtTiny/ |
timm convnext_tiny |
ImageNet | 96.81% |
DeiTTiny/ |
timm deit_tiny_patch16_224 (img_size=64) |
ImageNet | 92.92% |
Validation accuracy is the best-epoch balanced accuracy on the held-out
validation split, as logged in each checkpoint (val_acc key).
Task & data
- Input: single-channel FITS difference-image cutout, resized to 64Γ64 if
needed, normalized with astropy
ZScaleIntervalthen min-max scaled to[0, 1], replicated to 3 channels β tensor of shape(3, 64, 64). - Label 1 (positive): PSF injected into a real difference image at a known
position/SNR (
psf_injection_script.py, SNR sampled uniformly in [3, 10]). - Label 0 (negative): peak-finder detections (β₯3Ο) on unmodified
difference images that do not correspond to an injection
(
find_peaks_above_k_sigma_training.py). - Output: single sigmoid unit, i.e.
P(real transient)in[0, 1].
Loading a single checkpoint
Each .pth file is a dict: {'epoch': int, 'model_state_dict': ..., 'val_acc': float}.
See the per-family README for the exact nn.Module definition needed to
load_state_dict, e.g.:
import torch
ckpt = torch.load("EfficientNetB0/EfficientNetB0_Ensemble_Model1_best.pth",
map_location="cpu")
model = create_efficientnet(num_classes=1) # see EfficientNetB0/README.md
model.load_state_dict(ckpt["model_state_dict"])
model.eval()
print(ckpt["epoch"], ckpt["val_acc"])
Ensemble inference
For the full 24-model ensemble, average the sigmoid outputs of all loaded members (optionally restrict to a subset of families):
import torch
probs = torch.stack([m(x) for m in all_24_models]) # each m(x) -> (B,)
p_real = probs.mean(dim=0)
Training details (shared)
- Optimizer: AdamW, cosine-annealing-with-warm-restarts schedule.
- Per-member seeded
WeightedRandomSamplerfor class balance and ensemble diversity across the 4 members of each family. - No data augmentation β tensors are cached in RAM at dataset load time.
TRAIN_EPOCHS = 15(CNN families),DEIT_TRAIN_EPOCHS = 30(DeiTTiny).- Early stopping on best validation balanced accuracy; checkpoint saved on every new best.
Training/evaluation code: training_script.py, evaluate_injection_pipeline.py
(Roman SN PIT pipeline repository β not included here).
Citation
If you use these models, please cite the Roman SN PIT project. Citation details to be added.