Introdução ao PyTorch na Prática: do Primeiro Neurônio à Detecção de Ataques Cibernéticos
Um guia prático que percorre os fundamentos do PyTorch — tensores, redes neurais, loops de treinamento e otimização — culminando em um projeto real de classificação de ameaças cibernéticas com o dataset BETH.
Aprender PyTorch do zero é uma jornada que combina teoria matemática, intuição sobre otimização e muita prática com código. Neste artigo, documento esse caminho — do primeiro tensor até um modelo treinado para detectar ataques cibernéticos em tráfego de rede — com os aprendizados reais e os erros que encontrei no caminho.
Por que PyTorch?
PyTorch é hoje a principal ferramenta de pesquisa e produção em Deep Learning. Sua filosofia de grafo computacional dinâmico (define-by-run) permite escrever código Python natural e depurar modelos como qualquer outro programa. Em contraste com abordagens estáticas, você vê o que acontece a cada passo — o que é essencial para aprender e experimentar.
Os principais conceitos que precisamos dominar são:
- Tensor: a unidade básica de dado (como um ndarray do NumPy, mas com suporte a GPU e gradientes).
- Autograd: o mecanismo de diferenciação automática que calcula gradientes para otimização.
- nn.Module: a abstração para construir camadas e modelos.
- Otimizador: o algoritmo que atualiza os pesos com base nos gradientes.
Parte 1: A Arquitetura de uma Rede Neural
Antes de treinar qualquer modelo, precisamos entender os três tipos de camadas fundamentais.
Camadas Lineares (Fully Connected)
Uma camada linear realiza a operação $\mathbf{y} = \mathbf{W}\mathbf{x} + \mathbf{b}$, onde $\mathbf{W}$ são os pesos aprendíveis e $\mathbf{b}$ o viés (bias). Em PyTorch:
import torch.nn as nn
layer = nn.Linear(in_features=4, out_features=2)
Funções de Ativação
Sem funções de ativação, empilhar camadas lineares é equivalente a uma única camada linear — o modelo não consegue aprender padrões não-lineares. As mais usadas são:
- ReLU (
nn.ReLU): $f(x) = \max(0, x)$ — simples e eficiente para camadas ocultas. - Sigmoid (
nn.Sigmoid): $f(x) = \frac{1}{1 + e^{-x}}$ — comprime a saída entre 0 e 1, ideal para classificação binária. - Softmax: usada na saída de modelos multiclasse.
Funções de Perda (Loss)
A função de perda mede o quão errado o modelo está. A escolha depende do problema:
| Problema | Saída do Modelo | Loss Correta |
|---|---|---|
| Regressão | Valor contínuo | nn.MSELoss |
| Classificação Binária (1 neurônio + Sigmoid) | Probabilidade [0,1] | nn.BCELoss ou nn.BCEWithLogitsLoss |
| Classificação Multiclasse | Logits brutos | nn.CrossEntropyLoss |
Armadilha comum: usar
nn.CrossEntropyLosscom uma saída de 1 neurônio +Sigmoidé incorreto. Esse foi um dos erros encontrados durante o projeto e causou resultados inconsistentes.
Parte 2: O Loop de Treinamento
O coração de qualquer treinamento em PyTorch é o loop de épocas. Cada iteração segue sempre a mesma sequência de 5 passos:
for epoch in range(num_epochs):
for xb, yb in dataloader:
# 1. Zerar gradientes acumulados
optimizer.zero_grad()
# 2. Forward pass: calcular predições
pred = model(xb)
# 3. Calcular a perda
loss = criterion(pred, yb)
# 4. Backward pass: calcular gradientes
loss.backward()
# 5. Atualizar pesos
optimizer.step()
Por que resetar os gradientes?
PyTorch acumula gradientes por padrão. Se você não chamar zero_grad() antes de cada batch, os gradientes da iteração anterior são somados aos atuais — corrompendo o aprendizado.
DataLoader e mini-batch
Treinar com todos os dados de uma vez (batch completo) é computacionalmente proibitivo e convergência instável para datasets grandes. O DataLoader divide o dataset em mini-batches e embaralha os dados a cada época:
from torch.utils.data import TensorDataset, DataLoader
dataset = TensorDataset(X_tensor, y_tensor)
loader = DataLoader(dataset, batch_size=256, shuffle=True)
Parte 3: Taxa de Aprendizado e Momentum
Dois hiperparâmetros que fazem enorme diferença na qualidade do treinamento.
Learning Rate (LR)
A taxa de aprendizado controla o tamanho de cada passo de atualização dos pesos. Podemos visualizar isso como uma bola descendo uma superfície de perda:
- LR muito alto: a bola salta de um lado para o outro e pode divergir.
- LR muito baixo: o aprendizado é lento e pode ficar preso em mínimos locais.
- LR ideal: desce suavemente em direção ao mínimo global.
Momentum
O momentum adiciona “inércia” ao otimizador: ele mantém uma fração da direção do passo anterior, permitindo que o modelo ganhe velocidade em direções consistentes e “pule” mínimos locais rasos.
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
Em termos práticos, um momentum=0.9 é um bom ponto de partida para a maioria dos problemas.
Para a maioria dos problemas modernos, o Adam é preferível ao SGD puro, pois adapta o LR individualmente por parâmetro, combinando o efeito de momentum e escalonamento adaptativo.
Parte 4: Projeto Real — Detecção de Ataques Cibernéticos
Com os fundamentos estabelecidos, a aplicação natural é um problema do mundo real. O dataset escolhido foi o BETH (Behaviour-Expected-Through-Heuristics), que simula logs de endpoint de ambientes corporativos reais.
O Problema
Cada linha representa um evento de sistema (processo, thread, chamada de sistema). O objetivo é classificar se o evento é suspeito (sus_label=1) ou benigno (sus_label=0).
| Coluna | Descrição |
|---|---|
processId | Identificador único do processo |
threadId | ID da thread geradora do log |
parentProcessId | Processo pai |
userId | ID do usuário |
mountNamespace | Restrições de namespace |
argsNum | Número de argumentos do evento |
returnValue | Valor de retorno (geralmente 0) |
sus_label | Target: 1 = suspeito, 0 = benigno |
Etapa 1: Pipeline de Dados
O pipeline de dados seguiu boas práticas essenciais para evitar data leakage:
from sklearn.preprocessing import StandardScaler
# Separar features e labels
X_train = train_df.drop('sus_label', axis=1).values
y_train = train_df['sus_label'].values
# Fit APENAS no treino
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
# Transform nos demais com os mesmos parâmetros
X_val = scaler.transform(X_val)
X_test = scaler.transform(X_test)
Por que só fazer
fitno treino?
Se calcularmos a média e desvio-padrão nos dados de validação/teste, estamos “vazando” informações futuras para o modelo. O scaler deve enxergar apenas o que o modelo enxerga em produção.
Etapa 2: Arquitetura do Modelo
Para classificação binária com BCEWithLogitsLoss (mais estável numericamente que BCELoss):
model = nn.Sequential(
nn.Linear(input_dim, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 1) # Sem Sigmoid aqui — BCEWithLogitsLoss aplica internamente
)
criterion = nn.BCEWithLogitsLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-4)
Etapa 3: Treinamento e Resultados
Epoch 01/30 | Loss: 0.0076 | Train Acc: 0.9997 | Val Acc: 1.0000
Epoch 10/30 | Loss: 0.0022 | Train Acc: 0.9997 | Val Acc: 1.0000
Epoch 30/30 | Loss: 0.0022 | Train Acc: 0.9997 | Val Acc: 1.0000
Final Train Acc: 0.9997
Final Val Acc: 1.0000
Final Test Acc: 0.0940
A meta acadêmica foi cumprida (val_accuracy >= 0.6). Mas os números escondem algo importante.
Parte 5: A Análise que Ninguém Conta
Acurácia de 99.97% no treino e 0% no teste não é sucesso — é um sinal de alerta crítico.
A Matriz de Confusão Revela Tudo
Test confusion matrix:
[[ 17508 0]
[171195 264]]
Test Precision: 1.0000 | Recall: 0.0015 | F1: 0.0031
O modelo classificou 171.195 eventos maliciosos como benignos e detectou apenas 264 de 171.459. Em termos práticos:
- Recall = 0.0015: o modelo “vê” apenas 0.15% dos ataques reais.
- Precision = 1.0: quando alerta, não erra — mas quase nunca alerta.
Isso é o pior cenário possível para um sistema de segurança.
Por que Acurácia Engana Aqui?
O dataset tem forte desbalanceamento de classes. Se 94% dos eventos são benignos, um modelo que sempre prevê benigno atinge 94% de acurácia sem aprender nada. O modelo aprendeu esse atalho.
O que Aprendemos com este Erro
| Métrica | O que Mede | Para Segurança |
|---|---|---|
| Acurácia | % de acertos geral | ❌ Enganosa em dados desbalanceados |
| Recall (Sensibilidade) | % de ataques detectados | ✅ Crítico — minimiza falsos negativos |
| Precision | % de alertas corretos | ✅ Importante — minimiza fadiga de alertas |
| F1-Score | Equilíbrio entre Recall e Precision | ✅ Métrica principal para este problema |
| PR-AUC | Área sob curva Precision-Recall | ✅ Melhor métrica global |
Impacto Operacional Real
Em um Security Operations Center (SOC), esse modelo falharia catastroficamente:
- Falso negativo (ataque não detectado): o atacante persiste no ambiente, move-se lateralmente e exfiltra dados sem bloqueio.
- Falso positivo (benigno marcado como ataque): analistas perdem tempo investigando falsos alarmes, gerando alert fatigue e potencialmente ignorando alertas reais.
Este projeto demonstrou que em cibersegurança — especialmente com dados desbalanceados — otimizar para acurácia é o caminho errado.
Lições Aprendidas
1. Pipeline antes de modelo
Inconsistências de preprocessing (ordem de colunas, escala, encoding) destroem modelos em produção. Validar o pipeline é mais importante que tunar hiperparâmetros.
2. A função de perda define o problema
CrossEntropyLoss vs BCEWithLogitsLoss vs BCELoss não são equivalentes. Escolher errado introduz erros silenciosos que aparecem só no teste.
3. Métricas orientadas ao negócio
Acurácia é genérica. Para detecção de ameaças, o KPI real é recall da classe maliciosa. Para detecção de fraude, é F1. A métrica deve refletir o custo real de cada tipo de erro.
4. Dados desbalanceados exigem estratégia específica
Soluções para explorar: pos_weight no BCEWithLogitsLoss, oversampling (SMOTE), undersampling, ou ajuste dinâmico de limiar de decisão.
5. Validação e teste devem ser representativos
Val perfeita + teste ruim é sempre sinal de problema de dados, não de modelo.
Próximos Passos
Para transformar este experimento em um detector confiável:
- Corrigir o desbalanceamento com
pos_weight = n_negativos / n_positivos. - Buscar o limiar ótimo via curva PR na validação, não fixar em 0.5.
- Monitorar drift — comportamento de ataques muda com o tempo.
- Avaliar com PR-AUC e F1 como métricas primárias.
- Re-treinar periodicamente com dados rotulados atualizados.
Conclusão
A jornada de introdução ao PyTorch revelou que dominar a biblioteca é apenas o começo. O verdadeiro desafio está em entender o problema, escolher as métricas certas e garantir que o pipeline de dados seja robusto do notebook até produção.
PyTorch oferece as ferramentas. A sabedoria sobre quando e como usá-las vem da prática — e dos erros que encontramos no caminho.
“Um modelo de 99% de acurácia que deixa passar 99.85% dos ataques não é um sistema de segurança — é uma falsa sensação de proteção.”
Referências e Leituras Complementares
Documentação Oficial PyTorch
-
PyTorch Documentation — Guia completo de API, tutoriais e exemplos oficiais.
https://pytorch.org/docs/stable/index.html -
PyTorch Tutorials: Learn the Basics — Introdução oficial cobrindo tensores, autograd, datasets e loops de treinamento.
https://pytorch.org/tutorials/beginner/basics/intro.html -
torch.nn — Neural Network Modules — Referência de todas as camadas, funções de ativação e losses.
https://pytorch.org/docs/stable/nn.html -
torch.optim — Optimization Algorithms — Documentação dos otimizadores SGD, Adam e parâmetros como
lr,momentumeweight_decay.
https://pytorch.org/docs/stable/optim.html
DataCamp
-
Introduction to Deep Learning with PyTorch — Curso que cobre os fundamentos de redes neurais, loops de treinamento e classificação com PyTorch.
https://www.datacamp.com/courses/introduction-to-deep-learning-with-pytorch -
Intermediate Deep Learning with PyTorch — Aprofundamento em arquiteturas, técnicas de regularização e boas práticas.
https://www.datacamp.com/courses/intermediate-deep-learning-with-pytorch -
Machine Learning for Cyber Security — Aplicação de modelos de ML para detecção de ameaças e anomalias em segurança.
https://www.datacamp.com/courses/machine-learning-for-cyber-security
Dataset
- BETH Dataset: Real Cybersecurity Data for Anomaly Detection Research — Paper e dataset originais usados neste projeto, com descrição do ambiente de coleta e estrutura dos logs.
Highnam, K. et al. (2021). BETH Dataset: Real Cybersecurity Data for Anomaly Detection Research. ICML Workshop: Uncertainty & Robustness in Deep Learning.
https://www.kaggle.com/datasets/katehighnam/beth-dataset
Referências Complementares
-
Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep Learning. MIT Press.
Referência fundamental em arquiteturas de redes neurais, funções de perda e otimização.
https://www.deeplearningbook.org -
Scikit-learn: StandardScaler — Documentação do escalonamento de features e por que fazer
fitapenas no treino.
https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html -
Towards Data Science: Handling Imbalanced Datasets in Deep Learning — Estratégias práticas para
pos_weight, SMOTE, undersampling e ajuste de limiar.
https://towardsdatascience.com/handling-imbalanced-datasets-in-deep-learning -
Google PAIR Guidebook — Guia sobre métricas de avaliação orientadas ao problema real, especialmente em contextos de segurança e detecção de anomalias.
https://pair.withgoogle.com/guidebook