
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:
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
Argumentos específicos do gatilho
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/'
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.
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/'
Listas de parâmetros por tipo. Cada lista tem uma entrada por alvo daquele tipo — com
--target_types latency latency rate rate jitter_fixed você passa dois atrasos, duas taxas
e uma troca:
Omitir uma lista atribui automaticamente a partir do intervalo correspondente *_min / *_max.
Presets integrados (usados quando --target_types não é fornecido):
--n_targets 3 — static (quadros 0..T/3), latency (--delay), rate (--scale_factor)--n_targets 5 — dois static (grupos de quadros e posições diferentes), dois latency
(--delay, --delay_2), um rateQualquer outro valor de --n_targets requer --target_types.
Cada execução grava uma linha em um CSV compartilhado, além de um diretório de experimento autocontido.
Os parâmetros do gatilho são codificados no nome do diretório (df1 = atraso 1, sf0.1 = taxa
0.1, ns3 = 3 trocas), de modo que execuções que diferem apenas em um parâmetro de gatilho não se
sobrescrevem.
Partes desta base de código são adaptadas do repositório Sneaky Spikes de Gorka Abad et al., que acompanha o artigo "Sneaky Spikes: Uncovering Stealthy Backdoor Attacks in Spiking Neural Networks with Neuromorphic Data" (NDSS 2024). Agradecemos aos autores por disponibilizarem publicamente seu código.
Se você achar este trabalho útil em sua pesquisa, considere citá-lo:
@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}
}
Para perguntas ou problemas relacionados ao código, abra uma issue no GitHub ou entre em contato:
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| Argumento | Padrão | Descrição |
|---|
--n_targets | 3 | Número de alvos; 3 e 5 têm presets integrados |
--target_types | None | Tipo de gatilho por alvo — static, latency, rate, jitter, jitter_fixed. O comprimento deve ser igual a --n_targets. Substitui os presets |
--trigger_labels | [0..n-1] | Rótulos alvo |
--epsilon | 0.2 | Orçamento total, dividido igualmente entre os alvos |
| Argumento | Aplica-se a |
|---|
--latency_delays 1 2 | cada alvo latency |
--rate_scales 0.5 2.0 | cada alvo rate |
--jitter_fixed_shifts 3 | cada alvo jitter_fixed |
--jitter_stds 0.1 0.3 | cada alvo jitter |
--static_positions top-left bottom-right | cada alvo static |
--static_polarities 3 1 | cada alvo static |
| Configuração | CSV de resumo | Diretório do experimento |
|---|
| Único | <save_path>/results.csv | <dataset>_<type>_<eps>_<size>_<param>_<seed>/ |
| Múltiplos alvos | <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>/ |