Plotten der Klassifizierungswahrscheinlichkeit#

Dieses Beispiel illustriert die Verwendung von sklearn.inspection.DecisionBoundaryDisplay zum Plotten der vorhergesagten Klassenwahrscheinlichkeiten verschiedener Klassifikatoren in einem 2D-Merkmalsraum, hauptsächlich zu didaktischen Zwecken.

Die ersten drei Spalten zeigen die vorhergesagte Wahrscheinlichkeit für verschiedene Werte der beiden Merkmale. Runde Markierungen stellen die Testdaten dar, die zu dieser Klasse vorhergesagt wurden.

In der letzten Spalte sind alle drei Klassen in jedem Plot dargestellt; die Klasse mit der höchsten vorhergesagten Wahrscheinlichkeit an jedem Punkt wird geplottet. Die runden Markierungen zeigen die Testdaten und sind nach ihrer wahren Beschriftung gefärbt.

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib import cm

from sklearn import datasets
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.gaussian_process.kernels import RBF
from sklearn.inspection import DecisionBoundaryDisplay
from sklearn.kernel_approximation import Nystroem
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, log_loss, roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import (
    KBinsDiscretizer,
    PolynomialFeatures,
    SplineTransformer,
)

Daten: 2D-Projektion des Iris-Datensatzes#

iris = datasets.load_iris()
X = iris.data[:, 0:2]  # we only take the first two features for visualization
y = iris.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.5, random_state=42
)

Probabilistische Klassifikatoren#

Wir werden die Entscheidungsgrenzen mehrerer Klassifikatoren plotten, die eine predict_proba Methode haben. Dies wird es uns ermöglichen, die Unsicherheit des Klassifikators in Regionen zu visualisieren, in denen er sich seiner Vorhersage nicht sicher ist.

classifiers = {
    "Logistic regression\n(C=0.01)": LogisticRegression(C=0.1),
    "Logistic regression\n(C=1)": LogisticRegression(C=100),
    "Gaussian Process": GaussianProcessClassifier(kernel=1.0 * RBF([1.0, 1.0])),
    "Logistic regression\n(RBF features)": make_pipeline(
        Nystroem(kernel="rbf", gamma=5e-1, n_components=50, random_state=1),
        LogisticRegression(C=10),
    ),
    "Gradient Boosting": HistGradientBoostingClassifier(),
    "Logistic regression\n(binned features)": make_pipeline(
        KBinsDiscretizer(n_bins=5, quantile_method="averaged_inverted_cdf"),
        PolynomialFeatures(interaction_only=True),
        LogisticRegression(C=10),
    ),
    "Logistic regression\n(spline features)": make_pipeline(
        SplineTransformer(n_knots=5),
        PolynomialFeatures(interaction_only=True),
        LogisticRegression(C=10),
    ),
}

Plotten der Entscheidungsgrenzen#

Für jeden Klassifikator plotten wir die Wahrscheinlichkeiten pro Klasse in den ersten drei Spalten und die Wahrscheinlichkeiten der wahrscheinlichsten Klasse in der letzten Spalte.

n_classifiers = len(classifiers)
scatter_kwargs = {
    "s": 25,
    "marker": "o",
    "linewidths": 0.8,
    "edgecolor": "k",
    "alpha": 0.7,
}
y_unique = np.unique(y)

# Ensure legend not cut off
mpl.rcParams["savefig.bbox"] = "tight"
fig, axes = plt.subplots(
    nrows=n_classifiers,
    ncols=len(iris.target_names) + 1,
    figsize=(4 * 2.2, n_classifiers * 2.2),
)
evaluation_results = []
levels = 100
for classifier_idx, (name, classifier) in enumerate(classifiers.items()):
    y_pred = classifier.fit(X_train, y_train).predict(X_test)
    y_pred_proba = classifier.predict_proba(X_test)
    accuracy_test = accuracy_score(y_test, y_pred)
    roc_auc_test = roc_auc_score(y_test, y_pred_proba, multi_class="ovr")
    log_loss_test = log_loss(y_test, y_pred_proba)
    evaluation_results.append(
        {
            "name": name.replace("\n", " "),
            "accuracy": accuracy_test,
            "roc_auc": roc_auc_test,
            "log_loss": log_loss_test,
        }
    )
    for label in y_unique:
        # plot the probability estimate provided by the classifier
        disp = DecisionBoundaryDisplay.from_estimator(
            classifier,
            X_train,
            response_method="predict_proba",
            class_of_interest=label,
            ax=axes[classifier_idx, label],
            vmin=0,
            vmax=1,
            cmap="Blues",
            levels=levels,
        )
        axes[classifier_idx, label].set_title(f"Class {label}")
        # plot data predicted to belong to given class
        mask_y_pred = y_pred == label
        axes[classifier_idx, label].scatter(
            X_test[mask_y_pred, 0], X_test[mask_y_pred, 1], c="w", **scatter_kwargs
        )

        axes[classifier_idx, label].set(xticks=(), yticks=())
    # add column that shows all classes by plotting class with max 'predict_proba'
    max_class_disp = DecisionBoundaryDisplay.from_estimator(
        classifier,
        X_train,
        response_method="predict_proba",
        class_of_interest=None,
        ax=axes[classifier_idx, len(y_unique)],
        vmin=0,
        vmax=1,
        levels=levels,
    )
    for label in y_unique:
        mask_label = y_test == label
        axes[classifier_idx, 3].scatter(
            X_test[mask_label, 0],
            X_test[mask_label, 1],
            c=max_class_disp.multiclass_colors_[[label], :],
            **scatter_kwargs,
        )

    axes[classifier_idx, 3].set(xticks=(), yticks=())
    axes[classifier_idx, 3].set_title("Max class")
    axes[classifier_idx, 0].set_ylabel(name)

