Erste (und einfachste) Lösung: Wenn Sie sich nicht an die klassische RF halten möchten, wie sie in Andy Liaw implementiert ist randomForest
, können Sie das Party- Paket ausprobieren , das eine andere Implementierung des ursprünglichen RF ™ -Algorithmus bietet (Verwendung von bedingten Bäumen und Aggregationsschema basierend) nach Gewichtseinheiten (Durchschnittsgewicht). Dann können Sie, wie in diesem R-Hilfe-Beitrag berichtet , ein einzelnes Mitglied der Baumliste zeichnen. Es scheint reibungslos zu laufen, soweit ich das beurteilen kann. Unten sehen Sie eine grafische Darstellung eines Baumes, der von erstellt wurde cforest(Species ~ ., data=iris, controls=cforest_control(mtry=2, mincriterion=0))
.
Zweitens (fast so einfach) Lösung: Die meisten Baum-basierte Techniken in R ( tree
, rpart
, TWIX
, etc.) bietet eine tree
-ähnlichen Struktur für den Druck / einen einzigen Baum Plotten. Die Idee wäre, die Ausgabe von randomForest::getTree
in ein solches R-Objekt umzuwandeln , auch wenn es statistisch unsinnig ist. Grundsätzlich ist es einfach, von einem tree
Objekt aus auf die Baumstruktur zuzugreifen , wie unten gezeigt. Bitte beachten Sie, dass es je nach Aufgabentyp - Regression oder Klassifizierung - geringfügige Unterschiede gibt. Im späteren Fall werden klassenspezifische Wahrscheinlichkeiten als letzte Spalte von obj$frame
(das ist a data.frame
) hinzugefügt .
> library(tree)
> tr <- tree(Species ~ ., data=iris)
> tr
node), split, n, deviance, yval, (yprob)
* denotes terminal node
1) root 150 329.600 setosa ( 0.33333 0.33333 0.33333 )
2) Petal.Length < 2.45 50 0.000 setosa ( 1.00000 0.00000 0.00000 ) *
3) Petal.Length > 2.45 100 138.600 versicolor ( 0.00000 0.50000 0.50000 )
6) Petal.Width < 1.75 54 33.320 versicolor ( 0.00000 0.90741 0.09259 )
12) Petal.Length < 4.95 48 9.721 versicolor ( 0.00000 0.97917 0.02083 )
24) Sepal.Length < 5.15 5 5.004 versicolor ( 0.00000 0.80000 0.20000 ) *
25) Sepal.Length > 5.15 43 0.000 versicolor ( 0.00000 1.00000 0.00000 ) *
13) Petal.Length > 4.95 6 7.638 virginica ( 0.00000 0.33333 0.66667 ) *
7) Petal.Width > 1.75 46 9.635 virginica ( 0.00000 0.02174 0.97826 )
14) Petal.Length < 4.95 6 5.407 virginica ( 0.00000 0.16667 0.83333 ) *
15) Petal.Length > 4.95 40 0.000 virginica ( 0.00000 0.00000 1.00000 ) *
> tr$frame
var n dev yval splits.cutleft splits.cutright yprob.setosa yprob.versicolor yprob.virginica
1 Petal.Length 150 329.583687 setosa <2.45 >2.45 0.33333333 0.33333333 0.33333333
2 <leaf> 50 0.000000 setosa 1.00000000 0.00000000 0.00000000
3 Petal.Width 100 138.629436 versicolor <1.75 >1.75 0.00000000 0.50000000 0.50000000
6 Petal.Length 54 33.317509 versicolor <4.95 >4.95 0.00000000 0.90740741 0.09259259
12 Sepal.Length 48 9.721422 versicolor <5.15 >5.15 0.00000000 0.97916667 0.02083333
24 <leaf> 5 5.004024 versicolor 0.00000000 0.80000000 0.20000000
25 <leaf> 43 0.000000 versicolor 0.00000000 1.00000000 0.00000000
13 <leaf> 6 7.638170 virginica 0.00000000 0.33333333 0.66666667
7 Petal.Length 46 9.635384 virginica <4.95 >4.95 0.00000000 0.02173913 0.97826087
14 <leaf> 6 5.406735 virginica 0.00000000 0.16666667 0.83333333
15 <leaf> 40 0.000000 virginica 0.00000000 0.00000000 1.00000000
Dann gibt es Methoden zum hübschen Drucken und Plotten dieser Objekte. Die Schlüsselfunktionen sind eine allgemeine tree:::plot.tree
Methode (ich habe ein Triple angegeben :
, mit der Sie den Code in R direkt tree:::treepl
anzeigen können), die sich auf (grafische Anzeige) und tree:::treeco
(Berechnung der Knotenkoordinaten ) stützt . Diese Funktionen erwarten die obj$frame
Darstellung des Baumes. Andere subtile Probleme: (1) Das Argument type = c("proportional", "uniform")
in der Standardplotmethode tree:::plot.tree
hilft, den vertikalen Abstand zwischen Knoten zu verwalten ( proportional
bedeutet, dass es proportional zur Abweichung ist, dh, uniform
es ist fest). (2) Sie müssen plot(tr)
durch einen Aufruf zum text(tr)
Hinzufügen von Textbezeichnungen zu Knoten und Teilungen ergänzen, was in diesem Fall bedeutet, dass Sie auch einen Blick darauf werfen müssen tree:::text.tree
.
Die getTree
Methode from randomForest
gibt eine andere Struktur zurück, die in der Online-Hilfe dokumentiert ist. Unten ist eine typische Ausgabe dargestellt, bei der die Endknoten durch den status
Code (-1) gekennzeichnet sind. (Die Ausgabe unterscheidet sich wiederum je nach Aufgabentyp, jedoch nur nach den Spalten status
und prediction
.)
> library(randomForest)
> rf <- randomForest(Species ~ ., data=iris)
> getTree(rf, 1, labelVar=TRUE)
left daughter right daughter split var split point status prediction
1 2 3 Petal.Length 4.75 1 <NA>
2 4 5 Sepal.Length 5.45 1 <NA>
3 6 7 Sepal.Width 3.15 1 <NA>
4 8 9 Petal.Width 0.80 1 <NA>
5 10 11 Sepal.Width 3.60 1 <NA>
6 0 0 <NA> 0.00 -1 virginica
7 12 13 Petal.Width 1.90 1 <NA>
8 0 0 <NA> 0.00 -1 setosa
9 14 15 Petal.Width 1.55 1 <NA>
10 0 0 <NA> 0.00 -1 versicolor
11 0 0 <NA> 0.00 -1 setosa
12 16 17 Petal.Length 5.40 1 <NA>
13 0 0 <NA> 0.00 -1 virginica
14 0 0 <NA> 0.00 -1 versicolor
15 0 0 <NA> 0.00 -1 virginica
16 0 0 <NA> 0.00 -1 versicolor
17 0 0 <NA> 0.00 -1 virginica
Wenn Sie es schaffen, die obige Tabelle zu dem konvertieren , erzeugt durch tree
, werden Sie wahrscheinlich in der Lage sein , zu gestalten tree:::treepl
, tree:::treeco
und an tree:::text.tree
Ihren Bedürfnissen anpassen, obwohl ich kein Beispiel für diesen Ansatz hat. Insbesondere möchten Sie wahrscheinlich die Verwendung von Abweichungen, Klassenwahrscheinlichkeiten usw. vermeiden, die in RF nicht von Bedeutung sind. Sie möchten lediglich Knotenkoordinaten einrichten und Werte teilen. Sie könnten das gebrauchen fixInNamespace()
, aber um ehrlich zu sein, bin ich mir nicht sicher, ob dies der richtige Weg ist.
Dritte (und sicherlich clevere) Lösung: Schreiben Sie eine echte as.tree
Hilfsfunktion, die alle oben genannten "Patches" lindert. Sie könnten dann die Plotmethoden von R verwenden oder, wahrscheinlich besser, Klimt (direkt von R), um einzelne Bäume anzuzeigen.