
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:
| 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 |
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
| 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 |
Argomenti specifici del trigger
| 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 |
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/'
| 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 |
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.
| 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 |
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/'