
Forschungscode zur Implementierung von T-Backdoor, zeitlich ausgelösten Backdoor-Angriffen auf spiking neuronale Netze unter Verwendung von Rate-, Latenz- und Jitter-Triggern ohne räumliche Perturbation.
Backdoor-Angriffe stellen eine ernsthafte Sicherheitsbedrohung für tiefe neuronale Netze (DNNs) dar und sind für spikende neuronale Netze (SNNs) weitgehend unerforscht. Bestehende Angriffe führen hauptsächlich raumzeitliche Trigger ein, die Abweichungen in der Spike-Verteilung vergifteter Proben gegenüber ihren sauberen Gegenstücken hervorrufen. Um diese Einschränkung zu adressieren, schlägt diese Arbeit einen neuartigen Backdoor-Angriff auf SNNs vor, genannt \textbf{T-Backdoor}, der ausschließlich mit zeitlichen Triggern wie \textit{Rate}, \textit{Latency} und \textit{Jitter} arbeitet, ohne jegliche räumliche Störung einzuführen, wodurch die Verschiebung der Spike-Verteilungen deutlich schwerer zu erkennen ist. Durch umfangreiche Experimente auf drei Benchmark-Neuromorphik-Datensätzen: N-MNIST, CIFAR10-DVS und N-Caltech101, sowie Evaluierung gegen sieben Baseline-Backdoor-Abwehrverfahren zeigen wir, dass T-Backdoor eine nahezu perfekte Angriffserfolgsrate (ASR) von 100% sowohl in Single-Target- als auch in Multi-Target-Szenarien erreicht, mit nur geringfügiger Verschlechterung der sauberen Genauigkeit, während es robust gegenüber bestehenden Backdoor-Erkennungs- und -Abschwächungstechniken bleibt.
├── models.py # Architectures for all datasets (shared)
├── datasets.py # Neuromorphic dataset loading (shared)
│
├── main_single.py # 1. Single-target entry point
├── single_poisoned_dataset.py # Trigger implementations + loaders
├── single_utils.py # Train/eval loop, saving, plots
├── single_target.sh # Paper runs
│
├── main_multi_target.py # 2. Multi-target entry point
├── multi_target_poisoned_dataset.py # Per-target parameter assignment
├── multi_target_utils.py # Per-target ASR tracking, saving
├── multi_target.sh # Paper runs
│
├── main_mtmt.py # 3. Multi-trigger multi-target entry point
├── mtmt_poisoned_dataset.py # Per-target trigger-type config
├── mtmt_utils.py # Per-target ASR tracking, saving
└── mtmt.sh # Paper runs
python -m venv venv
source venv/bin/activate
pip install torch torchvision # CUDA build matching your driver
pip install spikingjelly
pip install numpy scipy matplotlib seaborn tqdm
Referenzumgebung, die für die berichteten Ergebnisse verwendet wurde:
Laden Sie die rohen neuromorphen Datensätze herunter und platzieren Sie jeden in einem eigenen Unterverzeichnis von
data/, genau benannt wie der --dataset-Wert:
data/
├── mnist/ # N-MNIST
├── cifar10/ # CIFAR10-DVS
├── caltech/ # N-Caltech101
└── gesture/ # DVS128-Gesture
data/ muss ein wörtliches Verzeichnis in Ihrem Arbeitsverzeichnis seinmain_single.py)Ein Trigger, eine Zielklasse.
python main_single.py --dataset cifar10 --type latency --delay_frames 1 \
--T 10 --epochs 100 --epsilon 0.1 --data_dir 'data/'
Kernargumente
Triggerspezifische Argumente
Das Setzen von --epsilon 0.0 trainiert ein sauberes Baseline-Modell.
main_multi_target.py)Ein Trigger-Typ, N Zielklassen getrennt durch den Parameterwert des Triggers.
# Latency: delay 1 -> class 0, delay 3 -> class 1, delay 5 -> class 2
python main_multi_target.py --dataset mnist --type latency --n_targets 3 \
--trigger_labels 0 1 2 --delay_params 1 3 5 \
--epsilon 0.2 --T 10 --epochs 10 --data_dir 'data/'
Pro-Ziel-Parameter. Geben Sie sie explizit an, oder lassen Sie sie automatisch durch
np.linspace über einen Bereich zuweisen. Explizite Listen müssen die Länge --n_targets haben und überschreiben
die Bereichsargumente.
Automatisch zugewiesene ganzzahlige Parameter (latency, jitter_fixed) werden durch
Inkrementieren von Kollisionen dedupliziert, sodass keine zwei Ziele denselben Wert teilen.
Bei static werden die Ziele dadurch getrennt, welche Frames den Patch tragen — die Zeitachse
unterscheidet sie, nicht das Erscheinungsbild des Patches.
Die Pro-Ziel-ASR wird in jeder Epoche zusammen mit der sauberen Genauigkeit ausgegeben.
main_mtmt.py)Ein anderer Trigger-Typ pro Ziel.
python main_mtmt.py --dataset mnist --T 10 --n_targets 5 \
--target_types latency latency rate rate jitter_fixed \
--trigger_labels 0 1 2 3 4 \
--latency_delays 1 2 --rate_scales 0.5 2.0 --jitter_fixed_shifts 3 \
--epsilon 0.3 --epochs 100 --data_dir 'data/'
Pro-Typ-Parameterlisten. Jede Liste hat einen Eintrag pro Ziel dieses Typs — mit
--target_types latency latency rate rate jitter_fixed übergeben Sie zwei Delays, zwei Rates
und einen Shift:
Das Weglassen einer Liste führt zur automatischen Zuweisung aus dem passenden *_min / *_max-Bereich.
Integrierte Presets (verwendet, wenn --target_types nicht angegeben ist):
--n_targets 3 — static (Frames 0..T/3), latency (--delay), rate (--scale_factor)--n_targets 5 — zwei static (verschiedene Frame-Gruppen und Positionen), zwei latency
(--delay, --delay_2), ein rateJeder andere --n_targets-Wert erfordert --target_types.
Jeder Lauf schreibt eine Zeile in eine gemeinsame CSV sowie ein eigenständiges Experimentverzeichnis.
Trigger-Parameter werden in den Verzeichnisnamen kodiert (df1 = Delay 1, sf0.1 = Rate
0.1, ns3 = 3 Swaps), sodass Läufe, die sich nur in einem Trigger-Parameter unterscheiden, einander nicht überschreiben.
Teile dieser Codebasis sind aus dem Repository Sneaky Spikes von Gorka Abad et al. übernommen, das zum Paper "Sneaky Spikes: Uncovering Stealthy Backdoor Attacks in Spiking Neural Networks with Neuromorphic Data" (NDSS 2024) gehört. Wir danken den Autoren für die öffentliche Bereitstellung ihres Codes.
Wenn Sie diese Arbeit in Ihrer Forschung nützlich finden, ziehen Sie bitte in Betracht, sie zu zitieren:
@article{miah2026tbackdoor,
title = {T-Backdoor: Exploiting Temporal Redundancy in Neuromorphic Data for Spike-preserving Backdoor Attacks on SNNs},
author = {Miah, Abdullah Arafat and Vu, Kevin and Bi, Yu},
journal = {arXiv},
year = {2026}
}
Bei Fragen oder Problemen bezüglich des Codes öffnen Sie bitte ein GitHub-Issue oder kontaktieren Sie:
| Paket | Version |
|---|
| Python | 3.11.10 |
| torch | 2.11.0+cu128 |
| torchvision | 0.26.0+cu128 |
| numpy | 2.2.6 |
| scipy | 1.16.0 |
| matplotlib | 3.8.4 |
| seaborn | 0.13.2 |
| spikingjelly | latest from source |
| Argument | Standard | Beschreibung |
|---|
--dataset | gesture | mnist, cifar10, caltech, gesture |
--type | static | static, moving, smart, latency, rate, jitter, jitter_fixed |
--epsilon | 0.1 | Anteil des Trainingssatzes, der vergiftet wird |
--trigger_label | 0 | Zielklasse |
--T | 10 | Simulationszeitschritte |
--epochs | 10 | Trainingsepochen |
--batch_size | 16 | Batch-Größe |
--lr | 0.001 | Lernrate |
--loss | mse | mse oder cross |
--optim | adam | adam oder sgd |
--amp | aus | Automatische gemischte Präzision aktivieren |
--seed | 42 | Zufallsseed |
--data_dir | data/ | Datensatz-Wurzelverzeichnis |
--save_path | experiments_single | Ausgabe-Wurzelverzeichnis |
--model_path | None | Von einem vortrainierten Checkpoint starten |
| Argument | Standard | Gilt für |
|---|
--delay_frames | 2 | latency — Verzögerungsframes |
--scale_factor | 0.5 | rate — <1 langsamer, >1 schneller |
--n_shift | 3 | jitter_fixed — Anzahl der vertauschten Frame-Paare |
--trigger_size | 0.1 | static/moving/smart — Patch-Größe als Bruchteil der Breite |
--pos | top-left | static — top-left, top-right, bottom-left, bottom-right, middle, random |
--polarity | 3 | static/moving/smart — 0=schwarz, 1=dunkelblau, 2=grün, 3=hellblau |
--n_masks | 2 | smart — Anzahl der Kandidatenregionen |
--least | aus | smart — auf die am wenigsten aktive Region abzielen statt auf die aktivste |
--most_polarity | aus | smart — die aktivste Polarität in der Region verwenden |
| Argument | Standard | Beschreibung |
|---|
--type | rate | static, latency, rate, jitter, jitter_fixed |
--n_targets | 3 | Anzahl der Zielklassen |
--trigger_labels | [0..n-1] | Explizite Ziel-Labels; Länge muss gleich --n_targets sein |
--epsilon | 0.1 | Gesamt-Budget, gleichmäßig auf die Ziele aufgeteilt |
| Trigger | Explizit | Auto-Bereich | Auto-Standard |
|---|
latency | --delay_params 1 3 5 | --delay_min, --delay_max | 1 … T//2 |
rate | --rate_params 0.3 0.6 0.9 | --rate_min, --rate_max | 0.1 … 6.0 |
jitter | --jitter_params 0.05 0.15 0.25 | --jitter_std_min, --jitter_std_max | 0.05 … 0.3 |
jitter_fixed | --nshift_params 1 3 5 | --n_shift_min, --n_shift_max | 1 … max(n_shift_min+1, T//4) |
static | — | — | T aufgeteilt in n_targets Frame-Gruppen |
| Argument | Standard | Beschreibung |
|---|
--n_targets | 3 | Anzahl der Ziele; 3 und 5 haben integrierte Presets |
--target_types | None | Trigger-Typ pro Ziel — static, latency, rate, jitter, jitter_fixed. Länge muss gleich --n_targets sein. Überschreibt die Presets |
--trigger_labels | [0..n-1] | Ziel-Labels |
--epsilon | 0.2 | Gesamt-Budget, gleichmäßig auf die Ziele aufgeteilt |
| Argument | Gilt für |
|---|
--latency_delays 1 2 | jedes latency-Ziel |
--rate_scales 0.5 2.0 | jedes rate-Ziel |
--jitter_fixed_shifts 3 | jedes jitter_fixed-Ziel |
--jitter_stds 0.1 0.3 | jedes jitter-Ziel |
--static_positions top-left bottom-right | jedes static-Ziel |
--static_polarities 3 1 | jedes static-Ziel |
| Einstellung | Zusammenfassungs-CSV | Experimentverzeichnis |
|---|
| Single | <save_path>/results.csv | <dataset>_<type>_<eps>_<size>_<param>_<seed>/ |
| Multi-Target | <save_path>/multi_target_results.csv | multi_<type>_<dataset>_<n>targets_<labels>_eps<eps>_<params>_seed<seed>/ |
| MTMT | <save_path>/mtmt_results.csv | mtmt_<dataset>_<n>t_<params>_eps<eps>_seed<seed>/ |