Trainings-Test-Aufteilung

In der Welt des maschinellen Lernens sind Daten der Treibstoff, der jedes Modell antreibt. Wie Sie diesen Treibstoff jedoch richtig einsetzen, entscheidet darüber, ob Ihr Modell zu einer intelligenten Maschine wird, die die Zukunft präzise vorhersagen kann, oder zu einem Papagei, der nur auswendig lernen kann.

Heute tauchen wir tief in ein entscheidendes und grundlegendes Konzept des maschinellen Lernens ein:die Aufteilung zwischen Trainings- und Testsets. Dies ist der erste Schritt beim Aufbau jedes zuverlässigen Modells und der Schlüssel zur Bewertung der wahren Leistungsfähigkeit eines Modells.

Einfach ausgedrückt ist die Aufteilung in Trainings- und Testsets wie das Lernen und das Ablegen von Prüfungen während der Schulzeit:

  • Der Trainingsdatensatzumfasst die Lehrbücher und Übungsaufgaben des Schülers; das Modell verwendet ihn, um die Regeln und Muster in den Daten zu lernen.
  • Das Testsetist die Abschlussprüfung; das Modell verwendet es, um zu prüfen, ob es das Wissen wirklich beherrscht, anstatt nur die Antworten auf die Übungsaufgaben (Trainingsset) auswendig zu lernen.

Warum ist es notwendig, Trainings- und Testsets aufzuteilen?

Stellen Sie sich einen Schüler vor, der nur die vom Lehrer gestellten Probefragen wiederholt hat, und die Prüfungsfragen waren genau dieselben Probefragen. Er bekam eine perfekte Punktzahl. Beweist das, dass er das Thema wirklich verstanden hat? Offensichtlich nicht. Er hat vielleicht nur die Antworten auswendig gelernt.

Beim maschinellen Lernen: Wenn wir ein Modell mitallen Datentrainieren und dann diegleichen Datenverwenden, um seine Leistung zu bewerten, machen wir denselben Fehler. Das Modell wird außergewöhnlich gut erscheinen, weil es jedes Detail der Daten "gesehen" und "erinnert" hat, einschließlich des Rauschens und zufälliger Übereinstimmungen. Dieses Phänomen nennt manÜberanpassung。

Ein überangepasstes Modell ist wie ein Schüler, der nur Beispielaufgaben aufsagen kann; sobald es auf neue, nie gesehene Fragen (neue Daten) trifft, schneidet es sehr schlecht ab. Seine "Generalisierungsfähigkeit" ist sehr schwach.

Deshalb müssen wir die Daten in zwei Teile aufteilen:

  1. Trainingsset: wird verwendet, umLehrendas Modell zu trainieren und es lernen zu lassen.
  2. Testset: wird verwendet, umzu prüfendas Modell zu bewerten und einzuschätzen, wie es mitneuen Daten umgeht, die es noch nie gesehen hat.

Das Testset muss vollständig vom Trainingsset isoliert sein und darfnichtvom Modell während des gesamten Trainingsprozesses gesehen werden. Nur so können die Bewertungsergebnisse auf dem Testset die wahre Generalisierungsfähigkeit des Modells objektiv widerspiegeln.


Wie man aufteilt: gängige Methoden und Strategien

Das Aufteilen von Daten klingt einfach, aber es gibt viel zu beachten. Verschiedene Aufteilungsstrategien eignen sich für verschiedene Szenarien.

1. Einfache zufällige Aufteilung

Dies ist die grundlegendste und gebräuchlichste Methode. Der gesamte Datensatz wird zufällig gemischt und dann nach einem bestimmten Verhältnis in zwei Teile aufgeteilt.

Beispiel

# Beispiel: Verwenden Sie die scikit-learn-Bibliothek von Python, um eine zufällige Aufteilung durchzuführen
from sklearn.model_selection import train_test_split

# Angenommen, X sind die Merkmalsdaten und y sind die Labeldaten
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

