Erstellen eines Entscheidungsbaums

In diesem Modul verwenden Sie die YDF-Bibliothek (Yggdrasil Decision Forest), um einen Entscheidungsbaum zu trainieren und zu interpretieren.

Dieses Modul basiert auf dem 🧭 Einführungsleitfaden für YDF.

Grundlegendes

Führen Sie vor dem Analysieren des Datensatzes die folgenden Schritte aus:

  1. Erstellen Sie ein neues Colab-Notebook.
  2. Installieren Sie die YDF-Bibliothek, indem Sie die folgende Codezeile in Ihr neues Colab-Notebook einfügen und ausführen:
    !pip install ydf -U
  3. Importieren Sie die folgenden Bibliotheken:
    import ydf
    import numpy as np
    import pandas as pd

Das Palmer-Pinguin-Dataset

In diesem Colab wird das Dataset „Palmer Penguins“ verwendet, das Größenmessungen für drei Pinguinarten enthält:

  • Kinnriemen
  • Gentoo
  • Adelie

Dies ist ein Klassifizierungsproblem. Ziel ist es, die Pinguinart anhand der Daten im Palmer's-Penguins-Dataset vorherzusagen. Hier sind die Pinguine:

Drei verschiedene Pinguinarten.

Abbildung 16. Drei verschiedene Pinguinarten. Bild von @allisonhorst

 

Im folgenden Code wird eine Pandas-Funktion aufgerufen, um den Palmer-Pinguin-Datensatz in den Arbeitsspeicher zu laden:

path = "https://storage.googleapis.com/download.tensorflow.org/data/palmer_penguins/penguins.csv"
dataset = pd.read_csv(path)
label = "species"

# Display the first 3 examples.
dataset.head(3)

In der folgenden Tabelle sind die ersten drei Beispiele im Palmer-Pinguin-Dataset formatiert:

Tabelle 3. Die ersten drei Beispiele in „Palmer Penguins“

Gattung Insel bill_length_mm bill_depth_mm flipper_length_mm body_mass_g Sex Jahr
0 Adelie Torgersen 39.1 18,7 181,0 3750,0 Männlich 2007
1 Adelie Torgersen 39,5 17,4 186,0 3.800,0 weiblich 2007
2 Adelie Torgersen 40.3 18.0 195,0 3.250,0 weiblich 2007

Der vollständige Datensatz enthält eine Mischung aus numerischen (z. B. bill_depth_mm), kategorischen (z. B. island) und fehlenden Merkmalen. Im Gegensatz zu neuronalen Netzwerken unterstützen Entscheidungsbäume alle diese Merkmaltypen nativ. Sie müssen also keine One-Hot-Codierung, Normalisierung oder zusätzliche „is_present“-Funktion durchführen.

In der folgenden Codezelle wird der Datensatz in ein Trainings- und ein Test-Dataset aufgeteilt:

# Use the ~20% of the examples as the testing set
# and the remaining ~80% of the examples as the training set.
np.random.seed(1)
is_test = np.random.rand(len(dataset)) < 0.2

train_dataset = dataset[~is_test]
test_dataset = dataset[is_test]

print("Training examples: ", len(train_dataset))
# >> Training examples: 272

print("Testing examples: ", len(test_dataset))
# >> Testing examples: 72

Entscheidungsbäume mit Standardhyperparametern trainieren

Sie können Ihren ersten Entscheidungsbaum mit dem CART-Lernalgorithmus (Classification and Regression Trees) trainieren, ohne hyperparameters anzugeben. Das liegt daran, dass der ydf.CartLearner-Lernalgorithmus gute Standardwerte für Hyperparameter bietet. Weitere Informationen zur Funktionsweise dieses Modelltyps erhalten Sie später im Kurs.

model = ydf.CartLearner(label=label).train(train_dataset)

Im vorherigen Aufruf wurden keine Spalten als Eingabemerkmale angegeben. Daher wird jede Spalte im Trainings-Dataset verwendet. Außerdem wurde in der Aufrufanfrage nicht die Semantik (z. B. numerisch, kategorisch, Text) der Eingabefeatures angegeben. Daher werden die Feature-Semantiken automatisch abgeleitet.

Rufen Sie model.plot_tree() auf, um den resultierenden Entscheidungsbaum zu sehen:

model.plot_tree()

In Colab können Sie mit der Maus Details zu bestimmten Elementen anzeigen lassen, z. B. die Klassenverteilung in jedem Knoten.

Ein Entscheidungsbaum, der mit den Standardhyperparametern trainiert wurde.

Abbildung 17. Ein Entscheidungsbaum, der mit Standardhyperparametern trainiert wurde.

In Colab wird angezeigt, dass die Wurzelbedingung 243 Beispiele enthält. Sie erinnern sich jedoch, dass das Trainingsdataset 272 Beispiele enthielt. Die verbleibenden 29 Beispiele wurden automatisch für die Validierung und den Baumschnitt reserviert.

Mit der ersten Bedingung wird der Wert von bill_depth_mm geprüft. In den Tabellen 4 und 5 sehen Sie die Wahrscheinlichkeit für verschiedene Arten, je nach Ergebnis der ersten Bedingung.

Tabelle 4. Wahrscheinlichkeit verschiedener Arten bei bill_depth_mm ≥ 42.3

Spezies Wahrscheinlichkeit
Adelie (rot) 8 %
Gentoo (blau) 58 %
Kinnriemen (grün) 36 %

 

Tabelle 5. Wahrscheinlichkeit verschiedener Arten bei bill_depth_mm < 42.3

