
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:
| 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 |
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
| 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 |
Triggerspezifische Argumente
| 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 |
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/'
| 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 |
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.
| 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 |
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/'