Introdução
Este laboratório demonstra como usar o Scikit-Learn para realizar a detecção de valores discrepantes em conjuntos de dados clássicos de detecção de anomalias usando os algoritmos de fator de discrepância local (LOF) e floresta de isolamento (IForest). O desempenho dos algoritmos é avaliado em um contexto de detecção de valores discrepantes, e as curvas ROC são usadas para plotar os resultados.
Dicas da Máquina Virtual
Após o término da inicialização da máquina virtual, clique no canto superior esquerdo para mudar para a aba Notebook para acessar o Jupyter Notebook para praticar.
Às vezes, pode ser necessário aguardar alguns segundos para que o Jupyter Notebook termine de carregar. A validação das operações não pode ser automatizada devido a limitações no Jupyter Notebook.
Se você enfrentar problemas durante o aprendizado, sinta-se à vontade para perguntar ao Labby. Forneça feedback após a sessão, e nós resolveremos prontamente o problema para você.
Pré-processamento de Dados
O primeiro passo é pré-processar o conjunto de dados. Neste exemplo, usamos conjuntos de dados do mundo real disponíveis no módulo datasets do Scikit-Learn. O tamanho da amostra de alguns conjuntos de dados é reduzido para acelerar o cálculo. Após o pré-processamento dos dados, as metas dos conjuntos de dados terão duas classes, 0 representando valores internos e 1 representando valores discrepantes. A função preprocess_dataset retorna dados e metas.
import numpy as np
from sklearn.datasets import fetch_kddcup99, fetch_covtype, fetch_openml
from sklearn.preprocessing import LabelBinarizer
import pandas as pd
rng = np.random.RandomState(42)
def preprocess_dataset(dataset_name):
## carregamento e vetorização
print(f"Carregando dados de {dataset_name}")
if dataset_name in ["http", "smtp", "SA", "SF"]:
dataset = fetch_kddcup99(subset=dataset_name, percent10=True, random_state=rng)
X = dataset.data
y = dataset.target
lb = LabelBinarizer()
if dataset_name == "SF":
idx = rng.choice(X.shape[0], int(X.shape[0] * 0.1), replace=False)
X = X[idx] ## reduz o tamanho da amostra
y = y[idx]
x1 = lb.fit_transform(X[:, 1].astype(str))
X = np.c_[X[:, :1], x1, X[:, 2:]]
elif dataset_name == "SA":
idx = rng.choice(X.shape[0], int(X.shape[0] * 0.1), replace=False)
X = X[idx] ## reduz o tamanho da amostra
y = y[idx]
x1 = lb.fit_transform(X[:, 1].astype(str))
x2 = lb.fit_transform(X[:, 2].astype(str))
x3 = lb.fit_transform(X[:, 3].astype(str))
X = np.c_[X[:, :1], x1, x2, x3, X[:, 4:]]
y = (y != b"normal.").astype(int)
if dataset_name == "forestcover":
dataset = fetch_covtype()
X = dataset.data
y = dataset.target
idx = rng.choice(X.shape[0], int(X.shape[0] * 0.1), replace=False)
X = X[idx] ## reduz o tamanho da amostra
y = y[idx]
## valores internos são aqueles com atributo 2
## valores discrepantes são aqueles com atributo 4
s = (y == 2) + (y == 4)
X = X[s, :]
y = y[s]
y = (y != 2).astype(int)
if dataset_name in ["glass", "wdbc", "cardiotocography"]:
dataset = fetch_openml(
name=dataset_name, version=1, as_frame=False, parser="pandas"
)
X = dataset.data
y = dataset.target
if dataset_name == "glass":
s = y == "tableware"
y = s.astype(int)
if dataset_name == "wdbc":
s = y == "2"
y = s.astype(int)
X_mal, y_mal = X[s], y[s]
X_ben, y_ben = X[~s], y[~s]
## amostrado para baixo para 39 pontos (9,8% de valores discrepantes)
idx = rng.choice(y_mal.shape[0], 39, replace=False)
X_mal2 = X_mal[idx]
y_mal2 = y_mal[idx]
X = np.concatenate((X_ben, X_mal2), axis=0)
y = np.concatenate((y_ben, y_mal2), axis=0)
if dataset_name == "cardiotocography":
s = y == "3"
y = s.astype(int)
## 0 representa valores internos e 1 representa valores discrepantes
y = pd.Series(y, dtype="category")
return (X, y)
Função de Predição de Valores Discrepantes
O próximo passo é definir uma função de previsão de valores discrepantes. Neste exemplo, usamos os algoritmos LocalOutlierFactor e IsolationForest. A função compute_prediction retorna a pontuação média de valores discrepantes de X.
from sklearn.neighbors import LocalOutlierFactor
from sklearn.ensemble import IsolationForest
def compute_prediction(X, model_name):
print(f"Computando previsão de {model_name}...")
if model_name == "LOF":
clf = LocalOutlierFactor(n_neighbors=20, contamination="auto")
clf.fit(X)
y_pred = clf.negative_outlier_factor_
if model_name == "IForest":
clf = IsolationForest(random_state=rng, contamination="auto")
y_pred = clf.fit(X).decision_function(X)
return y_pred
Plotar e Interpretar Resultados
O passo final é plotar e interpretar os resultados. O desempenho do algoritmo está relacionado à qualidade da taxa de verdadeiros positivos (TPR) em valores baixos da taxa de falsos positivos (FPR). Os melhores algoritmos têm a curva no canto superior esquerdo do gráfico e a área sob a curva (AUC) próxima de 1. A linha tracejada diagonal representa uma classificação aleatória de valores discrepantes e valores internos.
import math
import matplotlib.pyplot as plt
from sklearn.metrics import RocCurveDisplay
datasets_name = [
"http",
"smtp",
"SA",
"SF",
"forestcover",
"glass",
"wdbc",
"cardiotocography",
]
models_name = [
"LOF",
"IForest",
]
## parâmetros de plotagem
cols = 2
linewidth = 1
pos_label = 0 ## significa que 0 pertence à classe positiva
rows = math.ceil(len(datasets_name) / cols)
fig, axs = plt.subplots(rows, cols, figsize=(10, rows * 3), sharex=True, sharey=True)
for i, dataset_name in enumerate(datasets_name):
(X, y) = preprocess_dataset(dataset_name=dataset_name)
for model_idx, model_name in enumerate(models_name):
y_pred = compute_prediction(X, model_name=model_name)
display = RocCurveDisplay.from_predictions(
y,
y_pred,
pos_label=pos_label,
name=model_name,
linewidth=linewidth,
ax=axs[i // cols, i % cols],
plot_chance_level=(model_idx == len(models_name) - 1),
chance_level_kw={
"linewidth": linewidth,
"linestyle": ":",
},
)
axs[i // cols, i % cols].set_title(dataset_name)
plt.tight_layout(pad=2.0) ## espaçamento entre os subgráficos
plt.show()
Resumo
Este laboratório demonstrou como usar o Scikit-Learn para realizar a detecção de valores discrepantes em conjuntos de dados clássicos de detecção de anomalias utilizando os algoritmos de fator de valor discrepante local (LOF) e floresta de isolamento (IForest). O desempenho dos algoritmos foi avaliado no contexto de detecção de valores discrepantes, e curvas ROC foram usadas para plotar os resultados.