
Código de pesquisa que implementa o T-Backdoor, ataques de backdoor com gatilho temporal em redes neurais spiking usando gatilhos de taxa, latência e jitter sem perturbação espacial.
Ataques backdoor são uma séria ameaça à segurança de redes neurais profundas (DNNs) e permanecem amplamente pouco explorados para redes neurais de spikes (SNNs). Os ataques existentes introduzem principalmente gatilhos espaço-temporais que induzem desvios na distribuição de spikes de amostras envenenadas em relação às suas contrapartes limpas. Para abordar essa limitação, este trabalho propõe um novo ataque backdoor em SNNs, denominado \textbf{T-Backdoor}, que opera usando gatilhos puramente temporais, como \textit{Rate}, \textit{Latency} e \textit{Jitter}, sem introduzir qualquer perturbação espacial, tornando a mudança nas distribuições de spikes significativamente mais difícil de detectar. Por meio de experimentos extensivos em três conjuntos de dados neuromórficos de referência: N-MNIST, CIFAR10-DVS e N-Caltech101, e avaliação contra sete métodos de defesa backdoor de linha de base, demonstramos que o T-Backdoor alcança uma taxa de sucesso de ataque (ASR) quase perfeita de 100% tanto em configurações de alvo único quanto de múltiplos alvos, com apenas uma degradação menor na acurácia limpa, permanecendo robusto contra técnicas existentes de detecção e mitigação de 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 de referência usado para os resultados reportados:
| Pacote | Versão |
|---|---|
| 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 |
Baixe os conjuntos de dados neuromórficos brutos e coloque cada um em seu próprio subdiretório de
data/, nomeado exatamente como o valor de --dataset:
data/
├── mnist/ # N-MNIST
├── cifar10/ # CIFAR10-DVS
├── caltech/ # N-Caltech101
└── gesture/ # DVS128-Gesture
data/ deve ser um diretório literal no seu diretório de trabalhomain_single.py)Um gatilho, uma classe alvo.
python main_single.py --dataset cifar10 --type latency --delay_frames 1 \
--T 10 --epochs 100 --epsilon 0.1 --data_dir 'data/'
Argumentos principais
| Argumento | Padrão | Descrição |
|---|---|---|
--dataset | gesture | mnist, cifar10, caltech, gesture |
--type | static | static, moving, smart, latency, rate, jitter, jitter_fixed |
--epsilon | 0.1 | Fração do conjunto de treinamento a envenenar |
--trigger_label | 0 | Classe alvo |
--T | 10 | Passos de tempo da simulação |
--epochs | 10 | Épocas de treinamento |
--batch_size | 16 | Tamanho do lote |
--lr | 0.001 | Taxa de aprendizado |
--loss | mse | mse ou cross |
--optim | adam | adam ou sgd |
--amp | off | Habilita precisão mista automática |
--seed | 42 | Semente aleatória |
--data_dir | data/ | Raiz do conjunto de dados |
--save_path | experiments_single | Raiz de saída |
--model_path | None | Iniciar a partir de um checkpoint pré-treinado |
Argumentos específicos do gatilho
| Argumento | Padrão | Aplica-se a |
|---|---|---|
--delay_frames | 2 | latency — quadros de atraso |
--scale_factor | 0.5 | rate — <1 mais lento, >1 mais rápido |
--n_shift | 3 | jitter_fixed — número de pares de quadros trocados |
--trigger_size | 0.1 | static/moving/smart — tamanho do patch como fração da largura |
--pos | top-left | static — top-left, top-right, bottom-left, bottom-right, middle, random |
--polarity | 3 | static/moving/smart — 0=preto, 1=azul escuro, 2=verde, 3=azul claro |
--n_masks | 2 | smart — número de regiões candidatas |
--least | off | smart — direcionar a região menos ativa em vez da mais ativa |
--most_polarity | off | smart — usar a polaridade mais ativa na região |
Definir --epsilon 0.0 treina um modelo de linha de base limpo.
main_multi_target.py)Um tipo de gatilho, N classes alvo separadas pelo valor do parâmetro do gatilho.
# 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/'
| Argumento | Padrão | Descrição |
|---|---|---|
--type | rate | static, latency, rate, jitter, jitter_fixed |
--n_targets | 3 | Número de classes alvo |
--trigger_labels | [0..n-1] | Rótulos alvo explícitos; o comprimento deve ser igual a --n_targets |
--epsilon | 0.1 | Orçamento total, dividido igualmente entre os alvos |
Parâmetros por alvo. Forneça-os explicitamente, ou deixe que sejam atribuídos automaticamente por
np.linspace sobre um intervalo. Listas explícitas devem ter comprimento --n_targets e substituem
os argumentos de intervalo.
| Gatilho | Explícito | Intervalo automático | Padrão automático |
|---|---|---|---|
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 dividido em n_targets grupos de quadros |
Parâmetros inteiros atribuídos automaticamente (latency, jitter_fixed) são desduplicados
incrementando colisões, de modo que dois alvos não compartilham um valor.
Para static, os alvos são separados por quais quadros carregam o patch — o eixo temporal
os distingue, em vez da aparência do patch.
A ASR por alvo é impressa a cada época, juntamente com a acurácia limpa.
main_mtmt.py)Um tipo de gatilho diferente por alvo.
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/'