Release Highlights für scikit-learn 1.5#

Wir freuen uns, die Veröffentlichung von scikit-learn 1.5 bekannt zu geben! Viele Fehlerbehebungen und Verbesserungen wurden hinzugefügt, ebenso wie einige wichtige neue Funktionen. Im Folgenden stellen wir die Highlights dieser Version vor. Eine vollständige Liste aller Änderungen finden Sie in den Release Notes.

Um die neueste Version zu installieren (mit pip)

pip install --upgrade scikit-learn

oder mit conda

conda install -c conda-forge scikit-learn

FixedThresholdClassifier: Festlegen des Entscheidungsschwellenwerts eines binären Klassifikators#

Alle binären Klassifikatoren von scikit-learn verwenden einen festen Entscheidungsschwellenwert von 0,5, um Wahrscheinlichkeitsschätzungen (d. h. die Ausgabe von predict_proba) in Klassenvorhersagen umzuwandeln. 0,5 ist jedoch für ein gegebenes Problem fast nie der gewünschte Schwellenwert. FixedThresholdClassifier ermöglicht das Umschließen jedes binären Klassifikators und das Festlegen eines benutzerdefinierten Entscheidungsschwellenwerts.

from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.model_selection import train_test_split

X, y = make_classification(n_samples=10_000, weights=[0.9, 0.1], random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

classifier_05 = LogisticRegression(C=1e6, random_state=0).fit(X_train, y_train)
_ = ConfusionMatrixDisplay.from_estimator(classifier_05, X_test, y_test)
plot release highlights 1 5 0

Die Senkung des Schwellenwerts, d. h. die Zulassung von mehr Stichproben, die als positive Klasse klassifiziert werden, erhöht die Anzahl der True Positives auf Kosten von mehr False Positives (wie aus der Konkavität der ROC-Kurve bekannt ist).

from sklearn.model_selection import FixedThresholdClassifier

classifier_01 = FixedThresholdClassifier(classifier_05, threshold=0.1)
classifier_01.fit(X_train, y_train)
_ = ConfusionMatrixDisplay.from_estimator(classifier_01, X_test, y_test)
plot release highlights 1 5 0

TunedThresholdClassifierCV: Optimierung des Entscheidungsschwellenwerts eines binären Klassifikators#

Der Entscheidungsschwellenwert eines binären Klassifikators kann mithilfe von TunedThresholdClassifierCV optimiert werden, um eine vorgegebene Metrik zu optimieren.

Es ist besonders nützlich, den besten Entscheidungsschwellenwert zu finden, wenn das Modell in einem bestimmten Anwendungsfall eingesetzt werden soll, in dem wir unterschiedliche Gewinne oder Kosten für True Positives, True Negatives, False Positives und False Negatives zuweisen können.

Betrachten wir dies anhand eines willkürlichen Falles, bei dem

  • jeder True Positive 1 Einheit Gewinn einbringt, z. B. Euro, Jahre gesunden Lebens usw.;

  • True Negatives nichts einbringen oder kosten;

  • jeder False Negative 2 kostet;

  • jeder False Positive 0,1 kostet.

Unsere Metrik quantifiziert den durchschnittlichen Gewinn pro Stichprobe, der durch die folgende Python-Funktion definiert ist

from sklearn.metrics import confusion_matrix


def custom_score(y_observed, y_pred):
    tn, fp, fn, tp = confusion_matrix(y_observed, y_pred, normalize="all").ravel()
    return tp - 2 * fn - 0.1 * fp


print("Untuned decision threshold: 0.5")
print(f"Custom score: {custom_score(y_test, classifier_05.predict(X_test)):.2f}")
Untuned decision threshold: 0.5
Custom score: -0.12

Es ist interessant festzustellen, dass der durchschnittliche Gewinn pro Vorhersage negativ ist, was bedeutet, dass dieses Entscheidungssystem im Durchschnitt Verluste macht.

Die Optimierung des Schwellenwerts zur Optimierung dieser benutzerdefinierten Metrik ergibt einen kleineren Schwellenwert, der mehr Stichproben als positive Klasse klassifiziert. Infolgedessen verbessert sich der durchschnittliche Gewinn pro Vorhersage.

from sklearn.metrics import make_scorer
from sklearn.model_selection import TunedThresholdClassifierCV

custom_scorer = make_scorer(
    custom_score, response_method="predict", greater_is_better=True
)
tuned_classifier = TunedThresholdClassifierCV(
    classifier_05, cv=5, scoring=custom_scorer
).fit(X, y)

print(f"Tuned decision threshold: {tuned_classifier.best_threshold_:.3f}")
print(f"Custom score: {custom_score(y_test, tuned_classifier.predict(X_test)):.2f}")
Tuned decision threshold: 0.071
Custom score: 0.04

Wir beobachten, dass die Optimierung des Entscheidungsschwellenwerts ein maschinelles Lernsystem, das im Durchschnitt Verluste macht, in ein vorteilhaftes umwandeln kann.

In der Praxis kann die Definition einer aussagekräftigen anwendungsspezifischen Metrik dazu führen, dass diese Kosten für schlechte Vorhersagen und Gewinne für gute Vorhersagen von zusätzlichen Metadaten abhängen, die für jeden einzelnen Datenpunkt spezifisch sind, wie z. B. der Betrag einer Transaktion in einem Betrugserkennungssystem.

Um dies zu erreichen, nutzt TunedThresholdClassifierCV die Unterstützung für Metadaten-Routing (Benutzerhandbuch für Metadaten-Routing), um komplexe Geschäftsmetriken zu optimieren, wie im Beispiel Nach der Optimierung des Entscheidungsschwellenwerts für kostenempfindliches Lernen beschrieben.

Leistungsverbesserungen in PCA#

PCA verfügt über einen neuen Solver, "covariance_eigh", der für Datensätze mit vielen Datenpunkten und wenigen Merkmalen um eine Größenordnung schneller und speichereffizienter ist als die anderen Solver.

from sklearn.datasets import make_low_rank_matrix
from sklearn.decomposition import PCA

X = make_low_rank_matrix(
    n_samples=10_000, n_features=100, tail_strength=0.1, random_state=0
)

pca = PCA(n_components=10, svd_solver="covariance_eigh").fit(X)
print(f"Explained variance: {pca.explained_variance_ratio_.sum():.2f}")
Explained variance: 0.88

Der neue Solver akzeptiert auch spärliche Eingabedaten

from scipy.sparse import random

X = random(10_000, 100, format="csr", random_state=0)

pca = PCA(n_components=10, svd_solver="covariance_eigh").fit(X)
print(f"Explained variance: {pca.explained_variance_ratio_.sum():.2f}")
Explained variance: 0.13

Der Solver "full" wurde ebenfalls verbessert, um weniger Speicher zu verbrauchen und schnellere Transformationen zu ermöglichen. Die Standardoption svd_solver="auto" nutzt den neuen Solver und kann nun einen geeigneten Solver für spärliche Datensätze auswählen.

Ähnlich wie die meisten anderen PCA-Solver kann der neue Solver "covariance_eigh" GPU-Berechnungen nutzen, wenn die Eingabedaten als PyTorch- oder CuPy-Array übergeben werden, indem die experimentelle Unterstützung für die Array API aktiviert wird.

ColumnTransformer ist abfragbar#

Die Transformer eines ColumnTransformer können nun direkt über die Indizierung nach Namen aufgerufen werden.

import numpy as np

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler

X = np.array([[0, 1, 2], [3, 4, 5]])
column_transformer = ColumnTransformer(
    [("std_scaler", StandardScaler(), [0]), ("one_hot", OneHotEncoder(), [1, 2])]
)

column_transformer.fit(X)

print(column_transformer["std_scaler"])
print(column_transformer["one_hot"])
StandardScaler()
OneHotEncoder()

Benutzerdefinierte Imputationsstrategien für SimpleImputer#

SimpleImputer unterstützt nun benutzerdefinierte Strategien für die Imputation unter Verwendung eines aufrufbaren Objekts, das einen Skalarwert aus den nicht fehlenden Werten eines Spaltenvektors berechnet.

from sklearn.impute import SimpleImputer

X = np.array(
    [
        [-1.1, 1.1, 1.1],
        [3.9, -1.2, np.nan],
        [np.nan, 1.3, np.nan],
        [-0.1, -1.4, -1.4],
        [-4.9, 1.5, -1.5],
        [np.nan, 1.6, 1.6],
    ]
)


def smallest_abs(arr):
    """Return the smallest absolute value of a 1D array."""
    return np.min(np.abs(arr))


imputer = SimpleImputer(strategy=smallest_abs)

imputer.fit_transform(X)
array([[-1.1,  1.1,  1.1],
       [ 3.9, -1.2,  1.1],
       [ 0.1,  1.3,  1.1],
       [-0.1, -1.4, -1.4],
       [-4.9,  1.5, -1.5],
       [ 0.1,  1.6,  1.6]])

Paarweise Abstände mit nicht-numerischen Arrays#

pairwise_distances kann nun Abstände zwischen nicht-numerischen Arrays mithilfe einer aufrufbaren Metrik berechnen.

from sklearn.metrics import pairwise_distances

X = ["cat", "dog"]
Y = ["cat", "fox"]


def levenshtein_distance(x, y):
    """Return the Levenshtein distance between two strings."""
    if x == "" or y == "":
        return max(len(x), len(y))
    if x[0] == y[0]:
        return levenshtein_distance(x[1:], y[1:])
    return 1 + min(
        levenshtein_distance(x[1:], y),
        levenshtein_distance(x, y[1:]),
        levenshtein_distance(x[1:], y[1:]),
    )


pairwise_distances(X, Y, metric=levenshtein_distance)
array([[0., 3.],
       [3., 2.]])

Gesamtlaufzeit des Skripts: (0 Minuten 0,782 Sekunden)

Verwandte Beispiele

Post-hoc-Anpassung des Cut-off-Punkts der Entscheidungskfunktion

Post-hoc-Anpassung des Cut-off-Punkts der Entscheidungskfunktion

Post-Hoc-Anpassung des Entscheidungsschwellenwerts für kostenempfindliches Lernen

Post-Hoc-Anpassung des Entscheidungsschwellenwerts für kostenempfindliches Lernen

Beispiele für die Verwendung von FrozenEstimator

Beispiele für die Verwendung von FrozenEstimator

Leistung eines Klassifikators mit Konfusionsmatrix bewerten

Leistung eines Klassifikators mit Konfusionsmatrix bewerten

Galerie generiert von Sphinx-Gallery