Zurück...

Entscheidungsbaum / Klassifikations- und Regressionsbaum

Trainierte Regressions- / Klassifikationsbäume (Entscheidungsbäume) bilden Daten als Entscheidungsregeln ab. Diese Entscheidungsregeln können als ein mehr oder weniger verästelter Baum grafisch dargestellt werden. Anstatt Werte, wie z. B. bei der linearen Regression für die unabhängige Variable, vorzugeben, wird der Verästelung im Baum gefolgt, um den geschätzten Wert zu ermitteln. D. h., die Baum- (Modell-) Interpretation ist einfach, aber nicht so präzise wie z. B. bei einem linearen Modell.

Sie können sich über das Video Entscheidungsbaum mit R einen Einstieg in das Thema verschaffen.

Hier ein grober Überblick über die Einsatzbereiche von Entscheidungsbäumen:

  • Große Datensätze, die komplexe Zusammenhänge beschreiben.
  • Die Beziehung zwischen den Beobachtungen innerhalb der Datensätze müssen nicht linear sein!
  • Die Modellfunktion und deren Parameter sind nicht bekannt.
    • Um den Modellzusammenhang zu beschreiben, wird das Modell trainiert (maschinelles Lernen)
    • Das erfordert, dass die Daten in mindestens einem Trainings- und einem Modelltest-Datensatz geteilt werden. Ab und an wird der Datensatz nicht nur in die zwei genanten, sondern noch in einem weiteren Datensatz, dem Validierungsdatensatz, aufgeteilt.
      Diese Vorgehensweise ist notwendig, um Modellüberanpassungen zu erkennen!

Häufig angewendete Algorithmen zur Anpassung von Baummodellen sind die Klassifikations- und Regressionsbäume (Classification And Regressions Trees, CART). Der CART-Algorithmus wird in R in a Nutshell übersichtlich dargelegt.
Der Algorithmus ist in R als rpart-Funktion über das Paket rpart abgebildet und wird im Folgenden zum Trainieren von Regressions- / Klassifizierungsbäume verwendet. Dabei wird nur beispielhaft vorgegangen und nicht alle Möglichkeiten der rpart-Funktion dargelegt, bzw. genutzt. Informieren Sie sich bitte über weitere Funktions-Möglichkeiten mit der angebotenen Hilfefunktion!

Ein Beispiel:

Als Beispieldatensatz wird der Datensatz kyphosis des rpart-Paketes verwendet. Dieser Datensatz beschreibt Eingriffe bei Wirbelsäulenverkrümmung bei Kindern. Alle Kinder leiden unter der Verkrümmung und der Datensatz beschreibt das Vorhandensein (2 = present) / nicht Vorhandensein (1 = absent) nach einer Operation. Age ist das Alter in Monaten, Number die Anzahl der betroffenen Wirbeln und Start ist der Wirbel, mit dem der Eingriff begonnen wurde (Entschuldigung, ich bin kein Mediziner):

    > library(rpart)
    > data(kyphosis)
    > str(kyphosis)
    'data.frame':  81 obs. of 4 variables:
     $ Kyphosis: Factor w/ 2 levels "absent","present": 1 1 2 1 1 1 1 1 1 2 ...
     $ Age   : int 71 158 128 2 1 1 61 37 113 59 ...
     $ Number : int 3 3 4 5 4 2 2 3 2 6 ...
     $ Start  : int 5 14 5 1 15 16 17 16 16 12 ...

    > kyphosis
      Kyphosis Age Number Start
    1  absent 71   3   5
    2  absent 158   3  14
    3  present 128   4   5
    4  absent  2   5   1
    5  absent  1   4  15
    6  absent  1   2  16
    7  ...

