Sklearn train_test_split: Daten für maschinelles Lernen in Python aufteilen
Updated on
Ein Machine-Learning-Modell mit denselben Daten zu trainieren und zu evaluieren führt zu irreführend hoher Genauigkeit. Das Modell lernt die Trainingsdaten auswendig, anstatt verallgemeinerbare Muster zu erkennen -- ein Problem namens Overfitting. Sie brauchen ein separates Testset, das das Modell während des Trainings nie sieht, um ehrliche Leistungsmetriken zu erhalten.
Scikit-learns train_test_split() ist die Standardmethode, um Datensätze in Trainings- und Testanteile aufzuteilen. Die Funktion verarbeitet Arrays, DataFrames und Sparse-Matrizen, mit Optionen für Stratifikation, Reproduzierbarkeit und benutzerdefinierte Split-Verhältnisse.
Grundlegende Verwendung
from sklearn.model_selection import train_test_split
import numpy as np
# Beispieldaten: 100 Samples, 5 Features
X = np.random.randn(100, 5)
y = np.random.randint(0, 2, 100) # Binäre Labels
# Split: 80% Training, 20% Test
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"Trainingsset: {X_train.shape[0]} Samples")
print(f"Testset: {X_test.shape[0]} Samples")
# Trainingsset: 80 Samples
# Testset: 20 SamplesWichtige Parameter
| Parameter | Standard | Beschreibung |
|---|---|---|
test_size | 0.25 | Anteil (0.0-1.0) oder absolute Anzahl der Testsamples |
train_size | None | Anteil oder Anzahl der Trainingssamples (Komplement von test_size) |
random_state | None | Seed für reproduzierbare Splits |
shuffle | True | Ob die Daten vor dem Aufteilen gemischt werden |
stratify | None | Array für stratifizierte Aufteilung |
Mit Pandas DataFrames
from sklearn.model_selection import train_test_split
import pandas as pd
df = pd.DataFrame({
'age': [25, 30, 35, 40, 45, 50, 55, 60, 28, 33],
'income': [40, 50, 60, 70, 80, 90, 100, 110, 45, 55],
'purchased': [0, 0, 1, 1, 1, 1, 1, 1, 0, 0]
})
X = df[['age', 'income']]
y = df['purchased']
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
print(f"Train shape: {X_train.shape}") # (7, 2)
print(f"Test shape: {X_test.shape}") # (3, 2)
print(type(X_train)) # <class 'pandas.core.frame.DataFrame'>DataFrames bleiben nach dem Aufteilen DataFrames -- Spaltennamen und Indizes werden beibehalten.
random_state: Reproduzierbare Splits
Ohne random_state erhalten Sie bei jedem Durchlauf einen anderen Split:
from sklearn.model_selection import train_test_split
import numpy as np
X = np.arange(10).reshape(5, 2)
y = np.array([0, 0, 1, 1, 1])
# Ohne random_state: unterschiedlicher Split bei jedem Durchlauf
_, X_test1, _, _ = train_test_split(X, y, test_size=0.4)
_, X_test2, _, _ = train_test_split(X, y, test_size=0.4)
print(np.array_equal(X_test1, X_test2)) # Wahrscheinlich False
# Mit random_state: gleicher Split jedes Mal
_, X_test3, _, _ = train_test_split(X, y, test_size=0.4, random_state=42)
_, X_test4, _, _ = train_test_split(X, y, test_size=0.4, random_state=42)
print(np.array_equal(X_test3, X_test4)) # TrueSetzen Sie immer random_state für Reproduzierbarkeit. Verwenden Sie eine beliebige Ganzzahl -- 42 ist üblich, aber die konkrete Zahl spielt keine Rolle.
Stratifizierte Aufteilung
Bei unausgeglichenen Datensätzen könnte ein zufälliger Split die meisten Minderheitssamples in ein Set packen. Stratifikation stellt sicher, dass beide Sets die gleichen Klassenproportionen haben:
from sklearn.model_selection import train_test_split
import numpy as np
from collections import Counter
# Unausgeglichener Datensatz: 90% Klasse 0, 10% Klasse 1
np.random.seed(42)
X = np.random.randn(200, 4)
y = np.array([0] * 180 + [1] * 20)
# Ohne Stratifikation
_, _, y_train_bad, y_test_bad = train_test_split(
X, y, test_size=0.2, random_state=42
)
print("Ohne Stratifikation:")
print(f" Train: {Counter(y_train_bad)}")
print(f" Test: {Counter(y_test_bad)}")
# Mit Stratifikation
_, _, y_train_good, y_test_good = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print("\nMit stratify=y:")
print(f" Train: {Counter(y_train_good)}")
print(f" Test: {Counter(y_test_good)}")
# Train: Counter({0: 144, 1: 16}) -- 10% Klasse 1
# Test: Counter({0: 36, 1: 4}) -- 10% Klasse 1Wann Stratifikation verwenden
| Szenario | Stratify verwenden? |
|---|---|
| Ausgeglichene Klassen (50/50) | Optional |
| Unausgeglichene Klassen (90/10) | Ja |
| Mehrklassen-Klassifikation | Ja |
| Regression (kontinuierliches Ziel) | Nein (nicht unterstützt) |
| Kleine Datensätze (< 100 Samples) | Ja (verhindert leere Klassen) |
Train/Validierung/Test-Split
Für Hyperparameter-Tuning brauchen Sie drei Sets: Training, Validierung und Test. Wenden Sie train_test_split zweimal an:
from sklearn.model_selection import train_test_split
import numpy as np
X = np.random.randn(1000, 10)
y = np.random.randint(0, 3, 1000)
# Erster Split: 80% Train+Val, 20% Test
X_temp, X_test, y_temp, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Zweiter Split: 75% Train, 25% Val (von den 80% = 60/20/20 insgesamt)
X_train, X_val, y_train, y_val = train_test_split(
X_temp, y_temp, test_size=0.25, random_state=42, stratify=y_temp
)
print(f"Training: {X_train.shape[0]} Samples (60%)")
print(f"Validierung: {X_val.shape[0]} Samples (20%)")
print(f"Test: {X_test.shape[0]} Samples (20%)")Komplettes ML-Pipeline-Beispiel
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report
import numpy as np
# Beispieldaten generieren
np.random.seed(42)
X = np.random.randn(500, 8)
y = (X[:, 0] + X[:, 1] > 0).astype(int)
# Daten aufteilen
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Features skalieren (nur auf Trainingsdaten fitten!)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test) # Trainingsstatistiken verwenden
# Modell trainieren
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train_scaled, y_train)
# Evaluieren
y_pred = model.predict(X_test_scaled)
print(f"Genauigkeit: {accuracy_score(y_test, y_pred):.4f}")
print(classification_report(y_test, y_pred))Kritische Regel: Fitten Sie den Scaler (und jede Vorverarbeitung) nur auf dem Trainingsset. Wenden Sie die gleiche Transformation auf das Testset an. Das Fitten auf dem gesamten Datensatz verursacht Data Leakage.
Gängige Split-Verhältnisse
| Split | Training | Test | Wann verwenden |
|---|---|---|---|
| 80/20 | 80% | 20% | Standardwahl, die meisten Datensätze |
| 70/30 | 70% | 30% | Kleine Datensätze, größeres Testset benötigt |
| 90/10 | 90% | 10% | Große Datensätze (10k+ Samples) |
| 60/20/20 | 60% | 20% Val + 20% Test | Beim Hyperparameter-Tuning |
Modellergebnisse erkunden
Nach dem Aufteilen und Trainieren Ihres Modells können Sie mit PyGWalker (opens in a new tab) interaktiv Vorhersagen vs. tatsächliche Werte, Feature-Verteilungen über Train/Test-Sets und Fehlermuster in Jupyter erkunden:
import pandas as pd
import pygwalker as pyg
results = pd.DataFrame({
'actual': y_test,
'predicted': y_pred,
'correct': y_test == y_pred
})
walker = pyg.walk(results)FAQ
Was macht train_test_split in sklearn?
train_test_split() teilt Arrays oder DataFrames zufällig in zwei Teilmengen auf: eine für das Training und eine für das Testen. Es stellt sicher, dass die Modellbewertung Daten verwendet, die das Modell während des Trainings nicht gesehen hat, und liefert so ehrliche Leistungsschätzungen.
Was ist das beste Train/Test-Split-Verhältnis?
80/20 ist der Standardwert. Verwenden Sie 70/30 für kleinere Datensätze, bei denen Sie ein zuverlässiges Testset brauchen, und 90/10 für große Datensätze (10k+ Samples), bei denen 10% immer noch substanziell sind. Für Hyperparameter-Tuning verwenden Sie 60/20/20 (Train/Val/Test).
Was macht random_state in train_test_split?
random_state setzt den Zufallsseed für das Mischen vor dem Aufteilen. Die Verwendung desselben random_state-Werts erzeugt jedes Mal den gleichen Split, was Ihre Ergebnisse reproduzierbar macht. Jede Ganzzahl funktioniert.
Wann sollte ich stratify in train_test_split verwenden?
Verwenden Sie stratify=y, wenn Ihre Zielvariable unausgeglichen ist (z.B. 95% negativ, 5% positiv) oder wenn Sie einen kleinen Datensatz haben. Stratifikation stellt sicher, dass sowohl Train- als auch Testset den gleichen Anteil jeder Klasse haben.
Wie teile ich Daten in Train-, Validierungs- und Testsets auf?
Rufen Sie train_test_split zweimal auf. Teilen Sie zuerst in Train+Val und Test (z.B. 80/20). Teilen Sie dann Train+Val in Train und Val (z.B. 75/25 der 80%, was insgesamt 60/20/20 ergibt). Alternativ verwenden Sie sklearn.model_selection.KFold für Kreuzvalidierung.
Fazit
train_test_split() ist die Grundlage jedes Machine-Learning-Workflows in Python. Verwenden Sie es immer vor dem Training -- evaluieren Sie nie auf Trainingsdaten. Setzen Sie random_state für Reproduzierbarkeit, verwenden Sie stratify=y für unausgeglichene Klassen und denken Sie daran, Vorverarbeitungsschritte nur auf dem Trainingsset zu fitten. Für die Modellauswahl teilen Sie in drei Teile (Train/Validierung/Test) oder verwenden Sie Kreuzvalidierung für robustere Schätzungen.