Erstellen eines Entscheidungsbaums

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

Dieses Modul basiert auf dem Tutorial 🧭 YDF-Erste Schritte.

Grundlegendes

Gehen Sie vor der Analyse des Datasets so vor:

  1. Erstellen Sie ein neues Colab-Notebook.
  2. Installieren Sie die YDF-Bibliothek. Dazu platzieren und führen Sie die folgende Codezeile in Ihrem neuen Colab-Notebook aus:
    !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 Palmer Penguins-Dataset verwendet, das Größenmessungen für drei Pinguinarten enthält:

  • Zügelriemen
  • Eselspinguine
  • Adeliepinguine

Dies ist ein Klassifizierungsproblem. Das Ziel besteht darin, die Pinguinart anhand von Daten im Palmer-Pinguin-Dataset vorherzusagen. Hier sind die Pinguine:

Drei verschiedene Pinguinarten.

Abbildung 16. Drei verschiedene Pinguinarten. Bild von @allisonhorst

 

Der folgende Code ruft eine pandas-Funktion auf, um das Palmer Penguins-Dataset 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 werden die ersten drei Beispiele im Palmer Penguins-Dataset formatiert:

Tabelle 3. Die ersten drei Beispiele bei Palmer Penguins

Gattung Insel bill_length_mm bill_depth_mm flipper_length_mm body_mass_g geschlecht Jahr
0 Adeliepinguine Torgersen 39,1 18,7 181,0 3.750,0 männlich 2007
1 Adeliepinguine Torgersen 39,5 17,4 186,0 3.800,0 weiblich 2007
2 Adeliepinguine Torgersen 40,3 18.0 195,0 3.250,0 weiblich 2007

Das vollständige Dataset enthält eine Mischung aus numerischen (z. B. bill_depth_mm), kategorialen (z. B. island) und fehlenden Elementen. Im Gegensatz zu neuronalen Netzwerken unterstützen Entscheidungsstrukturen alle diese Featuretypen nativ, sodass Sie keine One-Hot-Codierung, Normalisierung oder ein zusätzliches „is_present“-Feature verwenden müssen.

Die folgende Codezelle teilt das Dataset in Trainings- und Test-Datasets auf:

# 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 Standard-Hyperparametern trainieren

Sie können Ihren ersten Entscheidungsbaum mit dem Lernalgorithmus CART (Classification and Regression Trees) (auch als Learner bezeichnet) trainieren, ohne Hyperparameter anzugeben. Das liegt daran, dass der Learner ydf.CartLearner gute Standardwerte für Hyperparameter bereitstellt. Im weiteren Verlauf dieses Kurses erfahren Sie mehr darüber, wie diese Art von Modell funktioniert.

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

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

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

model.plot_tree()

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

Ein Entscheidungsbaum, der mit Standard-Hyperparametern trainiert wurde.

Abbildung 17. Ein mit Standard-Hyperparametern trainierter Entscheidungsbaum.

Colab zeigt an, dass die Stammbedingung 243 Beispiele enthält. Wie Sie sich vielleicht erinnern, enthielt das Trainings-Dataset 272 Beispiele. Die verbleibenden 29 Beispiele wurden automatisch für die Validierung und die Baumbereinigung reserviert.

Mit der ersten Bedingung wird der Wert von bill_depth_mm getestet. Die Tabellen 4 und 5 zeigen die Wahrscheinlichkeit verschiedener Arten in Abhängigkeit vom Ergebnis der ersten Bedingung.

Tabelle 4. Wahrscheinlichkeit unterschiedlicher Arten, wenn bill_depth_mm ≥ 42.3

Art Likelihood
Adelie (rot) 8 %
Eselspinguine (blau) 58 %
Zügel (grün) 36 %

 

Tabelle 5. Wahrscheinlichkeit unterschiedlicher Arten, wenn bill_depth_mm < 42.3

Art Likelihood
Adelie (rot) 97 %
Eselspinguine (blau) 2 %
Zügel (grün) 0 %

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

Wenn bill_depth_mm ≥ 42.3 „True“ ist, werden weitere Tests ausgeführt, ob der flipper_length_mm ≥ 207.5 die Gentoos und die Eselspinguine und Adelie nahezu perfekt trennen kann.

