AM Não Supervisionado
AM Não Supervisionado
Detecção de Anomalias : Isolation Forest, One-Class SVM, DBSCAN, Autoencoders, LSTM
O que é detecção de anomalias
Detecção de anomalias é uma técnica não supervisionada. Primeiramente, ela identifica padrões raros ou diferentes nos dados. Por exemplo, transações fraudulentas em cartões de crédito. Geralmente, essas anomalias são muito diferentes da maioria. Inicialmente, o modelo aprende o comportamento normal. Em seguida, ele sinaliza pontos que fogem desse padrão. Diferentemente da classificação, não há exemplos de anomalias. Além disso, os dados normais são abundantes e as anomalias são raras. Cinco modelos principais são usados para essa tarefa. São eles: Isolation Forest, One-Class SVM, DBSCAN, Autoencoders e LSTM. Cada um tem uma arquitetura e vantagens específicas. Por essa razão, é fundamental conhecê-los bem.
Esses modelos podem ser aplicados em diversas áreas. Por exemplo, detecção de falhas em máquinas industriais. Outro exemplo é monitoramento de redes de computadores. Além disso, eles são usados na saúde para diagnósticos raros. Contudo, a escolha do modelo depende do tipo de dado. Dados tabulares funcionam bem com Isolation Forest. Por outro lado, dados sequenciais (séries temporais) usam LSTM. Da mesma forma, imagens frequentemente utilizam Autoencoders. Por conseguinte, é importante conhecer cada abordagem. Assim, este guia explora os cinco modelos principais. Portanto, continue lendo para entender as diferenças.
Arquitetura dos modelos
O Isolation Forest isola anomalias por meio de divisões aleatórias. Primeiramente, ele constrói árvores de decisão onde anomalias são isoladas rapidamente. Quanto mais curto o caminho na árvore, mais anômala é a amostra. Essa arquitetura é eficiente e escalável para grandes dados. O One-Class SVM aprende uma fronteira ao redor dos dados normais. Em seguida, ele mapeia os dados para um espaço de características. Pontos fora dessa fronteira são considerados anomalias. O kernel RBF é frequentemente usado nesse modelo. A fórmula do One-Class SVM minimiza: \(\min_{w,\xi,\rho} \frac{1}{2}||w||^2 + \frac{1}{\nu N}\sum \xi_i – \rho\). O DBSCAN agrupa pontos densos e marca isolados como anomalias. Além disso, ele não precisa do número de clusters antecipadamente. Pontos em regiões de baixa densidade são anomalias. Autoencoders usam redes neurais para reconstruir dados. Anomalias têm erro de reconstrução alto porque são raras. O codificador comprime e o decodificador reconstrói a entrada. LSTM é ideal para séries temporais e sequências. Primeiramente, ele aprende padrões temporais normais ao longo do tempo. Desvios desses padrões indicam anomalias na sequência. Portanto, cada modelo tem seu domínio de aplicação.
Hiperparâmetros e fórmulas matemáticas
Cada modelo tem hiperparâmetros específicos importantes. No Isolation Forest, o número de árvores é o principal. Além disso, a contaminação esperada também deve ser informada. Para One-Class SVM, o parâmetro nu é crucial. Ele define o limite superior da fração de anomalias. O kernel e seu coeficiente gamma afetam a suavidade. No DBSCAN, eps é o raio da vizinhança. Da mesma forma, min_samples é o número mínimo de pontos para formar cluster. Autoencoders têm taxa de aprendizado e número de camadas. A perda de reconstrução é calculada como: \(L = \frac{1}{N}\sum_{i=1}^{N} ||x_i – \hat{x}_i||^2\). LSTM possui número de unidades, camadas e dropout. O tamanho da janela temporal é outro hiperparâmetro. Um limiar de anomalia é definido após o treinamento. Geralmente, esse limiar é frequentemente um percentil do erro. A escolha dos hiperparâmetros é feita por validação. Dados rotulados (quando disponíveis) ajudam na calibração. Por fim, todos esses parâmetros precisam de ajuste cuidadoso.
Enunciado do exemplo clássico (dados sintéticos)
Você recebeu dados sintéticos com 95% de pontos normais. Primeiramente, os 5% restantes são anomalias inseridas manualmente. Seu objetivo é detectar essas anomalias usando três modelos. Use Isolation Forest, One-Class SVM e DBSCAN. Em seguida, compare os resultados com os rótulos verdadeiros. Calcule a precisão, recall e F1-score de cada modelo. Além disso, exiba um gráfico de dispersão mostrando os pontos. Pinte os pontos normais e as anomalias detectadas. O código abaixo resolve este enunciado completamente. Ele roda no Google Colab sem necessidade de ajustes. Portanto, boa prática! A detecção de anomalias é muito útil.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
import numpy as np import matplotlib.pyplot as plt from sklearn.ensemble import IsolationForest from sklearn.svm import OneClassSVM from sklearn.cluster import DBSCAN from sklearn.metrics import classification_report, accuracy_score, f1_score from sklearn.preprocessing import StandardScaler # Gera dados sintéticos com anomalias np.random.seed(42) n_normais = 950 n_anomalias = 50 # Dados normais: distribuição normal ao redor de (0,0) normais = np.random.randn(n_normais, 2) * 0.5 # Anomalias: distribuição uniforme em região distante anomalias = np.random.uniform(low=-3, high=3, size=(n_anomalias, 2)) # Garante que anomalias fiquem longe dos normais anomalias = anomalias * 2 # Combina os dados X = np.vstack([normais, anomalias]) y_true = np.array([0]*n_normais + [1]*n_anomalias) # 0=normal, 1=anomalia # Normalização scaler = StandardScaler() X_scaled = scaler.fit_transform(X) print("=" * 60) print("Dados sintéticos gerados:") print("=" * 60) print(f"Pontos normais: {n_normais}") print(f"Anomalias: {n_anomalias}") print(f"Total: {len(X)} pontos") # 1. Isolation Forest print("\n" + "=" * 60) print("1. Isolation Forest") print("=" * 60) iso_forest = IsolationForest(contamination=0.05, random_state=42, n_estimators=100) y_pred_if = iso_forest.fit_predict(X_scaled) y_pred_if = np.where(y_pred_if == -1, 1, 0) # -1 = anomalia, 1 = normal => inverte print(classification_report(y_true, y_pred_if, target_names=['Normal', 'Anomalia'])) # 2. One-Class SVM print("\n" + "=" * 60) print("2. One-Class SVM") print("=" * 60) oc_svm = OneClassSVM(nu=0.05, kernel='rbf', gamma='auto') y_pred_svm = oc_svm.fit_predict(X_scaled) y_pred_svm = np.where(y_pred_svm == -1, 1, 0) print(classification_report(y_true, y_pred_svm, target_names=['Normal', 'Anomalia'])) # 3. DBSCAN print("\n" + "=" * 60) print("3. DBSCAN") print("=" * 60) dbscan = DBSCAN(eps=0.3, min_samples=10) y_pred_db = dbscan.fit_predict(X_scaled) y_pred_db = np.where(y_pred_db == -1, 1, 0) # -1 = ruído (anomalia) print(classification_report(y_true, y_pred_db, target_names=['Normal', 'Anomalia'])) # Gráfico 1: Comparação visual dos resultados fig, axes = plt.subplots(2, 2, figsize=(12, 10)) cores = {0: 'blue', 1: 'red'} labels = {0: 'Normal', 1: 'Anomalia'} # Dados reais ax = axes[0, 0] for classe in [0, 1]: mask = y_true == classe ax.scatter(X[mask, 0], X[mask, 1], c=cores[classe], label=labels[classe], alpha=0.6, s=30) ax.set_title('Verdadeiro (dados originais)') ax.legend() ax.grid(True, alpha=0.3) # Isolation Forest ax = axes[0, 1] for classe in [0, 1]: mask = y_pred_if == classe ax.scatter(X[mask, 0], X[mask, 1], c=cores[classe], label=labels[classe], alpha=0.6, s=30) ax.set_title('Isolation Forest') ax.legend() ax.grid(True, alpha=0.3) # One-Class SVM ax = axes[1, 0] for classe in [0, 1]: mask = y_pred_svm == classe ax.scatter(X[mask, 0], X[mask, 1], c=cores[classe], label=labels[classe], alpha=0.6, s=30) ax.set_title('One-Class SVM') ax.legend() ax.grid(True, alpha=0.3) # DBSCAN ax = axes[1, 1] for classe in [0, 1]: mask = y_pred_db == classe ax.scatter(X[mask, 0], X[mask, 1], c=cores[classe], label=labels[classe], alpha=0.6, s=30) ax.set_title('DBSCAN') ax.legend() ax.grid(True, alpha=0.3) plt.suptitle('Comparação de modelos de detecção de anomalias', fontsize=14) plt.tight_layout() plt.show() # Gráfico 2: Comparação de F1-Score modelos = ['Isolation Forest', 'One-Class SVM', 'DBSCAN'] f1_scores = [ f1_score(y_true, y_pred_if), f1_score(y_true, y_pred_svm), f1_score(y_true, y_pred_db) ] plt.figure(figsize=(8, 5)) cores_barra = ['#1f77b4', '#ff7f0e', '#2ca02c'] barras = plt.bar(modelos, f1_scores, color=cores_barra, edgecolor='black') plt.ylim(0, 1) plt.ylabel('F1-Score') plt.title('Desempenho dos modelos na detecção de anomalias') for bar, score in zip(barras, f1_scores): plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.02, f'{score:.3f}', ha='center', va='bottom', fontsize=11) plt.grid(axis='y', linestyle='--', alpha=0.3) plt.tight_layout() plt.show() # Análise final print("\n" + "=" * 60) print("Análise dos resultados:") print("=" * 60) melhor_modelo = modelos[np.argmax(f1_scores)] print(f"Melhor modelo: {melhor_modelo} com F1-Score = {max(f1_scores):.3f}") print("\nObservações:") print("- Isolation Forest é rápido e eficaz para dados tabulares.") print("- One-Class SVM funciona bem, mas é mais sensível a outliers.") print("- DBSCAN detecta anomalias como pontos não pertencentes a clusters.") print("- Para dados reais, ajuste os hiperparâmetros cuidadosamente.") |
Esse código compara três modelos de detecção de anomalias. Primeiramente, os dados sintéticos têm 5% de anomalias espalhadas. O Isolation Forest apresenta bom desempenho geral. O One-Class SVM também detecta bem as anomalias. Além disso, o DBSCAN marca pontos isolados como anomalias. O gráfico de dispersão mostra a distribuição dos pontos. Em seguida, o gráfico de barras compara os F1-scores obtidos. Para séries temporais, use LSTM ou Autoencoders. Contudo, Autoencoders exigem mais dados para treinamento. Portanto, a detecção de anomalias é essencial em segurança e finanças. Parabéns por identificar padrões raros nos dados!
`