print(f"Anzahl der Stichproben im Trainingsset: {len(X_train)}")
print(f"Anzahl der Stichproben im Testset: {len(X_test)}")

Code-Erklärung:

  • train_test_split: Dies ist die Kernfunktion in scikit-learn zum Aufteilen von Daten.
  • X, y: Die Eingabe-Merkmalsdaten und die entsprechenden Labels.
  • test_size=0.2: Gibt an, dass der Größenanteil des Testsets 20% beträgt (d. h. das Trainingsset macht 80% aus). Sie können auchtrain_size=0.8verwenden, um es anzugeben.
  • random_state=42: Legen Sie einen Zufallsseed fest. Dadurch wird sichergestellt, dass das Aufteilungsergebnis bei jedem Ausführen des Codes exakt gleich ist, was für die Reproduzierbarkeit von Experimenten entscheidend ist. Sie können ihn auf eine beliebige ganze Zahl setzen.

2. Stratifizierte Stichprobenaufteilung

In Klassifikationsproblemen kann eine einfache zufällige Aufteilung, wenn die Klassenverteilung des Datensatzes unausgewogen ist (z. B. 90% Klasse A, 10% Klasse B), dazu führen, dass sich die Klassenanteile im Trainings- und Testset stark unterscheiden, was die Fairness der Bewertung beeinträchtigt.

Stratifizierte Stichprobenziehungstellt sicher, dass die Anteile jeder Klasse in den Trainings- und Testsets mit dem ursprünglichen Datensatz übereinstimmen.

Beispiel

# Beispiel: stratifizierte Stichprobenziehung in einem Klassifikationsproblem verwenden
from sklearn.model_selection import train_test_split

# Angenommen, y sind die Klassifikationslabels
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)

# Klassenverteilung nach dem Aufteilen überprüfen
from collections import Counter
print("Klassenverteilung der Originaldaten:", Counter(y))
print("Klassenverteilung des Trainingssets:", Counter(y_train))
print("Klassenverteilung des Testsets:", Counter(y_test))

Code-Erklärung:

  • stratify=y: Dies ist der entscheidende Parameter. Er weist die Funktion an, gemäßyder Klassenverteilung der Labels zu stratifizieren, wenn eine stratifizierte Stichprobenziehung durchgeführt wird.

3. Aufteilung von Zeitreihendaten

Bei Zeitreihendaten (z. B. Aktienkurse, tägliche Temperaturen) gibt es zeitliche Abhängigkeiten zwischen den Datenpunkten. Wir können nicht zufällig mischen, da zukünftige Daten nicht verwendet werden können, um die Vergangenheit vorherzusagen.

Die übliche Praxis ist, in chronologischer Reihenfolge aufzuteilen:Verwende die ersten 80 % der Daten nach Zeit als Trainingsset und die letzten 20 % als Testset.。

Beispiel

# Beispiel: sequenzielle Aufteilung von Zeitreihendaten
split_index = int(len(X) * 0.8) # Berechne den Index an der 80%-Position

X_train, X_test = X[:split_index], X[split_index:]
y_train, y_test = y[:split_index], y[split_index:]

print(f"Zeitbereich des Trainingssets: erste {split_index} Stichproben")
print(f"Zeitbereich des Testsets: letzte {len(X) - split_index} Stichproben")

Wie wählt man das Aufteilungsverhältnis?

Dies ist eine häufige Frage, aber es gibt keine feste Antwort. Häufige Verhältnisse sind:

Verhältnis (Trainingsset:Testset) Anwendungsszenario Vorteile Nachteile
70:30 Klassische Wahl für kleine bis mittelgroße Datensätze (Tausende bis Zehntausende von Stichproben) Gleicht die Größe der Trainingsdaten und die Zuverlässigkeit der Bewertung aus Bei extrem kleinen Datensätzen kann ein 30%-Testset zu wenige Stichproben enthalten, wodurch die Evaluierung instabil wird
80:20 Derzeit eine beliebtere Standardwahl, besonders geeignet für Deep Learning Bietet dem Modell mehr Daten zum Lernen Das Testset ist relativ klein, daher kann die Varianz der Evaluierung etwas größer sein
90:10 oder 95:5 Wenn die Datenmenge sehr begrenzt ist Maximiert die Nutzung begrenzter Daten für das Training Das Testset ist zu klein, daher können die Evaluierungsergebnisse unzuverlässig sein und nur eine geringe Konfidenz haben