Der folgende Code sorgt für die Trainings- und Testgenauigkeit des Modells:

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 als die Trainingsgenauigkeit ist. In diesem Fall unterscheidet sich das Test-Dataset möglicherweise vom Trainings-Dataset. Dies ist hier jedoch nicht der Fall, da Training und Test zufällig aufgeteilt wurden. Eine wahrscheinlichere Erklärung ist, dass das Test-Dataset sehr klein ist (nur 72 Beispiele), sodass die Genauigkeitsschätzung ungenau ist.

In der Praxis ist für ein derart kleines Dataset die Verwendung der Kreuzvalidierung zu bevorzugen, da dadurch genauere Auswertungsmesswerte berechnet werden könnten. In diesem Beispiel fahren wir jedoch der Einfachheit halber mit einem Training und Tests fort.

Modell-Hyperparameter verbessern

Das Modell besteht aus einem einzelnen Entscheidungsbaum, der mit Standard-Hyperparameterwerten trainiert wurde. So erhalten Sie bessere Vorhersagen:

  1. Verwenden Sie einen leistungsstärkeren Learner wie z. B. einen Random Forest oder ein Gradienten-Boosting Tree-Modell. Diese Lernalgorithmen werden auf der nächsten Seite erläutert.

  2. Sie können den Hyperparameter anhand Ihrer Beobachtungen und Ihrer Intuition optimieren. Der Leitfaden zur Verbesserung des Modells kann hilfreich sein.

  3. Verwenden Sie die Hyperparameter-Abstimmung, um eine große Anzahl möglicher Hyperparameter automatisch zu testen.

Da wir den Algorithmus für Random Forest- und Gradienten-Boosting-Bäume noch nicht gesehen haben und die Anzahl der Beispiele zu klein für eine automatische Hyperparameter-Abstimmung ist, werden Sie das Modell manuell verbessern.

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

  • Die Mindestanzahl von Stichproben pro Blatt (standardmäßig min_examples=5) wurde möglicherweise erreicht.
  • Der Baum wurde möglicherweise geteilt und dann beschnitten, um eine Überanpassung zu vermeiden.

Reduzieren Sie die Mindestanzahl von Beispielen auf 1, um die Ergebnisse zu sehen:

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

Ein mit min_examples=1 trainierter Entscheidungsbaum.

Abbildung 18. Ein mit min_examples=1 trainierter Entscheidungsbaum.

 

Der Blattknoten mit 61 Beispielen wurde mehrmals weiter unterteilt.

Um festzustellen, ob eine weitere Unterteilung des Knotens wertvoll ist, bewerten wir die Qualität dieses neuen Modells mit dem Test-Dataset:

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

Die Qualität des Modells hat sich mit einer Testgenauigkeit von 0,9167 bis 0,97222 erhöht. Diese Änderung des Hyperparameters war eine gute Idee.

Vorheriger Schritt: „Entscheidende Wälder“

Wenn wir die Hyperparameter weiter verbessern, können wir wahrscheinlich eine perfekte Genauigkeit erreichen. Statt zu diesem manuellen Prozess können wir jedoch auch ein leistungsstärkeres Modell wie z. B. eine Random-Gesamtstruktur trainieren, um zu sehen, ob es besser funktioniert.

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

Die Genauigkeit der Random Forest ist besser als bei unserem einfachen Baum. Auf den nächsten Seiten erfahren Sie, warum.

Nutzung und Einschränkung

Wie bereits erwähnt, hat ein einzelner Entscheidungsbaum oft eine geringere Qualität als moderne Methoden des maschinellen Lernens wie zufällige Wälder, Gradientenbäume und neuronale Netzwerke. Entscheidungsbäume sind jedoch in folgenden Fällen nützlich:

  • Als einfache und kostengünstige Grundlage zur Bewertung komplexerer Ansätze.
  • Wenn ein Kompromiss zwischen Modellqualität und Interpretierbarkeit besteht.
  • Als Proxy für die Interpretation des Modells „Entscheidungsstruktur“, das wir im weiteren Verlauf des Kurses behandeln.