Spezies Wahrscheinlichkeit
Adelie (rot) 97 %
Gentoo (blau) 2 %
Kinnriemen (grün) 0 %

bill_depth_mm ist ein numerisches Merkmal. Daher wurde der Wert 42, 3 mit dem Algorithmus Exakte Aufteilung für binäre Klassifizierung mit numerischen Merkmalen ermittelt.

Wenn bill_depth_mm ≥ 42.3 wahr ist, wird weiter getestet, ob die flipper_length_mm ≥ 207.5 die Gentoos und die Gentoos + Adelie fast perfekt voneinander trennen kann.

Der folgende Code gibt die Trainings- und Testgenauigkeit des Modells an:

train_evaluation = model.evaluate(train_dataset)
print("train accuracy:", train_evaluation.accuracy)
# >> train accuracy:  0.9338

test_evaluation = model.evaluate(test_dataset)
print("test accuracy:", test_evaluation.accuracy)
# >> test accuracy:  0.9167

Es ist selten, aber möglich, dass die Testgenauigkeit höher ist als die Trainingsgenauigkeit. In diesem Fall unterscheidet sich der Testsatz möglicherweise vom Trainingssatz. Dies ist hier jedoch nicht der Fall, da die Trainings- und Testdaten zufällig aufgeteilt wurden. Eine wahrscheinlichere Erklärung ist, dass der Testdatensatz sehr klein ist (nur 72 Beispiele), sodass die Genauigkeitsschätzung ungenau ist.

In der Praxis ist für einen so kleinen Datensatz die Kreuzvalidierung vorzuziehen, da damit genauere Bewertungsmesswerte berechnet werden. In diesem Beispiel fahren wir jedoch zur Vereinfachung mit dem Training und Testen fort.

Modell-Hyperparameter verbessern

Das Modell ist ein einzelner Entscheidungsbaum, der mit Standardhyperparameterwerten trainiert wurde. So erhalten Sie bessere Vorhersagen:

  1. Verwenden Sie einen leistungsstärkeren Lernalgorithmus wie einen Zufallswald oder ein Gradient Boosting-Modell. Diese Lernalgorithmen werden auf der nächsten Seite erläutert.

  2. Optimieren Sie den Hyperparameter anhand Ihrer Beobachtungen und Ihrer Intuition. Der Leitfaden zur Modellverbesserung kann Ihnen dabei helfen.

  3. Mit der Hyperparameter-Abstimmung können Sie automatisch eine große Anzahl möglicher Hyperparameter testen.

Da wir den Algorithmus für den Random Forest und den Gradient Boosted Tree noch nicht kennen und die Anzahl der Beispiele zu klein ist, um eine automatische Hyperparameter-Optimierung durchzuführen, verbessern Sie das Modell manuell.

Der Entscheidungsbaum oben ist klein und das Blatt mit dem Beispiel „61“ enthält eine Mischung aus Adelie- und Zügel-Labels. Warum hat der Algorithmus dieses Blatt nicht weiter unterteilt? Hierfür gibt es zwei mögliche Gründe:

  • Möglicherweise wurde die Mindestanzahl von Samples pro Blatt (standardmäßig min_examples=5) erreicht.
  • Der Baum wurde möglicherweise geteilt und dann beschnitten, um ein Überanpassen zu verhindern.

Reduzieren Sie die Mindestanzahl von Beispielen auf 1 und sehen Sie sich die Ergebnisse an:

model = ydf.CartLearner(label=label, min_examples=1).train(train_dataset)
model.plot_tree()

Ein Entscheidungsbaum, der mit „min_examples=1“ trainiert wurde.

Abbildung 18. Ein Entscheidungsbaum, der mit „min_examples=1“ trainiert wurde.

 

Der Endknoten mit 61 Beispielen wurde mehrmals weiter unterteilt.

Um festzustellen, ob eine weitere Aufteilung des Knotens sinnvoll ist, bewerten wir die Qualität dieses neuen Modells anhand des Test-Datasets:

print(model.evaluate(test_dataset).accuracy)
# >> 0.97222

Die Qualität des Modells hat sich verbessert, die Testgenauigkeit ist von 0,9167 auf 0,97222 gestiegen. Diese Änderung des Hyperparameters war eine gute Idee.

Vorherige Entscheidungsforste

Wenn wir die Hyperparameter weiter verbessern, könnten wir wahrscheinlich eine perfekte Genauigkeit erreichen. Anstelle dieses manuellen Prozesses können wir jedoch ein leistungsstärkeres Modell wie einen Random Forest trainieren und prüfen, ob es besser funktioniert.

model = ydf.RandomForestLearner(label=label).train(train_dataset)
print("Test accuracy: ", model.evaluate(test_dataset).accuracy)
# >> Test accuracy: 0.986111

Die Genauigkeit des Random Forest ist besser als die unseres einfachen Baums. Auf den nächsten Seiten erfahren Sie, warum.

Nutzung und Einschränkungen

Wie bereits erwähnt, ist die Qualität eines einzelnen Entscheidungsbaums oft geringer als die moderner Methoden des maschinellen Lernens wie Random Forests, Gradient Boosting Trees und neuronale Netze. In den folgenden Fällen sind Entscheidungsbäume jedoch weiterhin nützlich:

  • Als einfacher und kostengünstiger Referenzwert zur Bewertung komplexerer Ansätze.
  • Wenn es einen Kompromiss zwischen Modellqualität und Interpretierbarkeit gibt.
  • Als Proxy für die Interpretation des Entscheidungsforst-Modells, das im Kurs später behandelt wird.