Kernprinzipien:

  1. Stellen Sie sicher, dass das Trainingsset groß genug ist: Das Modell benötigt genügend Daten, um wirksame Muster zu lernen.
  2. Stellen Sie sicher, dass das Testset groß genug ist: Das Testset muss eine statistisch zuverlässige Leistungsbewertung ermöglichen. Normalerweise sollte das Testset mindestens ein paar hundert Stichproben enthalten, um stabile Evaluierungsergebnisse zu erzielen.
  3. Je größer die Datenmenge,desto relativkleinerkann der dem Testset zugewiesene Anteil sein, weil selbst ein sehr kleiner Anteil eine große Anzahl von Stichproben darstellen kann.

Fortgeschrittene Konzepte: Validierungsset und Kreuzvalidierung

In realen Projekten müssen wir nicht nur das endgültige Modell bewerten, sondern während des Trainings auch dieHyperparameterdes Modells (wie Lernrate, Baumtiefe usw.) abstimmen. Wenn wir das Testset direkt zum Abstimmen von Parametern verwenden, wird das Testset erneut "kontaminiert" und verliert seine Unparteilichkeit als "letzter Prüfer".

Zu diesem Zweck führen wir dasValidierungsset ein。

Dreiteilige Datenaufteilung: Trainings-, Validierungs- und Testset

  1. Trainingsset: wird zum Lernen der Modellparameter verwendet.
  2. Validierungsset: wird zum Abstimmen von Hyperparametern, zur Modellauswahl oder für frühzeitiges Stoppen während des Trainings verwendet. Es entspricht einer "Probeprüfung".
  3. Testset: wird für die abschließende, einmalige Leistungsbewertung verwendet, nachdem sowohl das Modell als auch die Hyperparameter festgelegt wurden. Es ist die "Abschlussprüfung".

Beispiel

# Beispiel: Zuerst Trainings+Validierungsset und Testset abtrennen, dann ein Validierungsset vom Trainings+Validierungsset abspalten
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.15, random_state=42) # Zuerst 15% als endgültiges Testset beiseitelegen
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.176, random_state=42) # Dann aus den verbleibenden 85% etwa 15% als Validierungsset beiseitelegen

# Berechne das Verhältnis: 0.85 * 0.176 ≈ 0.15, endgültiges Verhältnis ist etwa 70:15:15
print(f"Trainingsset: {len(X_train)}, Validierungsset: {len(X_val)}, Testset: {len(X_test)}")

K-fache Kreuzvalidierung

Wenn die Datenmenge nicht groß ist, verringert das Abspalten eines separaten Validierungssets die Trainingsdaten zusätzlich.K-fache Kreuzvalidierungist eine leistungsfähigere Lösung.

Ihr Ablauf ist wie folgt, und sie kann begrenzte Daten effektiv nutzen:

Beispiel

flowchart TD
A[Originaldatensatz] --> B[Zufällig mischen und gleichmäßig in K Teile aufteilen]
B --> C{Für K Runden wiederholen}
C --> D[Runde i: Den i-ten Teil als Validierungsset verwenden]
D --> E[Die verbleibenden K-1 Teile als Trainingsset zusammenführen]
E --> F[Das Modell für diese Runde auf dem Trainingsset trainieren]
F --> G[Score Si auf dem Validierungsset für diese Runde auswerten]
    G --> C
C -- Nach Abschluss von K Runden --> H[Berechne den Durchschnitt der K Scores als abschließende Bewertung]

Beispiel

# Beispiel: Modell mit 5-facher Kreuzvalidierung evaluieren
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression

model = LogisticRegression()
scores = cross_val_score(model, X, y, cv=5) # cv=5 bedeutet 5-fache Kreuzvalidierung

