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 🧭 YDF-Tutorial für den Einstieg.

Grundlegendes

Bevor Sie das Dataset untersuchen, führen Sie 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

 

Mit dem folgenden Code wird eine pandas-Funktion aufgerufen, 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 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 3800,0 weiblich 2007
2 Adelie Torgersen 40.3 18.0 195.0 3250,0 weiblich 2007

Das vollständige Dataset enthält eine Mischung aus numerischen (z. B. bill_depth_mm), kategorialen (z. B. island) und fehlenden Merkmalen. Im Gegensatz zu neuronalen Netzen unterstützen Entscheidungsbäume alle diese Merkmalstypen nativ. Sie müssen also keine One-Hot-Codierung, Normalisierung oder zusätzliche „is_present“-Merkmale vornehmen.

In der folgenden Codezelle wird das Dataset in ein Trainings- und 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 Standard-Hyperparametern trainieren

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

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

Im vorherigen Aufruf wurden keine Spalten als Eingabe-Features angegeben. Daher wird jede Spalte im Trainings-Dataset verwendet. Im Aufruf wurden auch nicht die Semantik (z. B. numerisch, kategorisch, Text) der Eingabefeatures angegeben. Daher wird die Semantik von Funktionen 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 wie der Klassenverteilung in den einzelnen Knoten aufrufen.

Ein Entscheidungsbaum, der mit Standardhyperparametern trainiert wurde.

Abbildung 17. Ein Entscheidungsbaum, der mit Standard-Hyperparametern trainiert wurde.

In Colab wird angezeigt, dass die Stammbedingung 243 Beispiele enthält. Das Trainings-Dataset enthielt jedoch 272 Beispiele. Die verbleibenden 29 Beispiele wurden automatisch für die Validierung und das Beschneiden des Baums reserviert.

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

Tabelle 4. Wahrscheinlichkeit verschiedener Arten, wenn bill_depth_mm ≥ 42.3

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

 

Tabelle 5. Wahrscheinlichkeit verschiedener Arten, wenn bill_depth_mm < 42.3

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

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

Wenn bill_depth_mm ≥ 42.3 „True“ ist, wird weiter getestet, ob die flipper_length_mm ≥ 207.5 die Gentoo-Pinguine fast perfekt von den Gentoo- und Adelie-Pinguinen 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 das Test-Dataset möglicherweise vom Trainings-Dataset. Das ist hier jedoch nicht der Fall, da die Aufteilung in Trainings- und Testdaten zufällig erfolgte. Eine wahrscheinlichere Erklärung ist, dass das Test-Dataset sehr klein ist (nur 72 Beispiele), sodass die Schätzung der Genauigkeit verrauscht ist.

In der Praxis wäre es für einen so kleinen Datensatz besser, Kreuzvalidierung zu verwenden, da dadurch genauere Werte für die Bewertungsmesswerte berechnet werden. In diesem Beispiel fahren wir jedoch der Einfachheit halber mit dem Training und Testen fort.

Modell-Hyperparameter verbessern

Das Modell ist ein einzelner Entscheidungsbaum, der mit Standard-Hyperparameterwerten trainiert wurde. So können Sie bessere Vorhersagen erhalten:

  1. Verwenden Sie einen leistungsstärkeren Lernalgorithmus wie Random Forest oder Gradient Boosted Trees. Diese Lernalgorithmen werden auf der nächsten Seite erläutert.

  2. Optimieren Sie den Hyperparameter anhand Ihrer Beobachtungen und Intuition. Der Leitfaden zur Modelloptimierung kann hilfreich sein.

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

Da wir den Random Forest- und Gradient Boosted Trees-Algorithmus noch nicht gesehen haben und die Anzahl der Beispiele zu klein ist, um eine automatische Hyperparameter-Abstimmung durchzuführen, werden Sie das Modell manuell verbessern.

Der oben gezeigte Entscheidungsbaum ist klein und das Blatt mit 61 Beispielen enthält eine Mischung aus Adelie- und Zügelpinguin-Labels. Warum wurde dieser Knoten vom Algorithmus 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 aufgeteilt und dann beschnitten, um eine Überanpassung 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 Blattknoten mit 61 Beispielen wurde mehrmals unterteilt.

Um zu sehen, ob es sinnvoll ist, den Knoten weiter zu unterteilen, 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.

Vorschau von Entscheidungsbäumen

Durch weitere Optimierung der Hyperparameter lässt sich wahrscheinlich eine perfekte Genauigkeit erreichen. Anstelle dieses manuellen Prozesses können wir jedoch ein leistungsstärkeres Modell wie einen Random Forest trainieren und sehen, 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 Entscheidungsbaums. 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 bei modernen Methoden für maschinelles Lernen wie Random Forests, Gradient-Boosted Trees und neuronalen Netzwerken. Entscheidungsbäume sind jedoch in den folgenden Fällen weiterhin nützlich:

  • Als einfache und kostengünstige Baseline zur Bewertung komplexerer Ansätze.
  • Wenn es einen Kompromiss zwischen Modellqualität und Interpretierbarkeit gibt.
  • Als Proxy für die Interpretation des Entscheidungsbaummodells, das später im Kurs behandelt wird.