ICD plug-in
August 26, 2026 · View on GitHub
Use ICD (Intelligent Coarse Dropout) and AICD (Anti-ICD) inside a standard PyTorch loop — without BNNRTrainer, branch search, or the full BNNR dashboard.
When to use this
- You already have a custom
train()/fit()loop (Lightning hooks, research code, etc.). - You want XAI-guided augmentations on top of pytorch-grad-cam saliency maps.
- You do not need automatic augmentation search — you will pick ICD/AICD yourself.
For automatic branch search and reporting, use BNNRTrainer or bnnr analyze instead.
Install
pip install bnnr
bnnr depends on grad-cam>=1.5.4 (PyPI package grad-cam, import pytorch_grad_cam). No separate install is required for the default saliency path.
Requirements
-
Indexed batches — your
DataLoadermust yield(image, label, index)soXAICachecan key saliency maps per sample. This is not optional: without the index nothing can be persisted, so ICD and AICD recompute saliency for every batch of every epoch and the only visible symptom is that training is slow. BNNR warns once per run when it detects this. Wrap any(image, label)dataset withIndexedDataset(see also the minimal example):from torch.utils.data import DataLoader from bnnr import IndexedDataset train_loader = DataLoader(IndexedDataset(train_dataset), batch_size=64, shuffle=True) -
Images — tensors in
[0, 1]floatBCHW, or uint8 converted inside ICD. Do not apply ImageNetNormalizebefore ICD unless you convert back for saliency. -
target_layers— list ofnn.Modulelayers for Grad-CAM (typically the lastConv2dbefore the classifier).
Minimal loop
-
Build
modelandtarget_layers. -
Wrap the dataset with
IndexedDatasetso batches carry the sample index. -
Precompute saliency once per training run:
from bnnr.xai_cache import XAICache from bnnr.icd import ICD cache = XAICache("./xai_cache") cache.precompute_cache( model=model, train_loader=train_loader, target_layers=target_layers, n_samples=len(train_dataset), method="gradcam", # uses pytorch-grad-cam via BNNR ) -
Create augmentations:
icd = ICD(model=model, target_layers=target_layers, cache=cache, explainer="gradcam") aicd = AICD(model=model, target_layers=target_layers, cache=cache, explainer="gradcam") -
In each training step, apply on the batch (uint8
NHWCpath):aug_np = icd.apply_batch_with_labels(imgs_uint8, labels_np, sample_indices=idx_np)Or per image:
icd.set_label(int(label))thenicd.apply(image_uint8_hwc).
Runnable script: examples/classification/icd_plugin_minimal.py.
Saliency backends
method="gradcam" produces Grad-CAM (eigen-smoothed) via pytorch-grad-cam; method="opticam" (the default) produces Opti-CAM, which optimises a per-image combination of the target-layer activations so the masked input maximises the target-class confidence. Both live in src/bnnr/xai.py.
Citation
If you use ICD/AICD from BNNR in research, cite the method paper, BNNR software, and pytorch-grad-cam (saliency). Full BibTeX blocks: citation.md.
@article{walo2026icd,
author = {Walo, Mateusz},
title = {Intelligent Coarse Dropout and Anti-ICD: Saliency-Guided Masking Augmentation for Visual Classifiers},
year = {2026},
doi = {10.5281/zenodo.20581077},
url = {https://doi.org/10.5281/zenodo.20581077},
note = {Preprint},
publisher = {Zenodo}
}
@software{walo2026bnnr,
author = {Walo, Mateusz and Morzhak, Diana and Zydorczyk, Dominika and Saczuk, Zuzanna},
title = {{BNNR}: Bulletproof Neural Network Recipe},
year = {2026},
url = {https://github.com/bnnr-team/bnnr},
version = {0.4.14},
doi = {10.5281/zenodo.20581372},
license = {MIT}
}
Performance
| Approach | Cost |
|---|---|
XAICache.precompute_cache (recommended) | One forward + CAM pass per training sample before epochs |
| No cache | RuntimeWarning + online CAM every ICD call — very slow |
Precompute on a subset (n_samples=...) if you only need ICD on part of the dataset.
See also
- Grad-CAM → ICD bridge (raw
GradCAMvs BNNRICDon the same batch):examples/integrations/gradcam_to_icd_loop.py - Full trainer + branch search:
golden_path.md - Failure analysis without retraining:
analyze.md - Ecosystem integrations hub:
integrations.md
What this is not
- Not a replacement for pytorch-grad-cam — it consumes saliency to augment images.
- Not a guarantee of +X% accuracy — see benchmark protocol caveats in
benchmarks.md.