print(f"Scores für jeden Fold: {scores}")
print(f"Durchschnittlicher Score: {scores.mean():.4f} (+/- {scores.std()*2:.4f})") # Mittelwert und Standardabweichung ausgeben

Vorteile der Kreuzvalidierung:

  • Nutzt alle Daten vollständig für Training und Validierung.
  • Die Evaluierungsergebnisse sind stabiler und zuverlässiger (da sie der Durchschnitt mehrerer Evaluierungen sind).
  • Es ist der Goldstandard für Modellauswahl und Hyperparameter-Tuning bei kleinen bis mittelgroßen Datensätzen.

Praktische Übung: Erlebe die Datenaufteilung selbst

Jetzt üben wir mit einem einfachen Datensatz.

Beispiel

# 1. Notwendige Bibliotheken importieren
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# 2. Iris-Datensatz laden
iris = load_iris()
X, y = iris.data, iris.target
print(f"Datensatzform: Merkmale {X.shape}, Labels {y.shape}")

# 3. Einfache zufällige Aufteilung (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"Zufällige Aufteilung -> Trainingssatz: {X_train.shape}, Testsatz: {X_test.shape}")

# 4. Stratifizierte zufällige Aufteilung
X_train_s, X_test_s, y_train_s, y_test_s = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)
print(f"Stratifizierte Aufteilung -> Trainingssatz: {X_train_s.shape}, Testsatz: {X_test_s.shape}")

# 5. Auswirkung der Stratifizierung prüfen
print("\n"Klassenverteilung der Originaldaten:", np.bincount(y))
print("Verteilung des Testsatzes nach zufälliger Aufteilung:", np.bincount(y_test)) # Möglicherweise unausgewogen
print("Verteilung des Testsatzes nach stratifizierter Aufteilung:", np.bincount(y_test_s)) # Sollte proportional zur ursprünglichen Verteilung sein

Deine Aufgabe:

  1. Führe den obigen Code aus und beobachte die Ausgabeergebnisse.
  2. Versuche, zu änderntest_sizeauf 0.3, und beobachte die Änderung der Größen des Trainings- und Testsets.
  3. Versuche, zu ändernrandom_stateauf eine andere Zahl (z. B. 7), führe den Code erneut aus und beobachte, ob sich die Aufteilungsergebnisse ändern.
  4. (Herausforderung) Setze nichtrandom_stateden Parameter, führe den Code mehrmals aus und beobachte, ob die Aufteilungsergebnisse jedes Mal gleich sind.

Zusammenfassung und Kernpunkte

  • Hauptzweck: Das Aufteilen der Trainings- und Testsets dient dazu,die Generalisierungsfähigkeit des Modells zu bewerten, Overfitting zu verhindern und sicherzustellen, dass das Modell mit neuen Daten umgehen kann.
  • Goldene Regel:Das Testset muss während des gesamten Trainingsprozesses vollständig vertraulich behandelt werden, und nur für die abschließende Bewertung verwendet werden.
  • Aufteilungsmethoden:
    • Zufällige Aufteilung: Die am häufigsten verwendete.
    • Stratifizierte Aufteilung: Geeignet für unausgewogene Daten in Klassifikationsproblemen.
    • Sequenzielle Aufteilung: Geeignet für Zeitreihendaten.
  • Aufteilungsverhältnis: Es gibt keinen absoluten Standard; es ist ein Kompromiss zwischen "ausreichendem Training" und "zuverlässiger Bewertung" erforderlich. 80:20 oder 70:30 sind übliche Ausgangspunkte.
  • Fortgeschrittene Werkzeuge:
    • Validierungssatz: Wird zur Modellabstimmung verwendet und schützt die Reinheit des Testsatzes.
    • K-fache Kreuzvalidierung: Ein leistungsstarkes Werkzeug zur Bewertung und Abstimmung bei kleinen bis mittelgroßen Datensätzen, das robustere Ergebnisse liefert.
Andere Erweiterungen