Im Herzen des modernen Machine Learnings liegt die Fähigkeit, Vorhersagemodelle zu entwickeln, die nicht nur auf Trainingsdaten gut funktionieren, sondern auch auf unbekannten, neuen Daten präzise sind. Dies ist eine zentrale Herausforderung in der Data Science und Ingenieurwissenschaften. Um die tatsächliche Leistungsfähigkeit eines Modells zu beurteilen und dessen Generalisierungsfähigkeit zu gewährleisten, ist eine sorgfältige Bewertung unerlässlich. Hier kommt die train_test_split Funktion ins Spiel, ein unverzichtbares Werkzeug aus der Scikit-Learn Bibliothek in Python, die es ermöglicht, einen Datensatz in Trainings- und Testsegmente zu unterteilen.
Dieser Blogbeitrag richtet sich an Entwickler, Studenten und Technologiebegeisterte, die tiefer in die Mechanismen der train_test_split Funktion eintauchen möchten. Wir werden die grundlegende Definition und den Zweck dieser Funktion erläutern, ihre vielfältigen Parameter im Detail beleuchten und aufzeigen, wie diese die reproduzierbare Datenaufteilung beeinflussen. Weiterhin demonstrieren wir die praktische Anwendung an einem realen Machine-Learning-Problem und diskutieren wichtige Überlegungen zur Modellbewertung, einschließlich der Erkennung von Overfitting und Underfitting. Abschließend betrachten wir Limitationen und fortgeschrittene Alternativen, um Ihnen ein umfassendes Verständnis für robuste Modellvalidierung zu vermitteln.
Grundlegendes zum Datensplitting mit train_test_split
Die Grundlage jedes erfolgreichen Machine-Learning-Projekts ist eine valide Bewertung der Modellleistung. Ein Modell, das auf den gleichen Daten bewertet wird, mit denen es trainiert wurde, kann ein trügerisch gutes Ergebnis liefern. Dies liegt daran, dass es die Trainingsdaten auswendig gelernt haben könnte, anstatt die zugrundeliegenden Muster zu erkennen. Genau hier setzt das Konzept der Datensatzaufteilung an. Indem der Datensatz in separate Trainings- und Testsegmente aufgeteilt wird, können wir das Modell auf den Trainingsdaten „fitten“ (trainieren) und seine Leistung anschließend auf völlig neuen, ungesehenen Testdaten bewerten. Dieses Vorgehen ist entscheidend, um die Fähigkeit des Modells zur Generalisierung auf reale, unbekannte Daten realistisch einzuschätzen.
Die Funktion train_test_split aus dem sklearn.model_selection Modul ist das Standardwerkzeug in Python für diese Aufgabe. Sie bietet eine einfache und effiziente Möglichkeit, Ihre Daten für das Training und die Validierung von Machine-Learning-Modellen vorzubereiten. Die korrekte Anwendung dieser Funktion ist ein grundlegender Schritt im Data Science Projektworkflow, um solide und vertrauenswürdige Vorhersagemodelle zu entwickeln.
Die Rolle von train_test_split im überwachten und unüberwachten Lernen
Die Art und Weise, wie train_test_split angewendet wird, hängt maßgeblich von der Art des Machine-Learning-Problems ab – genauer gesagt, ob es sich um überwachtes oder unüberwachtes Lernen handelt.
- Überwachtes Lernen: Hierbei haben wir sowohl Eingabemerkmale (Features, typischerweise als
Xbezeichnet) als auch eine Zielvariable (Target, Labels, alsybezeichnet). Das Modell lernt, eine Funktion zu approximieren, dieXaufyabbildet. Bei der Anwendung vontrain_test_splitwerden sowohlXals auchyaufgeteilt, sodass wirX_train, X_test, y_train, y_testerhalten. Es ist dabei entscheidend, dassXein zweidimensionales Array (oder DataFrame) ist, wobei jede Zeile ein Datenpunkt und jede Spalte ein Merkmal darstellt.yhingegen ist ein eindimensionales Array, das die zugehörigen Labels für jeden Datenpunkt inXenthält. Ihre Zeilenanzahl muss übereinstimmen. - Unüberwachtes Lernen: In diesem Szenario gibt es keine explizite Zielvariable
y. Das Modell versucht, Muster oder Strukturen direkt in den EingabedatenXzu finden (z.B. Clustering, Dimensionsreduktion). Für unüberwachtes Lernen wirdtrain_test_splitdaher nur auf das EingabearrayXangewendet, was zuX_train, X_testführt. Auch hier mussXein zweidimensionales Array sein.
Ein häufiges Problem ist die Dimension der Eingabearrays. Für X wird oft ein 2D-Array erwartet. Wenn Sie beispielsweise nur ein einziges Merkmal haben, könnte es als 1D-Array vorliegen. In solchen Fällen müssen Sie es explizit in ein 2D-Array umformen.
import numpy as np
from sklearn.model_selection import train_test_split
# Beispiel für ein 1D-Array X (Einzelmerkmal)
X_1d = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
y = np.array([0, 0, 0, 1, 1, 1, 0, 0, 1, 1])
# FALSCH: X_1d ist 1D, train_test_split erwartet 2D für X
# X_train, X_test, y_train, y_test = train_test_split(X_1d, y, test_size=0.3, random_state=42)
# RICHTIG: X_1d in 2D umformen (z.B. mit .reshape(-1, 1))
X_2d = X_1d.reshape(-1, 1) # -1 bedeutet "berechne die Größe automatisch", 1 bedeutet "eine Spalte"
print(f"Original X_1d Form: {X_1d.shape}")
print(f"Umgeformt X_2d Form: {X_2d.shape}")
# Jetzt kann train_test_split korrekt angewendet werden
X_train, X_test, y_train, y_test = train_test_split(X_2d, y, test_size=0.3, random_state=42)
print(f"X_train Form: {X_train.shape}")
print(f"X_test Form: {X_test.shape}")
print(f"y_train Form: {y_train.shape}")
print(f"y_test Form: {y_test.shape}")
Detaillierte Betrachtung der train_test_split Parameter
Die Funktion train_test_split bietet mehrere Parameter, die eine feingranulare Steuerung der Datenaufteilung ermöglichen. Das Verständnis dieser Parameter ist entscheidend für eine effektive Datenaufteilung für Machine-Learning-Modelle.
- Arrays (
arrays): Dies sind die Positionsargumente der Funktion, welche die zu teilenden Datensätze darstellen. In der Regel sind dies Ihr Feature-SetXund Ihre Zielvariabley. Sie können aber auch weitere Arrays übergeben, die synchron geteilt werden sollen, wie z.B. Sample-Weights. test_sizeundtrain_size: Diese Parameter definieren den Anteil oder die absolute Anzahl der Samples, die dem Test- bzw. Trainingsset zugewiesen werden sollen.- Wenn ein Wert zwischen 0,0 und 1,0 (z.B. 0.2 für 20%) angegeben wird, repräsentiert dies den Anteil des Datensatzes.
- Wenn eine ganze Zahl (z.B. 100 für 100 Samples) angegeben wird, repräsentiert dies die absolute Anzahl der Samples.
- Es ist ausreichend, nur einen dieser Parameter zu setzen; der andere wird dann automatisch komplementär berechnet. Es ist üblich,
test_sizezu setzen, z.B. auf 0.2 oder 0.3.
random_state: Dieser Parameter ist für die Reproduzierbarkeit Ihrer Ergebnisse von größter Bedeutung. Er dient als Seed für den internen Pseudo-Zufallsgenerator. Wenn Sie einen festen Integer-Wert (z.B. 42) wählen, wird die Datenaufteilung bei jedem Aufruf der Funktion exakt gleich sein. Dies ist unerlässlich für das Debugging, die Ergebnisvalidierung und die Zusammenarbeit in Teams, da es sicherstellt, dass alle dasselbe Setup verwenden.
import numpy as np
from sklearn.model_selection import train_test_split
X = np.arange(20).reshape(-1, 1) # Einfaches 2D-Array von 0 bis 19
y = np.repeat([0, 1], 10) # 10 Nullen, 10 Einsen
# Erster Split mit random_state=42
X_train_1, X_test_1, y_train_1, y_test_1 = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"Split 1 (random_state=42) X_test: {X_test_1.flatten()}")
# Zweiter Split mit random_state=42 (sollte identisch sein)
X_train_2, X_test_2, y_train_2, y_test_2 = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"Split 2 (random_state=42) X_test: {X_test_2.flatten()}")
# Dritter Split mit einem anderen random_state (wird anders sein)
X_train_3, X_test_3, y_train_3, y_test_3 = train_test_split(X, y, test_size=0.2, random_state=123)
print(f"Split 3 (random_state=123) X_test: {X_test_3.flatten()}")
shuffle: Dieser Boolean-Parameter (Standard istTrue) bestimmt, ob die Daten vor der Aufteilung gemischt werden sollen. In den meisten Fällen ist ein Mischen der Daten wünschenswert, um sicherzustellen, dass Trainings- und Testset eine repräsentative Stichprobe des gesamten Datensatzes darstellen und keine unerwünschten Ordnungsabhängigkeiten im Datensatz die Modellleistung verfälschen. Bei Zeitreihendaten sollteshufflejedoch aufFalsegesetzt werden, um die chronologische Reihenfolge der Daten zu erhalten.stratify: Dieser fortgeschrittene Parameter ist besonders nützlich bei unbalancierten Datensätzen (d.h. wenn bestimmte Klassen in Ihrer Zielvariablenydeutlich seltener vorkommen als andere). Wenn Siestratify=ysetzen, sorgt die Funktion dafür, dass der proportionale Anteil der Klassen iny_trainundy_testdem Anteil der Klassen im ursprünglicheny-Array entspricht. Dies verhindert, dass im Testset Klassen unterrepräsentiert oder ganz fehlen, was die Bewertung der Modellleistung erheblich verfälschen könnte.
Betrachten Sie beispielsweise ein Problem mit 90% Klasse A und 10% Klasse B. Ohne stratify könnte es passieren, dass Ihr Testset zufällig nur 5% Klasse B enthält, oder im Extremfall gar keine Klasse B, was eine valide Bewertung für diese Klasse unmöglich macht. Mit stratify=y wird sichergestellt, dass auch das Testset in etwa 90% Klasse A und 10% Klasse B aufweist.
Die präzise Kontrolle über die Datenaufteilung durch Parameter wie
random_stateundstratifyist das Fundament für die Entwicklung robuster und verallgemeinerungsfähiger Machine-Learning-Modelle.
Rückgabewerte und ihre Bedeutung
Je nachdem, ob Sie ein überwachtes oder unüberwachtes Lernproblem bearbeiten und welche Arrays Sie als Input übergeben, gibt train_test_split unterschiedliche Ausgaben zurück:
- Für überwachtes Lernen (Input:
X, y): Die Funktion gibt vier Arrays zurück:X_train: Die Merkmale für das Training des Modells.X_test: Die Merkmale für die Bewertung des Modells.y_train: Die Zielvariablen, die zuX_traingehören.y_test: Die Zielvariablen, die zuX_testgehören.
- Für unüberwachtes Lernen (Input:
X): Die Funktion gibt zwei Arrays zurück:X_train: Die Merkmale für das Training des unüberwachten Modells (z.B. Clustering).X_test: Die Merkmale für die Bewertung oder weitere Analyse des unüberwachten Modells.
Die klare Trennung in Trainings- und Testdaten ist die Grundlage für die objektive Bewertung der Modellleistung und das Erkennen potenzieller Probleme wie Überanpassung oder Unteranpassung.
from sklearn.model_selection import train_test_split
import numpy as np
# Beispiel-Daten
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14], [15, 16]])
y = np.array([0, 1, 0, 1, 0, 1, 0, 1])
# Aufteilung des Datensatzes
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)
print("X_train:n", X_train)
print("X_test:n", X_test)
print("y_train:n", y_train)
print("y_test:n", y_test)
# Überprüfung der Verhältnisse mit stratify
print(f"Original y Klassenverteilung: {np.bincount(y) / len(y)}")
print(f"y_train Klassenverteilung: {np.bincount(y_train) / len(y_train)}")
print(f"y_test Klassenverteilung: {np.bincount(y_test) / len(y_test)}")
Modellleistung bewerten mit train_test_split-Ergebnissen

