Ausreißererkennung mit Scikit-Learn-Algorithmen

Machine LearningMachine LearningBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab wird gezeigt, wie man mit Scikit-Learn die Ausreißererkennung auf klassischen Anomalieerkennungsdatenmengen mit den Algorithmen Local Outlier Factor (LOF) und Isolation Forest (IForest) durchführt. Die Leistung der Algorithmen wird in einem Ausreißererkennungs-Kontext bewertet, und ROC-Kurven werden verwendet, um die Ergebnisse darzustellen.

Tipps für die VM

Nachdem der VM-Start abgeschlossen ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu nutzen.

Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund von Einschränkungen in Jupyter Notebook nicht automatisiert werden.

Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/neighbors("Nearest Neighbors") sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/ensemble("Ensemble Methods") sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/preprocessing("Preprocessing and Normalization") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/metrics("Metrics") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/neighbors -.-> lab-49236{{"Ausreißererkennung mit Scikit-Learn-Algorithmen"}} sklearn/ensemble -.-> lab-49236{{"Ausreißererkennung mit Scikit-Learn-Algorithmen"}} sklearn/preprocessing -.-> lab-49236{{"Ausreißererkennung mit Scikit-Learn-Algorithmen"}} sklearn/metrics -.-> lab-49236{{"Ausreißererkennung mit Scikit-Learn-Algorithmen"}} sklearn/datasets -.-> lab-49236{{"Ausreißererkennung mit Scikit-Learn-Algorithmen"}} ml/sklearn -.-> lab-49236{{"Ausreißererkennung mit Scikit-Learn-Algorithmen"}} end

Datenaufbereitung

Der erste Schritt besteht darin, die Datensatz aufzubereiten. In diesem Beispiel verwenden wir reale Datensätze aus dem datasets-Modul von Scikit-Learn. Die Stichprobengröße einiger Datensätze wird reduziert, um die Berechnung zu beschleunigen. Nach der Datenaufbereitung werden die Ziele der Datensätze zwei Klassen haben, wobei 0 für Inlier und 1 für Ausreißer steht. Die preprocess_dataset-Funktion gibt Daten und Ziel zurück.

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):
    ## Laden und Vektorisierung
    print(f"Lade {dataset_name} Daten")
    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]  ## Stichprobengröße reduzieren
            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]  ## Stichprobengröße reduzieren
            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]  ## Stichprobengröße reduzieren
        y = y[idx]

        ## Inlier sind die mit Attribut 2
        ## Ausreißer sind die mit Attribut 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]

            ## auf 39 Punkte abgesampelt (9,8% Ausreißer)
            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 repräsentiert Inlier, und 1 repräsentiert Ausreißer
    y = pd.Series(y, dtype="category")
    return (X, y)

Ausreißerprädiktionsfunktion

Der nächste Schritt besteht darin, eine Ausreißerprädiktionsfunktion zu definieren. In diesem Beispiel verwenden wir die Algorithmen LocalOutlierFactor und IsolationForest. Die compute_prediction-Funktion gibt den durchschnittlichen Ausreißerscore von X zurück.

from sklearn.neighbors import LocalOutlierFactor
from sklearn.ensemble import IsolationForest

def compute_prediction(X, model_name):
    print(f"Berechne {model_name} Vorhersage...")
    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

Ergebnisse plotten und interpretieren

Der letzte Schritt besteht darin, die Ergebnisse zu plotten und zu interpretieren. Die Algorithmusleistung hängt davon ab, wie gut die True-Positive-Rate (TPR) bei einem niedrigen Wert der False-Positive-Rate (FPR) ist. Die besten Algorithmen haben die Kurve in der oberen linken Ecke des Plots und die Fläche unter der Kurve (AUC) nahe bei 1. Die diagonale durchgezogene Linie repräsentiert eine zufällige Klassifizierung von Ausreißern und Inlierern.

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",
]

## Plotparameter
cols = 2
linewidth = 1
pos_label = 0  ## Mittelwert 0 gehört zur positiven Klasse
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)  ## Abstand zwischen den Teilplots
plt.show()

Zusammenfassung

In diesem Lab wurde gezeigt, wie man mit Scikit-Learn die Ausreißererkennung auf klassischen Anomalieerkennungsdatenmengen mit den Algorithmen Local Outlier Factor (LOF) und Isolation Forest (IForest) durchführt. Die Leistung der Algorithmen wurde in einem Ausreißererkennungs-Kontext bewertet, und ROC-Kurven wurden verwendet, um die Ergebnisse darzustellen.