Code to reproduce the CIFAR-10 results in "Analytical Correction for Subsampling Bias in Drifting Models".
The drifting model needs the kernel-weighted centroid
over the full reference distribution. In a minibatch of
which has a pointwise
which has
DriftingABC/
├── README.md
├── requirements.txt
├── model.py # DriftDiT (DiT backbone with adaLN-Zero)
├── drifting.py # drifting field + ABC correction
├── feature_encoder.py # frozen DINOv2 multi-scale encoder
├── compute_fid.py # FID + Inception score
├── utils.py # EMA, scheduler, sample queue, checkpoint I/O
├── reproduce_cifar10.py # training entrypoint
├── sample.py # sampling / FID evaluation from a checkpoint
└── weights/
├── README.md
├── seed42_n8_abc.pt # ABC-corrected, n=8, seed 42 (4000 epochs)
└── seed42_n8_noabc.pt # Standard (uncorrected), n=8, seed 42
pip install -r requirements.txtDINOv2 weights are downloaded on first run via torch.hub (no manual fetch needed).
Note on DINOv2 /
torch.hub. The encoder pulls the latestfacebookresearch/dinov2repo fromtorch.hub. We tested with the repo state as of late 2025 (DINOv2 ViT-S/14,hub APItorch.hub.load("facebookresearch/dinov2", "dinov2_vits14", ...)). If upstream renames or removes the entry point in the future, you may need to either (a) install a known-good commit manually and load it from a local checkpoint, or (b) replacefeature_encoder.pywith any frozen ViT-S/14-style encoder. The drifting loss only relies on multi-scale GAP features and is encoder-agnostic.
The flag that toggles ABC is --abc.
# Standard (uncorrected) baseline at n=8, 4000 epochs
python reproduce_cifar10.py \
--gpu 0 --seed 42 --n_pos 8 --n_neg 8 --epochs 4000 \
--output_dir runs/n8_noabc_s42
# ABC-corrected at n=8, same budget
python reproduce_cifar10.py \
--gpu 0 --seed 42 --n_pos 8 --n_neg 8 --epochs 4000 \
--abc --output_dir runs/n8_abc_s42The training log, checkpoints, and intermediate FID / generated samples are written under --output_dir.
We follow the protocol in the paper: total positive samples seen is held fixed across --n_pos, --n_neg, and --epochs together (we keep --n_neg = --n_pos = n in all paper experiments).
python sample.py \
--ckpt weights/seed42_n8_abc.pt \
--num_samples 50000 \
--output_dir samples/n8_abc_s42sample.py uses a fixed classifier-free-guidance strength
Two checkpoints (n=8, 4000 epochs each) are bundled in weights/:
| File | Method | FID | Epoch |
|---|---|---|---|
seed42_n8_noabc.pt |
Standard | 7.28 | 3799 |
seed42_n8_abc.pt |
ABC (ours) | 5.79 | 3399 |
Numbers are single-seed only. Multi-seed results in the paper appear in Table 1.
If you find this repository or our work helpful, please consider citing:
@inproceedings{zhang2026analytical,
title={Analytical Correction for Subsampling Bias in Drifting Models},
author={Zhang, Jiaru and Zeyun, Deng and Lu, Juanwu and Ziran, Wang and Ruqi, Zhang},
booktitle={NeurIPS},
year={2026}
}