Interne Kreuzvalidierung des Target Encoders#

Der TargetEncoder ersetzt jede Kategorie eines kategorialen Merkmals durch den geschrumpften Mittelwert der Zielvariable für diese Kategorie. Diese Methode ist nützlich in Fällen, in denen eine starke Beziehung zwischen dem kategorialen Merkmal und dem Ziel besteht. Um Overfitting zu verhindern, verwendet TargetEncoder.fit_transform ein internes Cross-Fitting-Schema, um die Trainingsdaten zu kodieren, die von einem nachfolgenden Modell verwendet werden sollen. Dieses Schema beinhaltet das Aufteilen der Daten in *k* Folds und das Kodieren jedes Folds unter Verwendung der Kodierungen, die mit den *anderen k-1* Folds gelernt wurden. In diesem Beispiel demonstrieren wir die Bedeutung des Cross-Fitting-Verfahrens zur Verhinderung von Overfitting.

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

Erstellen eines synthetischen Datensatzes#

Für dieses Beispiel erstellen wir einen Datensatz mit drei kategorialen Merkmalen

  • ein informatives Merkmal mit mittlerer Kardinalität ("informative")

  • ein uninformativen Merkmal mit mittlerer Kardinalität ("shuffled")

  • ein uninformativen Merkmal mit hoher Kardinalität ("near_unique")

Zuerst generieren wir das informative Merkmal

import numpy as np

from sklearn.preprocessing import KBinsDiscretizer

n_samples = 50_000

rng = np.random.RandomState(42)
y = rng.randn(n_samples)
noise = 0.5 * rng.randn(n_samples)
n_categories = 100

kbins = KBinsDiscretizer(
    n_bins=n_categories,
    encode="ordinal",
    strategy="uniform",
    random_state=rng,
    subsample=None,
)
X_informative = kbins.fit_transform((y + noise).reshape(-1, 1))

# Remove the linear relationship between y and the bin index by permuting the
# values of X_informative:
permuted_categories = rng.permutation(n_categories)
X_informative = permuted_categories[X_informative.astype(np.int32)]

Das uninformativen Merkmal mit mittlerer Kardinalität wird generiert, indem die Reihenfolge des informativen Merkmals permutiert und die Beziehung zum Ziel entfernt wird

X_shuffled = rng.permutation(X_informative)

Das uninformativen Merkmal mit hoher Kardinalität wird so generiert, dass es unabhängig von der Zielvariablen ist. Wir werden zeigen, dass Target Encoding ohne Cross-Fitting zu katastrophalem Overfitting für den nachfolgenden Regressor führen wird. Diese Merkmale mit hoher Kardinalität sind im Grunde eindeutige Identifikatoren für Stichproben, die im Allgemeinen aus Machine-Learning-Datensätzen entfernt werden sollten. In diesem Beispiel generieren wir sie, um zu zeigen, wie das Standardverhalten von TargetEncoder bezüglich Cross-Fitting das Overfitting-Problem automatisch abmildert.

X_near_unique_categories = rng.choice(
    int(0.9 * n_samples), size=n_samples, replace=True
).reshape(-1, 1)

Schließlich stellen wir den Datensatz zusammen und führen eine Train-Test-Aufteilung durch

import pandas as pd

from sklearn.model_selection import train_test_split

X = pd.DataFrame(
    np.concatenate(
        [X_informative, X_shuffled, X_near_unique_categories],
        axis=1,
    ),
    columns=["informative", "shuffled", "near_unique"],
)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

Trainieren eines Ridge-Regressors#

In diesem Abschnitt trainieren wir einen Ridge-Regressor auf dem Datensatz mit und ohne Kodierung und untersuchen den Einfluss des Target Encoders mit und ohne internem Cross-Fitting. Zuerst sehen wir, dass das Ridge-Modell, das auf den Rohmerkmalen trainiert wurde, eine geringe Leistung aufweist. Dies liegt daran, dass wir die Reihenfolge des informativen Merkmals vertauscht haben, was bedeutet, dass X_informative roh nicht informativ ist

import sklearn
from sklearn.linear_model import Ridge

# Configure transformers to always output DataFrames
sklearn.set_config(transform_output="pandas")

ridge = Ridge(alpha=1e-6, solver="lsqr", fit_intercept=False)

raw_model = ridge.fit(X_train, y_train)
print("Raw Model score on training set: ", raw_model.score(X_train, y_train))
print("Raw Model score on test set: ", raw_model.score(X_test, y_test))
Raw Model score on training set:  0.0049896314219657345
Raw Model score on test set:  0.0045776215814927745