Der Datensatz kyphosis ist mit 81 Datensätzen nicht besonders groß, trotzdem wird er in einen Trainings- und Testdatensatz geteilt:

    > n_Daten <- nrow(kyphosis)  # 81 Zeilen
    > # 70% der Daten sollen zufällig ausgewählt zum Training verwendet werden
    > # (als Index):
    > Training_i <- sample(nrow(kyphosis), 0.7 * n_Daten)
    > length(Training_i) # Anzahl (und Nr.) der ausgewählten “Zeilen”
    [1] 56

    > # Die restlichen Daten (30%) werden als Testdatensatz festgelegt:
    > Test_i <- setdiff(1:nrow(kyphosis), Training_i)
    > length(Test_i)
    [1] 25

    Möchten Sie sich überzeugen, dass jeder Datensatz-Index sauber in einem Trainings- und Test-Index getrennt wurde, hilft die Funktion sort() weiter:

    > sort(Training_i); sort(Test_i)

    Nachdem die Datensatz-Zeilen (der Index) für den Trainings- und Testdatensatz festgelegt wurden, werden die Datensätze definiert:

    > Training <- kyphosis[Training_i,]
    > str(Training)
    'data.frame':  56 obs. of 4 variables:
     $ Kyphosis: Factor w/ 2 levels "absent","present": 2 1 1 1 2 1 1 1 1 1 ...
     $ Age   : int 73 37 78 87 96 177 159 206 125 4 ...
     $ Number : int 5 3 6 4 3 2 4 4 2 3 ...
     $ Start  : int 1 16 15 16 12 14 13 10 11 16 ...

    > Test <- kyphosis[Test_i,]
    > str(Test)
    'data.frame':  25 obs. of 4 variables:
     $ Kyphosis: Factor w/ 2 levels "absent","present": 2 1 1 1 1 1 1 1 1 1 ...
     $ Age   : int 128 1 148 18 1 168 8 112 93 61 ...
     $ Number : int 4 2 3 5 4 3 3 3 3 4 ...
     $ Start  : int 5 16 16 2 12 18 6 16 16 1 ...

Mit dem Trainingsdatensatz Training wird über die Funktion rpart ein Entscheidungsbaum trainiert. Es werden mit dem Funktionsaufruf keine zusätzlichen Argumente zur Steuerung des Trainings mitgegeben. Die Diagnose Kyphosis ist wie erwähnt, eine ja/nein-Beobachtung und oben dargestellte Datensatz-Struktur zeigt, dass diese Variable vom Typ Faktor ist. Der rpart-Funktionsaufruf kann mit dem Argument method = “class” so gesteuert werden, dass ein Klassifikationsbaum geschätzt wird (es liegen ja keine kontinuierliche Beobachtungen vor = Regressionsbaum). In dem folgenden einfachen Funktionsaufruf errät der rpart-Algorithmus, um welchen Typ es sich bei der Kriteriumsvariable (Kyphosis) handelt und schätzt einen Klassifikationsbaum:

    > # Einfaches Training, ohne weitere Funktionsargumente:
    > Anpassung <- rpart(Kyphosis ~ Age + Number + Start, data = Training)
    > print(Anpassung)
    n= 56

    node), split, n, loss, yval, (yprob)
       * denotes terminal node

    1) root 56 11 absent (0.8035714 0.1964286) 
     2) Start>=12.5 32 1 absent (0.9687500 0.0312500) *
     3) Start< 12.5 24 10 absent (0.5833333 0.4166667) 
      6) Age< 51.5 7 1 absent (0.8571429 0.1428571) *
      7) Age>=51.5 17 8 present (0.4705882 0.5294118) *

Die obige zahlenmäßige Ausgabe der Entscheidungsbaum-Anpassung zeigt, dass die Parameter Start und Age einen wesentlichen Beitrag zur operativen Korrektur der Wirbelsäulenverkrümmung haben. Wie ist obige Ausgabe zu lesen? Im mittleren Abschnitt der Ausgabe wird die Legende ausgeben:

  • node): Knotenummer. Es wird immer oben und dann von links nach rechts gelesen (siehe Abb. weiter unten).
  • split: Wie wird die Klassifizierung vorgenommen? hier durch z. B. Start>=12.5 und Age< 51.5.
  • n: Mit wie vielen Beobachtungen wird in den nächsten Knoten gegangen? Z. B. in den 2 Knoten mit 32 Beobachtungen.
  • loss: Verlust/Abgang. In den z. B. 2 Knoten wird mit 32 Beobachtungen hineingegangen, weil die Bedingung Start>=12.5 zutrifft. Nun liegt leider keine 100%ige Erfolgsquote vor, sondern “nur” 0.96875. Das bedeutet, ein erfolgreiche Eingriff ab dem 12,5 Wirbel wird unter diesen Bedingungen bei 31 Eingriffen erwartet und 1 Eingriff wird nicht erfolgreich sein. Der Abgang aus diesen Konten ist 1 und damit ist das Ende dieses Astes erreicht.
  • yval: Der zutreffende y-Wert (Kriteriumsvariable). In diesem Beispiel absent oder present.
  • (yprob): Die Verteilung der y-Werte. Für den 2. Knoten beträgt der absent-Anteil 96,875%.
  • *: Astende, die Bildung weiterer Knoten nicht mehr möglich.