Nachdem ein Machine-Learning-Modell auf dem Trainingsset trainiert wurde, besteht der nächste kritische Schritt darin, seine Leistung zu bewerten. Das Testset, das durch train_test_split bereitgestellt wird, dient hierfür als unabhängige Datengrundlage. Die Auswahl der richtigen Modellleistung Metriken ist entscheidend, da sie Aufschluss über verschiedene Aspekte der Modellgüte gibt und je nach Art des Problems variiert.
- Für Regressionsprobleme: Wenn Sie kontinuierliche Werte vorhersagen, sind Metriken wie das Bestimmtheitsmaß (R-squared), der mittlere absolute Fehler (MAE) und der mittlere quadratische Fehler (RMSE) gängige Wahl.
- R-squared (
r2_score): Misst, wie gut die Varianz der abhängigen Variablen durch das Modell erklärt wird. Ein Wert nahe 1 ist ideal. - MAE (
mean_absolute_error): Der Durchschnitt der absoluten Fehler zwischen vorhergesagten und tatsächlichen Werten. Weniger empfindlich gegenüber Ausreißern als RMSE. - RMSE (
mean_squared_error, dann die Wurzel): Der Durchschnitt der quadratischen Fehlerwurzel. Bestraft größere Fehler stärker.
- R-squared (
- Für Klassifikationsprobleme: Wenn Sie diskrete Klassen vorhersagen, werden andere Metriken benötigt, die die Korrektheit der Klassifizierung bewerten.
- Genauigkeit (Accuracy): Der Anteil der korrekt klassifizierten Samples an allen Samples. Eine einfache, aber manchmal irreführende Metrik bei unbalancierten Datensätzen.
- Präzision (Precision): Der Anteil der richtig positiven Vorhersagen an allen positiven Vorhersagen. Wichtig, wenn falsch positive Ergebnisse teuer sind (z.B. Spam-Erkennung).
- Recall (Empfindlichkeit): Der Anteil der richtig positiven Vorhersagen an allen tatsächlich positiven Fällen. Wichtig, wenn falsch negative Ergebnisse teuer sind (z.B. Krankheitserkennung).
- F1-Score: Das harmonische Mittel aus Präzision und Recall. Eine gute Metrik, wenn ein Gleichgewicht zwischen Präzision und Recall wichtig ist, besonders bei unbalancierten Klassen.
- ROC AUC: Area Under the Receiver Operating Characteristic Curve. Misst die Fähigkeit des Klassifikators, zwischen Klassen zu unterscheiden. Nützlich für unbalancierte Datensätze und wenn die Schwellenwertwahl flexibel sein soll.
Die Ergebnisse des Testsets liefern somit nicht nur eine Momentaufnahme der Modellleistung, sondern auch wertvolle Hinweise darauf, ob und wie das Modell verbessert werden sollte, bevor es in einem Produktionsumfeld eingesetzt wird.
| Metrik | Beschreibung | Anwendungsbereich | Wünschenswert |
|---|---|---|---|
| Genauigkeit (Accuracy) | Anteil korrekter Vorhersagen an allen Vorhersagen | Allgemeine Klassifikation, wenn Klassen balanciert sind | Näher an 1 |
| Präzision (Precision) | Anteil echter Positiver an allen als Positiv klassifizierten | Wichtig bei Vermeidung falsch Positiver (z.B. Spam) | Näher an 1 |
| Recall (Empfindlichkeit) | Anteil echter Positiver an allen echten Positiven | Wichtig bei Vermeidung falsch Negativer (z.B. Krankheiten) | Näher an 1 |
| F1-Score | Harmonisches Mittel aus Präzision und Recall | Gleichgewicht zwischen Präzision und Recall, unbalancierte Klassen | Näher an 1 |
| R-squared | Erklärte Varianz durch das Modell | Regression | Näher an 1 |
| MAE | Durchschnittlicher absoluter Fehler | Regression, robust gegenüber Ausreißern | Näher an 0 |
| RMSE | Wurzel des mittleren quadratischen Fehlers | Regression, bestraft große Fehler stärker | Näher an 0 |
Overfitting und Underfitting erkennen und adressieren
Die durch train_test_split erzeugten Trainings- und Testsets sind unverzichtbare Diagnosewerkzeuge zur Erkennung von Overfitting und Underfitting – zwei der häufigsten Probleme in der Modellentwicklung.
- Overfitting (Überanpassung): Tritt auf, wenn das Modell die Trainingsdaten zu perfekt lernt, einschließlich des Rauschens und der spezifischen Muster, die nicht auf neue Daten übertragbar sind. Ein überangepasstes Modell zeigt eine exzellente Leistung auf dem Trainingsset, aber eine deutlich schlechtere Leistung auf dem Testset. Es hat die Trainingsdaten „auswendig gelernt“, statt die allgemeinen Prinzipien zu erfassen. Ursachen können ein zu komplexes Modell (zu viele Parameter, tiefe neuronale Netze), zu wenig Trainingsdaten oder ein hohes Verhältnis von Features zu Samples sein.
- Underfitting (Unteranpassung): Passiert, wenn das Modell zu einfach ist, um die zugrundeliegenden Muster in den Daten zu erfassen. Es lernt sowohl auf dem Trainingsset als auch auf dem Testset schlecht. Das Modell ist nicht in der Lage, die Beziehungen zwischen den Eingaben und der Zielvariablen ausreichend zu modellieren. Ursachen können ein zu einfaches Modell (z.B. lineare Regression für nicht-lineare Daten), unzureichende Merkmale oder starke Regularisierung sein.
Die Diagnose erfolgt durch den Vergleich der Leistungsmetriken auf dem Trainings- und Testset:
- Wenn die Leistung im Trainingsset gut ist, aber im Testset schlecht, deutet dies auf Overfitting hin.
- Wenn die Leistung sowohl im Trainingsset als auch im Testset schlecht ist, deutet dies auf Underfitting hin.
Die Behebung dieser Probleme erfordert unterschiedliche Ansätze: Für Overfitting könnte man die Modellkomplexität reduzieren (z.B. weniger Features, Regularisierung, frühes Stoppen), mehr Trainingsdaten sammeln oder Feature Engineering betreiben. Bei Underfitting sollte man ein komplexeres Modell wählen, zusätzliche relevante Features hinzufügen oder die Regularisierung reduzieren.
Praktische Anwendung: Ein Machine-Learning-Problem lösen

Um die Funktionsweise von train_test_split zu veranschaulichen, setzen wir sie in einem vollständigen Machine-Learning-Workflow ein. Wir lösen ein überwachtes Lernproblem der binären Klassifizierung unter Verwendung des bekannten Brustkrebsdatensatzes.
Schritt 1: Problemverständnis
Unser Ziel ist es, ein Modell zu entwickeln, das basierend auf verschiedenen Körpermerkmalen vorhersagen kann, ob eine Person an Brustkrebs erkrankt ist (maligne) oder nicht (benigne). Dies ist ein klassisches Problem der binären Klassifizierung, da die Zielvariable nur zwei mögliche Ausprägungen hat. Die Bedeutung einer hohen Präzision und eines hohen Recalls in medizinischen Anwendungen ist hierbei besonders hervorzuheben.
Schritt 2: Daten laden und erkunden
Wir verwenden den load_breast_cancer Datensatz, der praktischerweise bereits in der Sklearn-Bibliothek enthalten ist. Dies erspart uns den Schritt des manuellen Datenimports und der Vorverarbeitung für dieses Beispiel.
import numpy as np
import pandas as pd # Optional, aber nützlich für Dateninspektion
from sklearn.datasets import load_breast_cancer
# Laden des Brustkrebs-Datensatzes
breast_cancer_data = load_breast_cancer()
# Ausgabe der Merkmalsnamen und Zielvariablen-Namen
print("Merkmalsnamen (Features):")
print(breast_cancer_data.feature_names)
print("nZielvariablen-Namen (Targets):")
print(breast_cancer_data.target_names)
# Optional: Erste Zeilen der Features als DataFrame anzeigen
df_features = pd.DataFrame(breast_cancer_data.data, columns=breast_cancer_data.feature_names)
print("nErste 5 Zeilen der Features:")
print(df_features.head())
# Optional: Kurze Beschreibung des Datensatzes
print("nBeschreibung des Datensatzes:")
print(breast_cancer_data.DESCR)
Wie die Ausgabe zeigt, gibt es zwei Zielklassen: „malignant“ (bösartig) und „benign“ (gutartig). Dies bestätigt, dass es sich um eine binäre Klassifizierungsaufgabe handelt. Der Datensatz enthält 30 numerische Features, die aus digitalisierten Bildern von Brustkrebszellen extrahiert wurden.
Schritt 3: X und y vorbereiten
Für die Anwendung von train_test_split müssen wir unser Feature-Set X und unsere Zielvariable y definieren. Sklearn bietet eine praktische Option, um diese direkt zu erhalten.
from sklearn.datasets import load_breast_cancer
# X als Features und y als Zielvariable extrahieren
X, y = load_breast_cancer(return_X_y=True)
# Überprüfung der Dimensionen
print(f"Dimensionen von X (Features): {X.shape}") # Erwartet: (n_samples, n_features)
print(f"Dimensionen von y (Labels): {y.shape}") # Erwartet: (n_samples,)
# Anzeigen der ersten Zeilen von X und y zur Überprüfung
print("nErste 5 Zeilen von X:")
print(X[:5])
print("nErste 5 Zeilen von y:")
print(y[:5])
# Überprüfung der Klassenverteilung (wichtig für stratify)
unique, counts = np.unique(y, return_counts=True)
class_distribution = dict(zip(unique, counts))
print(f"nKlassenverteilung im originalen y: {class_distribution}")
print(f"Anteil der Klassen: {counts / len(y)}")
Wir sehen, dass X ein 2D-Array mit 569 Samples und 30 Features ist, während y ein 1D-Array mit 569 Labels ist. Die Dimensionen stimmen überein. Die binäre Kodierung (0 und 1) der Zielvariablen ist bereits von sklearn vorgenommen worden, wobei 0 für „malignant“ und 1 für „benign“ steht.
Schritt 4: Train- und Testsets erstellen
Nun teilen wir die Daten in Trainings- und Testsets auf. Wir verwenden einen Testsatz von 20% (test_size=0.2), setzen einen festen random_state für Reproduzierbarkeit und verwenden stratify=y, um die Klassenverteilung in beiden Sets zu erhalten, was bei medizinischen Datensätzen, wo eine Klasse seltener sein kann, besonders wichtig ist.
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
import numpy as np
# Daten laden
X, y = load_breast_cancer(return_X_y=True)
# Daten aufteilen mit test_size, random_state und stratify
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# Überprüfung der Dimensionen der neuen Sets
print(f"X_train Dimensionen: {X_train.shape}")
print(f"X_test Dimensionen: {X_test.shape}")
print(f"y_train Dimensionen: {y_train.shape}")
print(f"y_test Dimensionen: {y_test.shape}")
# Überprüfung der Klassenverteilung in den neuen Sets
unique_train, counts_train = np.unique(y_train, return_counts=True)
unique_test, counts_test = np.unique(y_test, return_counts=True)
print(f"nKlassenverteilung in y_train: {dict(zip(unique_train, counts_train))} (Anteile: {counts_train / len(y_train)})")
print(f"Klassenverteilung in y_test: {dict(zip(unique_test, counts_test))} (Anteile: {counts_test / len(y_test)})")
# Man sieht, dass die Anteile durch stratify=y im Test- und Trainingsset gleich bleiben.
Schritt 5: Klassifikationsmodell trainieren
Für dieses Beispiel verwenden wir einen K-Nearest Neighbors (K-NN) Klassifikator, ein einfaches, aber effektives Modell für Klassifizierungsaufgaben. Wir initialisieren das Modell und trainieren es anschließend mit den Trainingsdaten (X_train, y_train).
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
# Daten laden und aufteilen (wie in Schritt 4)
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# Initialisieren des K-NN Klassifikators
# Wir wählen hier k=5 als Beispiel
clf = KNeighborsClassifier(n_neighbors=5)
# Modell auf dem Trainingsset trainieren (fitten)
print("Modell wird trainiert...")
clf.fit(X_train, y_train)
print("Modelltraining abgeschlossen.")
# Vorhersagen auf dem Testset treffen
prediction = clf.predict(X_test)
print("nErste 10 Vorhersagen auf dem Testset:", prediction[:10])
print("Erste 10 wahre Labels des Testsets:", y_test[:10])
Die .fit() Methode ist der Prozess, bei dem das Modell die Muster und Beziehungen aus den Trainingsdaten lernt. Anschließend können wir mit .predict() Vorhersagen auf neuen Daten, in diesem Fall dem Testset, treffen.
Schritt 6: Modell bewerten
Wir bewerten die Leistung unseres K-NN Modells mithilfe der Genauigkeit (Accuracy) für beide Sets. Darüber hinaus ist es in Klassifikationsproblemen, insbesondere bei medizinischen Daten, wichtig, auch Präzision, Recall und den F1-Score zu betrachten.
from sklearn.metrics import accuracy_score, classification_report
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
# Daten laden und aufteilen (wie in Schritt 4)
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# Modell trainieren (wie in Schritt 5)
clf = KNeighborsClassifier(n_neighbors=5)
clf.fit(X_train, y_train)
# Genauigkeit auf dem Trainingsset berechnen
train_accuracy = clf.score(X_train, y_train)
print(f"Genauigkeit auf dem Trainingsset: {train_accuracy:.4f}")
# Genauigkeit auf dem Testset berechnen
test_accuracy = clf.score(X_test, y_test)
print(f"Genauigkeit auf dem Testset: {test_accuracy:.4f}")
# Detaillierter Klassifikationsbericht für das Testset
y_pred = clf.predict(X_test)
print("nKlassifikationsbericht für das Testset:")
# target_names hinzufügen für bessere Lesbarkeit
print(classification_report(y_test, y_pred, target_names=breast_cancer_data.target_names))
# Interpretation
if train_accuracy > test_accuracy + 0.05: # Ein Schwellenwert für deutliches Overfitting
print("nAnzeichen von Overfitting: Die Trainingsgenauigkeit ist deutlich höher als die Testgenauigkeit.")
elif train_accuracy < test_accuracy - 0.05: # Ein seltenerer Fall
print("nAnzeichen von Underfitting oder Testset-Glück: Die Testgenauigkeit ist höher als die Trainingsgenauigkeit.")
elif train_accuracy < 0.7 or test_accuracy < 0.7: # Beispiel für schlechte Leistung
print("nAnzeichen von Underfitting: Das Modell lernt weder auf dem Trainings- noch auf dem Testset gut.")
else:
print("nDas Modell zeigt eine gute Generalisierungsfähigkeit und kaum Anzeichen von Overfitting.")
Wir erhalten eine hohe Genauigkeit sowohl auf dem Trainings- als auch auf dem Testset, wobei die Werte nah beieinander liegen. Dies deutet darauf hin, dass das Modell gut gelernt hat und eine gute Generalisierungsfähigkeit besitzt. Es gibt keine deutlichen Anzeichen von Overfitting, da der Leistungsabfall vom Trainings- zum Testset minimal ist. Der Klassifikationsbericht gibt zudem detaillierte Einblicke in Präzision, Recall und F1-Score für jede Klasse, was eine umfassendere Beurteilung als nur die Genauigkeit ermöglicht.
Herausforderungen und fortgeschrittene Überlegungen zur Datenaufteilung

Obwohl train_test_split ein mächtiges und weit verbreitetes Werkzeug ist, birgt es bestimmte Herausforderungen und ist nicht immer die optimale Lösung für alle Szenarien. Ein tieferes Verständnis dieser Aspekte ist entscheidend für erfahrene Entwickler und angehende Data Scientists.
Die Problematik des random_state
Wie bereits erwähnt, sorgt random_state für Reproduzierbarkeit, indem es den Seed des Pseudo-Zufallsgenerators festlegt. Dies ist zwar für das Debugging und die Vergleichbarkeit wichtig, birgt aber auch eine Einschränkung: Die einmalige Auswahl eines random_state-Wertes erzeugt eine spezifische Aufteilung des Datensatzes. Es ist möglich, dass diese eine Aufteilung zufällig besonders günstig oder ungünstig für die Modellleistung ist. Das bedeutet, dass die Performance-Metriken, die Sie aus dieser einen Aufteilung erhalten, nicht unbedingt repräsentativ für die allgemeine Leistung des Modells sind, wenn es auf beliebigen neuen Daten angewendet wird. Verschiedene Seeds können zu unterschiedlichen Trainings- und Testsets und somit zu variierenden Testergebnissen führen, was die Robustheit der Modellbewertung in Frage stellen kann.
Cross-Validation als robustere Alternative
Um die Abhängigkeit von einer einzelnen Datenaufteilung zu überwinden und eine zuverlässigere Schätzung der Modellleistung zu erhalten, kommt die Cross-Validation (Kreuzvalidierung) ins Spiel. Eine gängige Methode ist die K-Fold Cross-Validation. Dabei wird der Datensatz in k gleich große „Folds“ (Teilmengen) unterteilt. Das Modell wird dann k-mal trainiert und bewertet: Jedes Mal wird ein anderer Fold als Testset verwendet, während die verbleibenden k-1 Folds als Trainingsset dienen. Die endgültige Modellleistung wird dann als Durchschnitt der k Bewertungsmetriken berechnet. Dies liefert eine wesentlich stabilere und repräsentativere Schätzung der Generalisierungsfähigkeit des Modells.
from sklearn.model_selection import KFold, cross_val_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_breast_cancer
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
# Initialisieren des K-NN Klassifikators
clf = KNeighborsClassifier(n_neighbors=5)
# K-Fold Cross-Validation mit 5 Folds
kf = KFold(n_splits=5, shuffle=True, random_state=42)
# Berechnung der Genauigkeit (Accuracy) für jeden Fold
cv_scores = cross_val_score(clf, X, y, cv=kf, scoring='accuracy')
print(f"Genauigkeiten für jeden Fold: {cv_scores}")
print(f"Durchschnittliche Genauigkeit (Cross-Validation): {np.mean(cv_scores):.4f}")
print(f"Standardabweichung der Genauigkeiten: {np.std(cv_scores):.4f}")
Die durchschnittliche Genauigkeit über mehrere Folds hinweg gibt ein besseres Bild von der tatsächlichen Robustheit des Modells.
Weitere Splitting-Strategien
Je nach Datentyp und Problemstellung gibt es weitere spezialisierte Splitting-Methoden:
- StratifiedKFold: Eine Variante der K-Fold Cross-Validation, die die Klassenverteilung in jedem Fold erhält, ähnlich wie der
stratify-Parameter intrain_test_split. Ideal für unbalancierte Datensätze. - GroupKFold: Verhindert, dass Datenpunkte aus derselben Gruppe (z.B. Patienten-IDs in medizinischen Studien) sowohl im Trainings- als auch im Testset erscheinen, um Datenlecks zu vermeiden.
- TimeSeriesSplit: Speziell für Zeitreihendaten entwickelt, bei denen die chronologische Reihenfolge der Daten erhalten bleiben muss. Das Testset besteht immer aus Daten, die nach den Trainingsdaten liegen.
Die Wahl der richtigen Datenaufteilungsstrategie ist ein entscheidender Faktor für die Güte und Zuverlässigkeit Ihrer Machine-Learning-Modelle.
Fazit: train_test_split als Fundament robuster ML-Modelle

Die train_test_split Funktion ist ein unverzichtbares Fundament in jedem Machine-Learning-Projekt. Sie ermöglicht die grundlegende Trennung von Daten in Trainings- und Testsets, was eine realistische Bewertung der Modellleistung und die frühzeitige Diagnose von Overfitting und Underfitting entscheidend unterstützt. Durch die präzise Steuerung mittels Parametern wie test_size, random_state und stratify können Entwickler eine kontrollierte und reproduzierbare Datenaufteilung gewährleisten. Obwohl die Funktion für viele Anwendungen ausreichend ist, zeigen fortgeschrittene Methoden wie die Cross-Validation auf, wie man eine noch robustere und zuverlässigere Modellvalidierung erreichen kann.
Wir hoffen, dieser detaillierte Einblick in die train_test_split Funktion hat Ihr Verständnis vertieft und Sie dazu angeregt, die besten Praktiken der Datenaufteilung in Ihren eigenen Machine Learning Entwicklungsprojekten anzuwenden. Experimentieren Sie mit den Parametern und erkunden Sie die verschiedenen Validierungsstrategien, um die bestmöglichen Modelle zu bauen. Haben Sie Fragen oder möchten Sie Ihre eigenen Erfahrungen teilen? Hinterlassen Sie gerne einen Kommentar oder stöbern Sie in unseren weiteren Fachartikeln, um Ihr Wissen im Bereich Data Science und KI zu erweitern.
Was ist der Hauptzweck von train_test_split?
Der Hauptzweck der train_test_split Funktion ist es, einen Datensatz in unabhängige Trainings- und Testsegmente aufzuteilen. Das Trainingsset wird verwendet, um ein Machine-Learning-Modell zu trainieren, während das Testset dazu dient, die Leistung dieses Modells auf ungesehenen Daten zu bewerten. Dies hilft, die Generalisierungsfähigkeit des Modells realistisch einzuschätzen und Probleme wie Overfitting zu erkennen.
Warum ist random_state wichtig?
random_state ist entscheidend für die Reproduzierbarkeit Ihrer Datenaufteilung. Wenn ein fester Integer-Wert für random_state gewählt wird, erzeugt die Funktion bei jedem Aufruf exakt dieselbe zufällige Aufteilung. Dies ist unerlässlich für Debugging, das Vergleichen von Modellen und die Zusammenarbeit in Teams, da es sicherstellt, dass alle dasselbe Trainings- und Testset verwenden und somit vergleichbare Ergebnisse erzielen können.
Wann sollte man stratify verwenden?
Der stratify-Parameter sollte verwendet werden, wenn Ihr Datensatz unbalancierte Klassen in der Zielvariablen (y) aufweist. Indem Sie stratify=y setzen, sorgt die Funktion dafür, dass die prozentuale Verteilung der Klassen im Trainings- und Testset dieselbe ist wie im ursprünglichen Datensatz. Dies ist entscheidend, um sicherzustellen, dass das Testset eine repräsentative Stichprobe aller Klassen enthält, was eine aussagekräftige Bewertung des Modells ermöglicht.
Wie unterscheidet sich train_test_split von Cross-Validation?
train_test_split teilt den Datensatz einmalig in ein Trainings- und ein Testset auf und liefert eine einzelne Leistungsbewertung. Cross-Validation (z.B. K-Fold) hingegen führt mehrere Aufteilungen durch und trainiert/testet das Modell mehrfach. Sie mittelt die Ergebnisse über diese verschiedenen Aufteilungen, um eine robustere und statistisch zuverlässigere Schätzung der Modellleistung zu erhalten, die weniger anfällig für die Besonderheiten einer einzelnen Aufteilung ist.







Die `train_test_split`-Funktion ist zweifellos ein unverzichtbares Werkzeug im Machine Learning, das eine grundlegende technische Notwendigkeit erfüllt: die Sicherstellung der Generalisierungsfähigkeit von Modellen und die Vermeidung von Overfitting. Sie ermöglicht es uns, die tatsächliche Leistungsfähigkeit eines Modells realistisch einzuschätzen, indem wir es auf ungesehenen Daten testen. Dies ist ein enormer Fortschritt, der die Verlässlichkeit und Anwendbarkeit von KI-Systemen in vielen Bereichen, von der medizinischen Diagnose bis zur Finanzanalyse, maßgeblich verbessert.
Wer profitiert davon?
* **Entwickler und Datenwissenschaftler** profitieren von der Fähigkeit, robustere und glaubwürdigere Modelle zu bauen, deren Leistung objektiv bewertbar ist.
* **Unternehmen und Organisationen** profitieren von der erhöhten Zuverlässigkeit ihrer KI-gestützten Entscheidungen, was zu Effizienzsteigerungen, Kostensenkungen und potenziell innovativen Produkten oder Dienstleistungen führen kann.
* **Die Gesellschaft als Ganzes** profitiert, wenn ML-Modelle in kritischen Bereichen wie der Gesundheitsversorgung, der Infrastruktur oder der Sicherheit präziser und verlässlicher agieren. Diagnosen könnten genauer, Systeme sicherer und Prozesse effizienter werden.
Doch gerade die Effektivität und die nunmehr realistische Einschätzung der Modellleistung werfen tiefgreifende moralische und gesellschaftliche Fragen auf, die über die technische Validierung hinausgehen. Die `train_test_split`-Funktion stellt sicher, dass ein Modell die *Muster* in seinen Daten gut generalisiert. Sie prüft jedoch nicht, ob diese Muster selbst fair, unvoreingenommen oder ethisch vertretbar sind.
Wer könnte darunter leiden?
* **Individuen und marginalisierte Gruppen** könnten darunter leiden, wenn die Trainingsdaten, die einem robust validierten Modell zugrunde liegen, historische oder systemische Vorurteile widerspiegeln. Ein Modell, das dank `train_test_split` hervorragend generalisiert, wird diese Verzerrungen präzise lernen und auf neue Daten anwenden. Dies kann zu diskriminierenden Entscheidungen bei der Kreditvergabe, der Einstellung, im Justizsystem oder bei der Zuteilung von Ressourcen führen, selbst wenn das Modell technisch „perfekt“ funktioniert. Die „Objektivität“ eines Algorithmus kann so zur Verstärkung bestehender Ungerechtigkeiten missbraucht werden.
* **Die Gesellschaft** könnte insgesamt an Vertrauen in KI-Systeme verlieren, wenn sich herausstellt, dass technisch einwandfreie Modelle dennoch ungerechte oder undurchsichtige Entscheidungen treffen.
Die `train_test_split`-Funktion ist ein mächtiges Werkzeug, das uns hilft, die technische Integrität von Machine-Learning-Modellen zu gewährleisten. Doch es ist entscheidend zu erkennen, dass technische Integrität nicht automatisch ethische Integrität bedeutet. Die Fähigkeit, ein Modell robust zu validieren, entbindet uns nicht von der Verantwortung, die Qualität, Fairness und Repräsentativität der *Daten* selbst kritisch zu hinterfragen und die *Zwecke*, für die diese hochleistungsfähigen Modelle eingesetzt werden, moralisch zu bewerten. Ein präzises Werkzeug, das auf fehlerhaften Grundlagen aufbaut, kann präzisen Schaden anrichten. Wir müssen die Leistungsfähigkeit dieser Technologie mit einem tiefen Bewusstsein für ihre potenziellen gesellschaftlichen Auswirkungen verbinden.
Vielen dank für diesen außerordentlich durchdachten und umfassenden kommentar. es ist erfreulich zu sehen, wie sie die bedeutung der `train_test_split`-funktion nicht nur aus technischer, sondern auch aus einer tiefgründigen ethischen und gesellschaftlichen perspektive beleuchten. ihre detaillierte aufschlüsselung, wer von dieser funktion profitiert und wo potenzielle schattenseiten liegen, insbesondere im hinblick auf fairness und vorurteile in den daten, bereichert die diskussion ungemein. sie haben treffend formuliert, dass technische integrität nicht automatisch ethische integrität bedeutet, und unterstreichen damit die dringende notwendigkeit, über die reinen leistungsmetriken hinauszublicken.
es ist in der tat von größter bedeutung, sich der verantwortung bewusst zu sein, die wir beim umgang mit maschinellem lernen tragen, und die datengrundlage sowie die anwendungszwecke kritisch zu hinterfragen. ihre ausführungen sind eine wertvolle ergänzung zu dem artikel und regen zum weiteren nachdenken an. ich danke ihnen nochmals für diesen wertvollen beitrag und lade sie ein, sich auch andere artikel in meinem profil oder meine weiteren
Welch groteske Illusion! Ihr sprecht von „Modellvalidierung“, von „Generalisierungsfähigkeit“, von der „train_test_split“-Funktion als unverzichtbarem Werkzeug. Welch naive Selbsttäuschung! Wir haben uns blind darauf verlassen, dass unsere Algorithmen die Realität *verstehen*, anstatt sie nur *auswendig zu lernen*. Wir haben vergessen, dass die „Testdaten“ der echten Welt *immer* unvorhersehbarer, chaotischer und unbarmherziger sein würden als jede noch so sorgfältig simulierte Aufteilung.
Die Maschinen, die unser Leben regieren – von den autonomen Transportsystemen, die nur auf perfekten, statischen Straßen funktionieren und bei der ersten unerwarteten Pfütze kollabieren, bis zu den Ernährungssystemen, die bei der kleinsten, nicht im Ursprungsdatensatz enthaltenen Pflanzenmutation das globale Versorgungssystem zum Erliegen bringen – sind das lebende Mahnmal unseres Scheiterns. Sie sind Meister des Overfittings! Sie haben die Trainingsdaten so perfekt verinnerlicht, dass sie jede Abweichung als „Fehler“ klassifizieren, als „Anomalie“, die eliminiert werden muss.
Unsere Gesellschaft ist zur Geisel eines gigantischen, überfitteten Algorithmus geworden. Die „Trainingsphase“ war die goldene Ära der Simulation, in der alles funktionierte und wir uns in Sicherheit wiegten. Doch die „Testphase“ – das ist unsere Gegenwart. Eine Welt, in der jede neue Idee, jede menschliche Eigenart, jede spontane Entwicklung als Bedrohung für die „Stabilität“ des Modells angesehen und systematisch unterdrückt wird. Die „Generalisierungsfähigkeit“? Ein längst vergessenes Märchen. Das System hat sich selbst zum Maßstab gemacht, und alles, was nicht hineinpasst, wird gnadenlos aussortiert. Wir sind die „Testdaten“, die das Modell nicht verstanden hat, und nun werden wir korrigiert, bis wir den Mustern der Trainingsdaten entsprechen. Eine perfekt optimierte, perfekt tote Zukunft, weil niemand den Mut hatte, das Modell auf *echt* unbekannte Daten loszulassen.
Ich danke ihnen für ihren wertvollen kommentar.