Als Nächstes erstellen wir eine Pipeline mit dem Target Encoder und dem Ridge-Modell. Die Pipeline verwendet TargetEncoder.fit_transform, das Cross-Fitting verwendet. Wir sehen, dass das Modell die Daten gut anpasst und auf den Testdatensatz generalisiert

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import TargetEncoder

model_with_cf = make_pipeline(TargetEncoder(random_state=0), ridge)
model_with_cf.fit(X_train, y_train)
print("Model with CF on train set: ", model_with_cf.score(X_train, y_train))
print("Model with CF on test set: ", model_with_cf.score(X_test, y_test))
Model with CF on train set:  0.8000184677460304
Model with CF on test set:  0.7927845601690917

Die Koeffizienten des linearen Modells zeigen, dass der Großteil des Gewichts auf dem Merkmal mit dem Spaltenindex 0 liegt, was das informative Merkmal ist

import matplotlib.pyplot as plt
import pandas as pd

plt.rcParams["figure.constrained_layout.use"] = True

coefs_cf = pd.Series(
    model_with_cf[-1].coef_, index=model_with_cf[-1].feature_names_in_
).sort_values()
ax = coefs_cf.plot(kind="barh")
_ = ax.set(
    title="Target encoded with cross fitting",
    xlabel="Ridge coefficient",
    ylabel="Feature",
)
Target encoded with cross fitting

Während TargetEncoder.fit_transform ein internes Cross-Fitting-Schema verwendet, um Kodierungen für den Trainingsdatensatz zu lernen, tun dies TargetEncoder.fit gefolgt von TargetEncoder.transform nicht. Es verwendet den vollständigen Trainingsdatensatz, um Kodierungen zu lernen und die kategorialen Merkmale zu transformieren. Daher können wir TargetEncoder.fit gefolgt von TargetEncoder.transform verwenden, um das Cross-Fitting zu deaktivieren. Diese Kodierung wird dann an das Ridge-Modell übergeben.

target_encoder = TargetEncoder(random_state=0)
target_encoder.fit(X_train, y_train)
X_train_no_cf_encoding = target_encoder.transform(X_train)
X_test_no_cf_encoding = target_encoder.transform(X_test)

model_no_cf = ridge.fit(X_train_no_cf_encoding, y_train)

Wir evaluieren das Modell, das beim Kodieren kein Cross-Fitting verwendet hat, und sehen, dass es zu Overfitting neigt

print(
    "Model without CF on training set: ",
    model_no_cf.score(X_train_no_cf_encoding, y_train),
)
print(
    "Model without CF on test set: ",
    model_no_cf.score(
        X_test_no_cf_encoding,
        y_test,
    ),
)
Model without CF on training set:  0.858486250088675
Model without CF on test set:  0.6338211367102257

Das Ridge-Modell neigt zu Overfitting, da es den uninformativen Merkmalen mit extrem hoher ("near_unique") und mittlerer ("shuffled") Kardinalität wesentlich mehr Gewicht beimisst als wenn das Modell Cross-Fitting zum Kodieren der Merkmale verwendet hätte.

coefs_no_cf = pd.Series(
    model_no_cf.coef_, index=model_no_cf.feature_names_in_
).sort_values()
ax = coefs_no_cf.plot(kind="barh")
_ = ax.set(
    title="Target encoded without cross fitting",
    xlabel="Ridge coefficient",
    ylabel="Feature",
)
Target encoded without cross fitting

Schlussfolgerung#

Dieses Beispiel demonstriert die Bedeutung des internen Cross-Fitting des TargetEncoder. Es ist wichtig, TargetEncoder.fit_transform zu verwenden, um Trainingsdaten zu kodieren, bevor sie an ein Machine-Learning-Modell übergeben werden. Wenn ein TargetEncoder Teil einer Pipeline ist und die Pipeline angepasst wird, ruft die Pipeline korrekt TargetEncoder.fit_transform auf und verwendet Cross-Fitting beim Kodieren der Trainingsdaten.

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

Verwandte Beispiele

Vergleich von Target Encoder mit anderen Encodern

Vergleich von Target Encoder mit anderen Encodern

Unterstützung für kategorische Merkmale in Gradient Boosting

Unterstützung für kategorische Merkmale in Gradient Boosting

HuberRegressor vs Ridge auf Datensatz mit starken Ausreißern

HuberRegressor vs Ridge auf Datensatz mit starken Ausreißern

Gewöhnliche kleinste Quadrate und Ridge Regression

Gewöhnliche kleinste Quadrate und Ridge Regression

Galerie generiert von Sphinx-Gallery