# colorbar for single class plots
ax_single = fig.add_axes([0.15, 0.01, 0.5, 0.02])
plt.title("Probability")
_ = plt.colorbar(
    cm.ScalarMappable(norm=None, cmap=disp.surface_.cmap),
    cax=ax_single,
    orientation="horizontal",
)

# colorbars for max probability class column
max_class_cmaps = [s.cmap for s in max_class_disp.surface_]

for label in y_unique:
    ax_max = fig.add_axes([0.73, (0.06 - (label * 0.04)), 0.16, 0.015])
    plt.title(f"Probability class {label}", fontsize=10)
    _ = plt.colorbar(
        cm.ScalarMappable(norm=None, cmap=max_class_cmaps[label]),
        cax=ax_max,
        orientation="horizontal",
    )
    if label in (0, 1):
        ax_max.set(xticks=(), yticks=())
Class 0, Class 1, Class 2, Max class, Class 0, Class 1, Class 2, Max class, Class 0, Class 1, Class 2, Max class, Class 0, Class 1, Class 2, Max class, Class 0, Class 1, Class 2, Max class, Class 0, Class 1, Class 2, Max class, Class 0, Class 1, Class 2, Max class, Probability, Probability class 0, Probability class 1, Probability class 2

Quantitative Auswertung#

pd.DataFrame(evaluation_results).round(2)
Name Genauigkeit ROC-AUC log_loss
0 Logistische Regression (C=0.01) 0.83 0.92 0.71
1 Logistische Regression (C=1) 0.81 0.93 0.36
2 Gaußscher Prozess 0.80 0.93 0.54
3 Logistische Regression (RBF-Merkmale) 0.77 0.93 0.40
4 Gradient Boosting 0.83 0.92 0.40
5 Logistische Regression (binnierte Merkmale) 0.81 0.92 0.48
6 Logistische Regression (Spline-Merkmale) 0.79 0.92 0.42


Analyse#

Die beiden logistischen Regressionsmodelle, die auf den ursprünglichen Merkmalen trainiert wurden, zeigen erwartungsgemäß lineare Entscheidungsgrenzen. Für dieses spezielle Problem scheint dies nicht nachteilig zu sein, da beide Modelle im Vergleich zu den nichtlinearen Modellen, wenn sie quantitativ am Testdatensatz ausgewertet werden, wettbewerbsfähig sind. Wir können beobachten, dass die Höhe der Regularisierung die Modellkonfidenz beeinflusst: hellere Farben für das stark regularisierte Modell mit einem niedrigeren Wert von C. Die Regularisierung wirkt sich auch auf die Ausrichtung der Entscheidungsgrenze aus, was zu leicht unterschiedlichen ROC-AUC-Werten führt.

Der Log-Loss hingegen bewertet sowohl die Schärfe als auch die Kalibrierung und begünstigt infolgedessen stark das schwach regularisierte logistische Regressionsmodell, wahrscheinlich weil das stark regularisierte Modell unterkalibriert ist. Dies könnte durch die Betrachtung der Kalibrierungskurve unter Verwendung von sklearn.calibration.CalibrationDisplay bestätigt werden.

Das logistische Regressionsmodell mit RBF-Merkmalen hat eine „klumpige“ Entscheidungsgrenze, die im ursprünglichen Merkmalsraum nichtlinear ist und dem Entscheidungsrand des Gaußschen Prozessklassifikators, der so konfiguriert ist, dass er einen RBF-Kernel verwendet, sehr ähnlich ist.

Das logistische Regressionsmodell, das auf binnierte Merkmale mit Interaktionen trainiert wurde, hat eine Entscheidungsgrenze, die im ursprünglichen Merkmalsraum nichtlinear ist und dem Entscheidungsrand des Gradient Boosting-Klassifikators sehr ähnlich ist: Beide Modelle bevorzugen achsenparallele Entscheidungen, wenn sie in ungesehene Bereiche des Merkmalsraums extrapolieren.

Das logistische Regressionsmodell, das auf Spline-Merkmale mit Interaktionen trainiert wurde, weist ein ähnliches achsenparalleles Extrapolationsverhalten auf, aber eine glattere Entscheidungsgrenze im dichten Bereich des Merkmalsraums als die beiden vorherigen Modelle.

Zusammenfassend lässt sich sagen, dass es interessant ist zu beobachten, dass das Feature Engineering für logistische Regressionsmodelle verwendet werden kann, um einige der induktiven Vorurteile verschiedener nichtlinearer Modelle nachzuahmen. Für diesen speziellen Datensatz ist die Verwendung der rohen Merkmale jedoch ausreichend, um ein wettbewerbsfähiges Modell zu trainieren. Dies wäre bei anderen Datensätzen nicht unbedingt der Fall.

Gesamtlaufzeit des Skripts: (0 Minuten 2.401 Sekunden)

Verwandte Beispiele

Visualisierung der probabilistischen Vorhersagen eines VotingClassifier

Visualisierung der probabilistischen Vorhersagen eines VotingClassifier

Restricted Boltzmann Machine Merkmale für Ziffernklassifikation

Restricted Boltzmann Machine Merkmale für Ziffernklassifikation

Vergleich der Kalibrierung von Klassifikatoren

Vergleich der Kalibrierung von Klassifikatoren

Entscheidungsgrenzen von multinomialer und One-vs-Rest Logistischer Regression

Entscheidungsgrenzen von multinomialer und One-vs-Rest Logistischer Regression

Galerie generiert von Sphinx-Gallery