Die Baumstruktur, d. h., das Schätzen der optimalen Anpassung ist durch Wahl der geeigneten Funktionsargumente möglich, was in diesem Beispiel aber nicht vertieft wird!

Zur Unterstützung der Anpassungs-Interpretation kann die Anpassung grafisch dargestellt werden:

    > plot(Anpassung, uniform = T, compress = T, branch = 0.7)
    > text(Anpassung, all = T, use.n = T, cex = 0.5)

    Entscheidungsbaum_1

Wenn der obige Entscheidungsbaum das erste mal betrachtet wird, ist bestimmt Deutungsunterstützung notwendig. Dazu wird obige Grafik ein wenig ergänzt:

Entscheidungsbaum_2

Der Entscheidungsbaum macht deutlich, dass ein operativer Erfolg von dem Start-Wirbel (ab dem ~13 Wirbel) und dem Alter des Kindes (jünger als 51,5 Monate) abhängt. Um den Erfolg eines Eingriffes für eine bestimmte Wirbel-Start-Position unter Berücksichtigung des Kindesalters abzuschätzen, braucht man nur dem Baum zu folgen!

Über die Funktionen printcp(Anpassung) und summary(Anpassung) werden Angaben über die Güte der Schätzung gemacht.

Für Regressionsbäume ist die Funktion rsq.rpart() interessant! Über diese Funktion wird für den geschätzten (trainierten) Baum für jeden Knoten der Komplexitätsparameter CP mit den dazugehörigen Abweichungen, inklusive grafischer Darstellung, ausgegeben. Erscheint der geschätzte Baum zu komplex (visueller Eindruck und aufgrund des Parameters CP), lässt er sich über die Funktion prune (geschätzter Baum, cp = Schätzung auf Basis des relativen Fehlers) zurückschneiden und neu schätzen.

Die Schätzung des Klassifikationsbaums Anpassung basiert auf einen Trainingsdatensatz mit 56 Beobachtungen. Zur Schätzung eines Entscheidungsbaumes sollte die Anzahl der Beobachtungen (die Größe des Datensatzes) deutlich höher sein (mehrere Hundert). Die Gütekriterien sind eine Sache. Ein Test, basierend auf gemachte Beobachtungen, eine andere. Nun kommt unser Testdatensatz ins Spiel!

Wir machen eine Vorhersage auf Basis des Testdatensatzes, ob der Eingriff erfolgreich ist:

    > # Auf Basis des Modells “Anpassung” sollen für die Daten “Test”
    > # vorhersagen gemacht werden:
    > Vorhergesagt = predict(Anpassung, newdata=Test, type="class")

    > # Um einen Überblick über die Test- und Vorhersage-Daten zu bekommen,
    > # werden beide Daten zu einem data.frame zusammengefasst:
    > Kombination <- data.frame(Test, Vorhergesagt)
    > Kombination
      Kyphosis Age Number Start Vorhergesagt
    3  present 128   4   5   present
    6  absent  1   2  16    absent
    12  absent 148   3  16    absent
    13  absent 18   5   2    absent
    14  absent  1   4  12    absent
    15  absent 168   3  18    absent
    27  absent  8   3   6    absent
    34  absent 112   3  16    absent
    36  absent 93   3  16    absent
    44  absent 61   4   1   present *
    48  absent 131   5  13    absent
    52  absent  9   2  17    absent
    53 present 139   10   6   present
    57  absent  2   3  13    absent
    60  absent 102   3  13    absent
    61 present 130   4   1   present
    62 present 114   7   8   present
    63  absent 81   4   1   present *
    65  absent 118   4  16    absent
    69  absent 18   4  11    absent
    70  absent 15   5  16    absent
    71  absent 158   5  14    absent
    77 present 157   3  13    absent *
    78  absent 26   7  13    absent
    80 present 42   7   6    absent *

Die Kyphosis-Beobachtung, die sich in dem Test- und Vorhersage-Daten unterscheiden, sind markiert!

Zum Schluss möchte ich folgende Punkte hervorheben:

      • Stellen Sie sicher, dass Ihr Datenumfang groß genug ist!
      • Der Argument-Umfang der verschiedenen R-Entscheidungsbaum-Funktionen ist recht groß und erscheint komplex, beschäftigen Sie sich mit ihm!
Seitenanfang

Hat der Inhalt Ihnen weitergeholfen und Sie möchten diese Seiten unterstützen?