Sklearn Train Test Split: Vollständiger Leitfaden zur Datenaufteilung in Python
Updated on
Das Trainieren eines Modells für maschinelles Lernen auf Ihrem gesamten Datensatz und dessen anschließende Bewertung auf denselben Daten führt zu einem kritischen Problem: Ihr Modell scheint gut zu funktionieren, hat aber die Daten lediglich auswendig gelernt, anstatt Muster zu erlernen. Dieses Overfitting bedeutet, dass Ihr Modell kläglich scheitern wird, wenn es auf neue, ungesehene Daten trifft. Datenwissenschaftler benötigen eine zuverlässige Methode, um die Modellleistung auf Daten zu bewerten, die das Modell während des Trainings nie gesehen hat.
Die Lösung ist die Train-Test-Aufteilung. Indem Sie einen Teil Ihrer Daten für die Evaluation zurückhalten, erhalten Sie eine ehrliche Einschätzung, wie Ihr Modell in der realen Welt funktionieren wird. Sklearns train_test_split-Funktion macht diesen Prozess unkompliziert, aber eine falsche Verwendung kann dennoch zu Datenlecks, schlechter Generalisierung und irreführenden Leistungsmetriken führen.
Dieser Leitfaden behandelt alles, was Sie über Sklearns train_test_split wissen müssen, von der grundlegenden Verwendung bis zu fortgeschrittenen Techniken für Zeitreihendaten, unausgewogene Klassen und Multi-Output-Probleme.
Was ist Train Test Split?
Train Test Split ist die grundlegende Technik zur Bewertung von Modellen für maschinelles Lernen. Sie teilen Ihren Datensatz in zwei Teile auf: einen Trainingssatz, der zum Anpassen des Modells verwendet wird, und einen Testsatz, der zur Bewertung der Modellleistung auf ungesehenen Daten dient.
Die train_test_split-Funktion aus scikit-learn (sklearn) automatisiert diesen Prozess und handhabt das zufällige Mischen und Aufteilen mit nur einer Codezeile.
from sklearn.model_selection import train_test_split
# Grundlegende Verwendung
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)In diesem Beispiel enthält X Ihre Features (Eingabevariablen) und y Ihre Zielvariable (was Sie vorhersagen möchten). Die Funktion gibt vier Arrays zurück: Trainingsfeatures, Testfeatures, Trainingslabels und Testlabels.
Grundlegende train_test_split-Syntax
Die einfachste Verwendung von train_test_split erfordert nur zwei Argumente: Ihre Features und Ihre Zielvariable.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
# Beispieldaten laden
iris = load_iris()
X = iris.data
y = iris.target
# Daten aufteilen (80% Training, 20% Test)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
print(f"Training samples: {len(X_train)}")
print(f"Test samples: {len(X_test)}")Dies teilt Ihre Daten zufällig auf, wobei 80% zum Training und 20% zum Testen gehen. Diese grundlegende Verwendung hat jedoch einen kritischen Fehler: Die Aufteilung ist jedes Mal anders, wenn Sie den Code ausführen, was die Ergebnisse nicht reproduzierbar macht.
Wesentliche Parameter
test_size und train_size
Der test_size-Parameter steuert, wie viele Daten in den Testsatz gehen. Sie können ihn angeben als:
- Ein Float zwischen 0.0 und 1.0 (Anteil des Datensatzes)
- Eine Ganzzahl (absolute Anzahl von Testproben)
# 30% Testsatz
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
# 50 Proben im Testsatz
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=50)
# Alternativ train_size angeben
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8)Wenn Sie sowohl test_size als auch train_size angeben, müssen sie sich zu 1.0 addieren (oder zur Gesamtgröße des Datensatzes bei Ganzzahlen). In den meisten Fällen reicht es aus, nur test_size anzugeben.
random_state für Reproduzierbarkeit
Der random_state-Parameter ist entscheidend für reproduzierbare Ergebnisse. Ohne ihn erhalten Sie jedes Mal eine andere Aufteilung, wenn Sie Ihren Code ausführen, was Debugging oder Vergleiche von Experimenten unmöglich macht.
# Ohne random_state - jedes Mal unterschiedliche Aufteilung
X_train1, X_test1, y_train1, y_test1 = train_test_split(X, y, test_size=0.2)
X_train2, X_test2, y_train2, y_test2 = train_test_split(X, y, test_size=0.2)
print(f"Same split? {(X_train1 == X_train2).all()}") # False
# Mit random_state - jedes Mal die gleiche Aufteilung
X_train1, X_test1, y_train1, y_test1 = train_test_split(X, y, test_size=0.2, random_state=42)
X_train2, X_test2, y_train2, y_test2 = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"Same split? {(X_train1 == X_train2).all()}") # TrueVerwenden Sie eine beliebige Ganzzahl für random_state. Die spezifische Zahl spielt keine Rolle; wichtig ist, dieselbe Zahl konsistent in Ihrem Projekt zu verwenden.
shuffle-Parameter
Standardmäßig mischt train_test_split die Daten vor dem Aufteilen. Für die meisten Aufgaben im maschinellen Lernen ist dies genau das, was Sie wollen. Bei Zeitreihendaten oder wenn die Reihenfolge wichtig ist, sollten Sie das Mischen jedoch deaktivieren.
# Mischen aktiviert (Standard)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True)
# Mischen deaktiviert (für Zeitreihen)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)Wenn shuffle=False, nimmt die Funktion einfach den ersten Teil für das Training und den letzten Teil für das Testen und behält die ursprüngliche Reihenfolge bei.
Parameter-Referenztabelle
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
test_size | float oder int | None | Anteil (0.0-1.0) oder Anzahl der Proben für Testsatz |
train_size | float oder int | None | Anteil (0.0-1.0) oder Anzahl der Proben für Trainingssatz |
random_state | int | None | Zufallsseed für Reproduzierbarkeit |
shuffle | bool | True | Ob Daten vor dem Aufteilen gemischt werden sollen |
stratify | array-like | None | Daten für stratifizierte Aufteilung |
Stratifizierte Aufteilung für unausgewogene Daten
Wenn Ihr Datensatz unausgewogene Klassen hat (einige Klassen haben weit weniger Proben als andere), kann eine zufällige Aufteilung Trainings- oder Testsätze erstellen, die die Gesamtverteilung schlecht repräsentieren. Dies ist besonders problematisch für Klassifizierungsaufgaben.
Der stratify-Parameter stellt sicher, dass die Klassenverteilung in den Trainings- und Testsätzen mit dem ursprünglichen Datensatz übereinstimmt.
import numpy as np
from sklearn.model_selection import train_test_split
# Unausgewogenen Datensatz erstellen (90% Klasse 0, 10% Klasse 1)
X = np.random.randn(1000, 5)
y = np.array([0] * 900 + [1] * 100)
# Ohne Stratifizierung
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"Train distribution: Class 0: {sum(y_train == 0)}, Class 1: {sum(y_train == 1)}")
print(f"Test distribution: Class 0: {sum(y_test == 0)}, Class 1: {sum(y_test == 1)}")
# Mit Stratifizierung
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"\nStratified train distribution: Class 0: {sum(y_train == 0)}, Class 1: {sum(y_train == 1)}")
print(f"Stratified test distribution: Class 0: {sum(y_test == 0)}, Class 1: {sum(y_test == 1)}")Mit Stratifizierung behalten sowohl Trainings- als auch Testsätze die 90/10-Klassenverteilung bei. Ohne sie könnten Sie Glück haben und eine repräsentative Aufteilung erhalten, oder Sie könnten mit einem Testsatz enden, der nur 5% der Klasse 1 hat, was zu unzuverlässigen Bewertungsmetriken führt.
Mehrere Arrays aufteilen
Sie können mehrere Arrays gleichzeitig aufteilen, und sklearn stellt sicher, dass sie auf die gleiche Weise aufgeteilt werden (gleiche Indizes für alle Arrays).
import numpy as np
X = np.random.randn(100, 5)
y = np.random.randint(0, 2, 100)
sample_weights = np.random.rand(100)
# Alle drei Arrays aufteilen
X_train, X_test, y_train, y_test, weights_train, weights_test = train_test_split(
X, y, sample_weights, test_size=0.2, random_state=42
)
print(f"X_train shape: {X_train.shape}")
print(f"y_train shape: {y_train.shape}")
print(f"weights_train shape: {weights_train.shape}")Dies ist besonders nützlich, wenn Sie Probengewichte, mehrere Zielvariablen oder zusätzliche Metadaten haben, die konsistent aufgeteilt werden müssen.
Train/Test Split vs. Kreuzvalidierung vs. Holdout
Verschiedene Validierungsstrategien dienen unterschiedlichen Zwecken. Hier ist ein Vergleich:
| Methode | Datennutzung | Rechenaufwand | Am besten für | Einschränkungen |
|---|---|---|---|---|
| Train/Test Split | 70-80% Training, 20-30% Test | Niedrig | Schnelle Modellbewertung, große Datensätze | Einzelne Bewertung, könnte Glück/Pech bei der Aufteilung haben |
| Kreuzvalidierung | 100% für Training/Testing verwendet (k-fold) | Hoch (k-mal langsamer) | Kleine Datensätze, zuverlässige Leistungsschätzung | Rechenintensiv, nicht für Zeitreihen |
| Train/Val/Test (Holdout) | 60% Training, 20% Validierung, 20% Test | Mittel | Hyperparameter-Tuning, finale Bewertung | Mehr Daten benötigt, komplexerer Workflow |
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
model = RandomForestClassifier(random_state=42)
# Methode 1: Einfache Train/Test-Aufteilung
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model.fit(X_train, y_train)
print(f"Train/Test Split Score: {model.score(X_test, y_test):.3f}")
# Methode 2: 5-fache Kreuzvalidierung
scores = cross_val_score(model, X, y, cv=5)
print(f"Cross-Validation Score: {scores.mean():.3f} (+/- {scores.std():.3f})")
# Methode 3: Train/Val/Test-Aufteilung
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.25, random_state=42)
model.fit(X_train, y_train)
print(f"Validation Score: {model.score(X_val, y_val):.3f}")
print(f"Test Score: {model.score(X_test, y_test):.3f}")Beginnen Sie für die meisten Projekte mit einer einfachen Train/Test-Aufteilung. Verwenden Sie Kreuzvalidierung, wenn Sie begrenzte Daten haben oder eine robustere Leistungsschätzung benötigen. Verwenden Sie Train/Val/Test, wenn Sie Hyperparameter abstimmen müssen.
Fortgeschrittene Aufteilungstechniken
Zeitreihen-Aufteilung
Bei Zeitreihendaten zerstört zufälliges Mischen die zeitliche Reihenfolge, was zu Datenlecks führen kann (Verwendung zukünftiger Informationen zur Vorhersage der Vergangenheit). Verwenden Sie stattdessen TimeSeriesSplit:
from sklearn.model_selection import TimeSeriesSplit
import numpy as np
X = np.random.randn(100, 5)
y = np.random.randn(100)
tscv = TimeSeriesSplit(n_splits=5)
for train_index, test_index in tscv.split(X):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
print(f"Train size: {len(train_index)}, Test size: {len(test_index)}")TimeSeriesSplit erstellt mehrere Train/Test-Aufteilungen, wobei jeder Trainingssatz alle vergangenen Daten bis zu einem bestimmten Punkt enthält, und der Testsatz enthält die unmittelbar folgende Periode. Dies simuliert reale Vorhersagen, bei denen Sie nur vergangene Daten haben, um die Zukunft vorherzusagen.
GroupShuffleSplit für gruppierte Daten
Wenn Ihre Daten Gruppen haben (z.B. mehrere Messungen vom selben Patienten, mehrere Transaktionen vom selben Kunden), müssen Sie sicherstellen, dass ganze Gruppen entweder im Trainings- oder im Testsatz bleiben, um Datenlecks zu vermeiden.
from sklearn.model_selection import GroupShuffleSplit
import numpy as np
X = np.random.randn(100, 5)
y = np.random.randint(0, 2, 100)
groups = np.array([0] * 25 + [1] * 25 + [2] * 25 + [3] * 25) # 4 Gruppen
gss = GroupShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
for train_idx, test_idx in gss.split(X, y, groups):
X_train, X_test = X[train_idx], X[test_idx]
y_train, y_test = y[train_idx], y[test_idx]
print(f"Train groups: {np.unique(groups[train_idx])}")
print(f"Test groups: {np.unique(groups[test_idx])}")Dies stellt sicher, dass alle Proben einer bestimmten Gruppe entweder im Trainingssatz oder im Testsatz sind, niemals in beiden.
Stratifizierte Multi-Output-Aufteilung
Bei Multi-Output-Klassifizierungsproblemen können Sie stratify nicht direkt mit einem 2D-Array verwenden. Erstellen Sie stattdessen ein einzelnes Label, das die Kombination aller Outputs darstellt:
import numpy as np
from sklearn.model_selection import train_test_split
X = np.random.randn(1000, 10)
y = np.random.randint(0, 2, (1000, 3)) # 3 binäre Outputs
# Kombinierte Labels für Stratifizierung erstellen
y_combined = y[:, 0] * 4 + y[:, 1] * 2 + y[:, 2]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y_combined
)
print(f"Original distribution: {np.unique(y_combined, return_counts=True)[1]}")
print(f"Train distribution: {np.unique(y_combined[:(len(X) - len(X_test))], return_counts=True)[1]}")Best Practices für Train Test Split
Das richtige Aufteilungsverhältnis wählen
Die häufigsten Aufteilungsverhältnisse sind:
- 80/20: Standardwahl für mittlere bis große Datensätze (10.000+ Proben)
- 70/30: Besser für kleinere Datensätze (1.000-10.000 Proben), um eine robustere Testbewertung zu haben
- 90/10: Für sehr große Datensätze (100.000+ Proben), bei denen auch 10% ausreichend Testproben liefern
- 60/20/20: Für Train/Validation/Test beim Abstimmen von Hyperparametern
import numpy as np
def recommend_split_ratio(n_samples):
if n_samples < 1000:
return "Consider cross-validation instead of simple split"
elif n_samples < 10000:
return "70/30 split recommended"
elif n_samples < 100000:
return "80/20 split recommended"
else:
return "90/10 or 80/20 split recommended"
sample_sizes = [500, 5000, 50000, 500000]
for size in sample_sizes:
print(f"{size} samples: {recommend_split_ratio(size)}")Datenlecks vermeiden
Datenlecks treten auf, wenn Informationen aus dem Testsatz den Trainingsprozess beeinflussen. Häufige Quellen:
- Vorverarbeitung vor dem Aufteilen: Immer zuerst aufteilen, dann vorverarbeiten
- Feature-Skalierung auf kombinierten Daten: Scaler nur auf Trainingsdaten anpassen
- Feature-Auswahl auf kombinierten Daten: Features nur mit Trainingsdaten auswählen
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import numpy as np
X = np.random.randn(1000, 10)
y = np.random.randint(0, 2, 1000)
# FALSCH: Vor dem Aufteilen skalieren (Datenleck!)
scaler_wrong = StandardScaler()
X_scaled_wrong = scaler_wrong.fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_scaled_wrong, y, test_size=0.2)
# RICHTIG: Zuerst aufteilen, dann skalieren
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # Auf Trainingsdaten anpassen
X_test_scaled = scaler.transform(X_test) # Testdaten mit Trainingsstatistiken transformierenDer falsche Ansatz verwendet Informationen aus dem gesamten Datensatz (einschließlich Testproben), um Skalierungsparameter zu berechnen, wodurch Informationen über den Testsatz in den Trainingsprozess gelangen.
Wann immer möglich stratifizieren
Verwenden Sie für Klassifizierungsprobleme immer stratifizierte Aufteilung, es sei denn, Sie haben einen bestimmten Grund dagegen. Dies ist besonders wichtig für:
- Unausgewogene Datensätze
- Kleine Datensätze
- Multi-Klassen-Probleme mit seltenen Klassen
from sklearn.model_selection import train_test_split
import numpy as np
# Datensatz seltener Krankheiten: 1% positive Fälle
X = np.random.randn(1000, 20)
y = np.array([0] * 990 + [1] * 10)
# Ohne Stratifizierung - könnte keine positiven Fälle im Testsatz haben!
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=123)
print(f"Non-stratified test positives: {sum(y_test)}")
# Mit Stratifizierung - garantiert proportionale Repräsentation
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.1, random_state=123, stratify=y
)
print(f"Stratified test positives: {sum(y_test)}")Häufige Fehler, die zu vermeiden sind
1. random_state vergessen
Ohne random_state ändern sich Ihre Ergebnisse jedes Mal, wenn Sie den Code ausführen. Dies macht Debugging unmöglich und Experimente nicht reproduzierbar.
# SCHLECHT: Kein random_state
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# GUT: random_state setzen
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)2. Unausgewogene Klassen nicht stratifizieren
Bei unausgewogenen Datensätzen kann zufälliges Aufteilen hochgradig nicht repräsentative Testsätze erstellen, was zu unzuverlässigen Leistungsmetriken führt.
# SCHLECHT: Keine Stratifizierung für unausgewogene Daten
X_train, X_test, y_train, y_test = train_test_split(X, y_imbalanced, test_size=0.2)
# GUT: Stratifizierung verwenden
X_train, X_test, y_train, y_test = train_test_split(
X, y_imbalanced, test_size=0.2, stratify=y_imbalanced, random_state=42
)3. Zeitreihendaten mit Shuffle aufteilen
Zeitreihenmodelle hängen von der zeitlichen Reihenfolge ab. Mischen zerstört diese Struktur und kann zu schweren Datenlecks führen.
# SCHLECHT: Zeitreihendaten mischen
X_train, X_test, y_train, y_test = train_test_split(
X_timeseries, y_timeseries, test_size=0.2, shuffle=True
)
# GUT: Mischen deaktivieren oder TimeSeriesSplit verwenden
X_train, X_test, y_train, y_test = train_test_split(
X_timeseries, y_timeseries, test_size=0.2, shuffle=False
)4. Vorverarbeitung vor dem Aufteilen
Das Anpassen von Präprozessoren (Scaler, Imputer, Encoder) auf den gesamten Datensatz vor dem Aufteilen verursacht Datenlecks.
# SCHLECHT: Vorverarbeitung vor dem Aufteilen
X_scaled = StandardScaler().fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2)
# GUT: Zuerst aufteilen, dann vorverarbeiten
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)5. Testsatz für Hyperparameter-Tuning verwenden
Der Testsatz sollte nur für die finale Bewertung verwendet werden. Wenn Sie ihn zur Auswahl von Hyperparametern verwenden, trainieren Sie im Wesentlichen auf Ihren Testdaten.
# SCHLECHT: Tuning auf Testsatz
from sklearn.ensemble import RandomForestClassifier
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
best_score = 0
best_params = None
for n_estimators in [10, 50, 100]:
model = RandomForestClassifier(n_estimators=n_estimators)
model.fit(X_train, y_train)
score = model.score(X_test, y_test) # Testsatz verwenden!
if score > best_score:
best_score = score
best_params = n_estimators
# GUT: Validierungssatz oder Kreuzvalidierung verwenden
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.25, random_state=42)
best_score = 0
best_params = None
for n_estimators in [10, 50, 100]:
model = RandomForestClassifier(n_estimators=n_estimators)
model.fit(X_train, y_train)
score = model.score(X_val, y_val) # Validierungssatz verwenden
if score > best_score:
best_score = score
best_params = n_estimatorsPraktisches Beispiel: Vollständiger Workflow
Hier ist ein vollständiger Workflow für maschinelles Lernen mit korrekter Verwendung von train_test_split:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
# Daten laden
np.random.seed(42)
X = np.random.randn(1000, 10)
y = (X[:, 0] + X[:, 1] > 0).astype(int) # Binäre Klassifizierung
# Schritt 1: Daten aufteilen (stratifiziert für ausgewogenen Testsatz)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Schritt 2: Vorverarbeiten (nur auf Trainingsdaten anpassen)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Schritt 3: Modell trainieren
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train_scaled, y_train)
# Schritt 4: Bewerten
y_pred = model.predict(X_test_scaled)
print("Classification Report:")
print(classification_report(y_test, y_pred))
print("\nConfusion Matrix:")
print(confusion_matrix(y_test, y_pred))
# Schritt 5: Auf Overfitting prüfen
train_score = model.score(X_train_scaled, y_train)
test_score = model.score(X_test_scaled, y_test)
print(f"\nTrain accuracy: {train_score:.3f}")
print(f"Test accuracy: {test_score:.3f}")
print(f"Overfitting gap: {train_score - test_score:.3f}")RunCell für interaktive Datenaufteilung verwenden
Bei der Arbeit in Jupyter-Notebooks kann das Experimentieren mit verschiedenen Aufteilungsverhältnissen und Parametern mühsam sein. RunCell (opens in a new tab) bietet einen KI-Agenten, der speziell für Data-Science-Workflows in Jupyter entwickelt wurde. Er kann Ihnen helfen:
- Mehrere Aufteilungsverhältnisse automatisch zu testen und Ergebnisse zu vergleichen
- Datenlecks in Ihrer Vorverarbeitungspipeline zu erkennen
- Optimale Stratifizierungsstrategien für Ihren spezifischen Datensatz vorzuschlagen
- Validierungskurven zu generieren, um das richtige Train/Test-Verhältnis zu wählen
RunCell integriert sich direkt in Ihre Jupyter-Umgebung und erleichtert die Iteration Ihrer Datenaufteilungsstrategie ohne wiederholenden Code.
Ihre Daten mit PyGWalker visualisieren
Nach dem Aufteilen Ihrer Daten ist es wichtig zu überprüfen, dass Ihre Trainings- und Testsätze ähnliche Verteilungen haben. PyGWalker (opens in a new tab) verwandelt Ihre Pandas-DataFrames in interaktive Visualisierungen im Tableau-Stil und erleichtert:
- Vergleich von Feature-Verteilungen zwischen Trainings- und Testsätzen
- Identifizierung potenzieller Stichprobenverzerrungen in Ihren Aufteilungen
- Visualisierung von Klassenungleichgewichten und Überprüfung, ob Stratifizierung korrekt funktioniert hat
- Erkundung von Beziehungen zwischen Features in Ihren Trainingsdaten
import pygwalker as pyg
import pandas as pd
# In DataFrames für Visualisierung konvertieren
train_df = pd.DataFrame(X_train, columns=[f'feature_{i}' for i in range(X_train.shape[1])])
train_df['dataset'] = 'train'
test_df = pd.DataFrame(X_test, columns=[f'feature_{i}' for i in range(X_test.shape[1])])
test_df['dataset'] = 'test'
combined = pd.concat([train_df, test_df])
# Interaktive Visualisierung erstellen
pyg.walk(combined)Dies ermöglicht es Ihnen, interaktiv zu erkunden, ob Ihre Train- und Test-Verteilungen übereinstimmen, was für eine zuverlässige Modellbewertung entscheidend ist.
FAQ
Wie wähle ich zwischen 80/20- und 70/30-Aufteilung?
Verwenden Sie 80/20 für Datensätze größer als 10.000 Proben und 70/30 für kleinere Datensätze (1.000-10.000 Proben). Der Schlüssel ist sicherzustellen, dass Ihr Testsatz genügend Proben für eine zuverlässige Bewertung hat – typischerweise mindestens 200-500 Proben für Klassifizierungsprobleme. Bei sehr großen Datensätzen (100.000+ Proben) können Sie 90/10 oder sogar 95/5 verwenden, da selbst 5% Tausende von Testproben liefern.
Was ist random_state und warum ist es wichtig?
random_state ist der Seed für den Zufallszahlengenerator, der Ihre Daten vor dem Aufteilen mischt. Die Verwendung desselben random_state-Werts stellt sicher, dass Sie jedes Mal die identische Aufteilung erhalten, wenn Sie Ihren Code ausführen, was für Reproduzierbarkeit und Debugging unerlässlich ist. Ohne ihn erhalten Sie jedes Mal unterschiedliche Train/Test-Aufteilungen, was es unmöglich macht zu bestimmen, ob Leistungsänderungen auf Modellverbesserungen oder nur auf glückliche/unglückliche Datenaufteilungen zurückzuführen sind.
Wann sollte ich den stratify-Parameter verwenden?
Verwenden Sie stratify=y für alle Klassifizierungsprobleme, insbesondere wenn Sie unausgewogene Klassen oder kleine Datensätze haben. Stratifizierung stellt sicher, dass die Klassenverteilung in Ihren Trainings- und Testsätzen mit der Gesamtverteilung übereinstimmt. Wenn beispielsweise 10% Ihrer Daten positive Fälle sind, garantiert Stratifizierung, dass sowohl Trainings- als auch Testsätze ungefähr 10% positive Fälle haben, wodurch Bewertungsverzerrungen durch nicht repräsentative Aufteilungen verhindert werden.
Kann ich train_test_split für Zeitreihendaten verwenden?
Nein, Sie sollten train_test_split nicht mit shuffle=True für Zeitreihendaten verwenden, da es die zeitliche Ordnung zerstört und Datenlecks verursacht (Verwendung zukünftiger Daten zur Vorhersage der Vergangenheit). Verwenden Sie stattdessen entweder train_test_split mit shuffle=False für eine einfache chronologische Aufteilung oder verwenden Sie TimeSeriesSplit für Kreuzvalidierung, die die zeitliche Reihenfolge respektiert. Bei Zeitreihen stellen Sie immer sicher, dass Trainingsdaten chronologisch vor Testdaten kommen.
Wie unterscheidet sich train_test_split von Kreuzvalidierung?
train_test_split erstellt eine einzelne Train/Test-Partition (typischerweise 80/20) und gibt Ihnen eine Leistungsschätzung. Kreuzvalidierung (wie k-fold) erstellt mehrere Train/Test-Aufteilungen und mittelt die Ergebnisse, was eine robustere Leistungsschätzung liefert. Verwenden Sie train_test_split für schnelle Bewertung und große Datensätze. Verwenden Sie Kreuzvalidierung für kleine Datensätze (weniger als 1.000 Proben) oder wenn Sie zuverlässigere Leistungsschätzungen benötigen. Kreuzvalidierung ist k-mal langsamer (z.B. ist 5-fold 5× langsamer), reduziert aber die Varianz in Ihren Leistungsmetriken.
Fazit
Sklearns train_test_split ist das grundlegende Werkzeug zur Bewertung von Modellen für maschinelles Lernen. Durch korrektes Aufteilen Ihrer Daten erhalten Sie ehrliche Leistungsschätzungen, die das reale Modellverhalten vorhersagen. Beachten Sie die Schlüsselprinzipien: Setzen Sie immer random_state für Reproduzierbarkeit, verwenden Sie stratify für Klassifizierungsprobleme, vermeiden Sie Vorverarbeitung vor dem Aufteilen und wählen Sie Ihr Aufteilungsverhältnis basierend auf der Datensatzgröße.
Meistern Sie diese Grundlagen, und Sie werden die häufigsten Fallstricke vermeiden, die zu überangepassten Modellen und irreführenden Leistungsmetriken führen. Egal, ob Sie einen einfachen Klassifikator oder ein komplexes Deep-Learning-System aufbauen, die korrekte Train-Test-Aufteilung ist der erste Schritt zu zuverlässigem maschinellem Lernen.