
Codice di ricerca che implementa T-Backdoor, attacchi backdoor con trigger temporale su reti neurali a impulsi utilizzando trigger di rate, latenza e jitter senza perturbazione spaziale.
Gli attacchi backdoor rappresentano una seria minaccia alla sicurezza delle reti neurali profonde (DNN) e rimangono in gran parte poco esplorati per le reti neurali a impulsi (SNN). Gli attacchi esistenti introducono principalmente trigger spazio-temporali che inducono deviazioni nella distribuzione degli spike dei campioni avvelenati rispetto alle loro controparti pulite. Per affrontare questo limite, questo lavoro propone un nuovo attacco backdoor sulle SNN, denominato \textbf{T-Backdoor}, che opera utilizzando trigger puramente temporali come \textit{Rate}, \textit{Latency} e \textit{Jitter} senza introdurre alcuna perturbazione spaziale, rendendo lo spostamento nelle distribuzioni degli spike significativamente più difficile da rilevare. Attraverso esperimenti estesi su tre dataset neuromorfici di riferimento: N-MNIST, CIFAR10-DVS e N-Caltech101, e valutazioni contro sette metodi di difesa backdoor di riferimento, dimostriamo che T-Backdoor raggiunge un tasso di successo dell'attacco (ASR) quasi perfetto del 100% sia in configurazioni a target singolo che multi-target con solo una lieve degradazione dell'accuratezza pulita, rimanendo al contempo robusto contro le tecniche esistenti di rilevamento e mitigazione delle backdoor.
├── 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
Ambiente di riferimento utilizzato per i risultati riportati:
Scarica i dataset neuromorfici grezzi e posiziona ciascuno nella propria sottodirectory di
data/, denominata esattamente come il valore di --dataset:
data/
├── mnist/ # N-MNIST
├── cifar10/ # CIFAR10-DVS
├── caltech/ # N-Caltech101
└── gesture/ # DVS128-Gesture
data/ deve essere una directory letterale nella tua directory di lavoromain_single.py)Un trigger, una classe target.
python main_single.py --dataset cifar10 --type latency --delay_frames 1 \
--T 10 --epochs 100 --epsilon 0.1 --data_dir 'data/'
Argomenti principali
Argomenti specifici del trigger
Impostando --epsilon 0.0 si addestra un modello baseline pulito.
main_multi_target.py)Un tipo di trigger, N classi target separate dal valore del parametro del trigger.
# 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/'
Parametri per target. Forniscili esplicitamente, oppure lascia che vengano assegnati automaticamente da
np.linspace su un intervallo. Le liste esplicite devono avere lunghezza --n_targets e sovrascrivono
gli argomenti di intervallo.
I parametri interi assegnati automaticamente (latency, jitter_fixed) vengono deduplicati
incrementando le collisioni, così due target non condividono mai un valore.
Per static, i target sono separati da quali frame portano la patch — l'asse temporale
li distingue piuttosto che l'aspetto della patch.
L'ASR per target viene stampato ogni epoca, insieme all'accuratezza pulita.
main_mtmt.py)Un tipo di trigger diverso per ogni target.
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/'
Liste di parametri per tipo. Ogni lista ha una voce per ogni target di quel tipo — con
--target_types latency latency rate rate jitter_fixed passi due delay, due rate
e uno shift:
Omettere una lista assegna automaticamente dall'intervallo corrispondente *_min / *_max.
Preset integrati (usati quando --target_types non è fornito):
--n_targets 3 — static (frame 0..T/3), latency (--delay), rate (--scale_factor)--n_targets 5 — due static (gruppi di frame e posizioni diversi), due latency
(--delay, --delay_2), un rateQualsiasi altro valore di --n_targets richiede --target_types.
Ogni esecuzione scrive una riga in un CSV condiviso più una directory di esperimento autocontenuta.
I parametri del trigger sono codificati nel nome della directory (df1 = delay 1, sf0.1 = rate
0.1, ns3 = 3 scambi), così le esecuzioni che differiscono solo per un parametro del trigger non si sovrascrivono
a vicenda.
Parti di questa codebase sono adattate dal repository Sneaky Spikes di Gorka Abad et al., che accompagna il paper "Sneaky Spikes: Uncovering Stealthy Backdoor Attacks in Spiking Neural Networks with Neuromorphic Data" (NDSS 2024). Ringraziamo gli autori per aver reso pubblicamente disponibile il loro codice.
Se ritieni utile questo lavoro nella tua ricerca, ti invitiamo a citarlo:
@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}
}
Per domande o problemi riguardanti il codice, apri una issue su GitHub o contatta:
| Pacchetto | Versione |
|---|
| 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 | ultima dal sorgente |
| Argomento | Default | Descrizione |
|---|
--dataset | gesture | mnist, cifar10, caltech, gesture |
--type | static | static, moving, smart, latency, rate, jitter, jitter_fixed |
--epsilon | 0.1 | Frazione del training set da avvelenare |
--trigger_label | 0 | Classe target |
--T | 10 | Passi temporali di simulazione |
--epochs | 10 | Epoche di addestramento |
--batch_size | 16 | Dimensione del batch |
--lr | 0.001 | Learning rate |
--loss | mse | mse o cross |
--optim | adam | adam o sgd |
--amp | off | Abilita la precisione mista automatica |
--seed | 42 | Seed casuale |
--data_dir | data/ | Root del dataset |
--save_path | experiments_single | Root di output |
--model_path | None | Parti da un checkpoint pre-addestrato |
| Argomento | Default | Si applica a |
|---|
--delay_frames | 2 | latency — frame di ritardo |
--scale_factor | 0.5 | rate — <1 più lento, >1 più veloce |
--n_shift | 3 | jitter_fixed — numero di coppie di frame scambiate |
--trigger_size | 0.1 | static/moving/smart — dimensione della patch come frazione della larghezza |
--pos | top-left | static — top-left, top-right, bottom-left, bottom-right, middle, random |
--polarity | 3 | static/moving/smart — 0=nero, 1=blu scuro, 2=verde, 3=azzurro |
--n_masks | 2 | smart — numero di regioni candidate |
--least | off | smart — prende di mira la regione meno attiva invece della più attiva |
--most_polarity | off | smart — usa la polarità più attiva nella regione |
| Argomento | Default | Descrizione |
|---|
--type | rate | static, latency, rate, jitter, jitter_fixed |
--n_targets | 3 | Numero di classi target |
--trigger_labels | [0..n-1] | Etichette target esplicite; la lunghezza deve essere uguale a --n_targets |
--epsilon | 0.1 | Budget totale, suddiviso equamente tra i target |
| Trigger | Esplicito | Intervallo automatico | Default automatico |
|---|
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 suddiviso in n_targets gruppi di frame |
| Argomento | Default | Descrizione |
|---|
--n_targets | 3 | Numero di target; 3 e 5 hanno preset integrati |
--target_types | None | Tipo di trigger per target — static, latency, rate, jitter, jitter_fixed. La lunghezza deve essere uguale a --n_targets. Sovrascrive i preset |
--trigger_labels | [0..n-1] | Etichette target |
--epsilon | 0.2 | Budget totale, suddiviso equamente tra i target |
| Argomento | Si applica a |
|---|
--latency_delays 1 2 | ogni target latency |
--rate_scales 0.5 2.0 | ogni target rate |
--jitter_fixed_shifts 3 | ogni target jitter_fixed |
--jitter_stds 0.1 0.3 | ogni target jitter |
--static_positions top-left bottom-right | ogni target static |
--static_polarities 3 1 | ogni target static |
| Impostazione | CSV di riepilogo | Directory dell'esperimento |
|---|
| 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>/ |