73 votos

Cómo trazar un ejemplo de árbol de randomForest::getTree()?

Alguien tiene o de la biblioteca de código de sugerencias en cuanto a la trama de un par de muestras de árboles de:

getTree(rfobj, k, labelVar=TRUE)

(Sí, sé que no estás dispuesto a hacer esto operacionalmente, la RF es una caja negra, etc, etc. Quiero visualmente la cordura-echa un árbol para ver si alguna de las variables se comportan contradictorio, tendrá que ajustar/combinar/discretización/transformación, comprobar lo bien que mi codifican factores de trabajo, etc.)

(Antes de la pregunta sin respuesta decente: 'Cómo hacer que los Bosques Aleatorios más interpretable?'. También "la Obtención de conocimiento a partir de un bosque aleatorio' Quiero trazar un ejemplo de árbol. Así que no discutas conmigo sobre eso, ya. No estoy preguntando acerca de varImpPlot(Variable de Importancia en la Trama) o partialPlot o MDSPlot, o estas otras parcelas, ya tengo los, pero no son un sustituto para ver un ejemplo de árbol. Sí puedo inspeccionar visualmente la salida de getTree(...,labelVar=TRUE))

(Supongo que un plot.rf.tree() contribución sería muy bien recibido).

52voto

DavLink Puntos 101

La primera (y más fácil) solución: Si no están dispuestos a seguir con radiofrecuencia clásicos, como el implementado en Andy Liaw s randomForest, usted puede tratar la parte del paquete que proporciona una implementación diferente de la original de RF algoritmo (uso del condicional árboles y esquema de agregación basado en unidades de peso promedio). Entonces, como se informó en este R-help post, se puede trazar un solo miembro de la lista de árboles. Parece funcionar sin problemas, por lo que puedo contar. Abajo es un dibujo de un árbol generado por cforest(Species ~ ., data=iris, controls=cforest_control(mtry=2, mincriterion=0)).

enter image description here

Segundo (casi tan fácil) solución: la Mayoría de árbol de técnicas basadas en R (tree, rpart, TWIX, etc.) ofrece una tree-como la estructura para la impresión/representación gráfica de un único árbol. La idea sería convertir la salida de randomForest::getTree a un R objeto, incluso si no tiene sentido desde un punto de vista estadístico. Básicamente, es fácil acceder a la estructura de árbol de un tree objeto, como se muestra a continuación. Por favor, tenga en cuenta que es ligeramente diferente en función del tipo de tarea-regresión vs clasificación, donde en el último caso se añade la clase específica de probabilidades como la última columna de la obj$frame (que es un data.frame).

> 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

Entonces, hay métodos para la impresión y el trazado de los objetos. Las principales funciones son un genérico tree:::plot.tree (método puse un triple : que le permite ver el código en R directamente) confiar en tree:::treepl (pantalla gráfica) y tree:::treeco (nodos de cálculo de coordenadas). Estas funciones de esperar que el obj$frame de la representación del árbol. Otras sutiles cuestiones: (1) el argumento de type = c("proportional", "uniform") en el valor predeterminado de trazado método, tree:::plot.tree, ayuda a administrar la distancia vertical entre los nodos (proportional significa que es proporcional a la desviación, uniform significa que es fija); (2) que necesita para complementar plot(tr) a través de una llamada a text(tr) agregar etiquetas de texto de los nodos y divisiones, que en este caso significa que usted también tendrá que echar un vistazo a tree:::text.tree.

El getTree método de randomForest devuelve una estructura diferente, que está documentada en la ayuda en línea. Una salida típica se muestra a continuación, con los nodos terminales indicados por status código (-1). (De nuevo, la salida será diferente en función del tipo de tarea, pero sólo en la status y prediction columnas).

> 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

Si usted puede manejar para convertir la tabla de arriba a la generada por tree, usted probablemente será capaz de personalizar tree:::treepl, tree:::treeco y tree:::text.tree para satisfacer sus necesidades, a pesar de que no tengo un ejemplo de este enfoque. En particular, es probable que desee deshacerse de el uso de la desviación, la clase de probabilidades, etc. que no son significativos en RF. Todo lo que quieres es configurar los nodos de coordenadas y dividir los valores. Usted podría utilizar fixInNamespace() por que, pero, para ser honesto, no estoy seguro de que este es el camino correcto a seguir.

Tercera (y ciertamente inteligente) solución: Escribir un cierto as.treehelper la función que alivia todos los de arriba "parches". Usted podría utilizar R métodos de trazado o, probablemente mejor, Klimt (directamente desde R) para mostrar los árboles individuales.

16voto

Michael K Puntos 3235

He creado algunas funciones para extraer las reglas de un árbol.

#**************************
#return the rules of a tree
#**************************
getConds<-function(tree){
  #store all conditions into a list
  conds<-list()
  #start by the terminal nodes and find previous conditions
  id.leafs<-which(tree$status==-1)
	  j<-0
	  for(i in id.leafs){
		j<-j+1
		prevConds<-prevCond(tree,i)
		conds[[j]]<-prevConds$cond
		while(prevConds$id>1){
		  prevConds<-prevCond(tree,prevConds$id)
		  conds[[j]]<-paste(conds[[j]]," & ",prevConds$cond)
		  if(prevConds$id==1){
			conds[[j]]<-paste(conds[[j]]," => ",tree$prediction[i])
        break()
      }
    }

  }

  return(conds)
}

#**************************
#find the previous conditions in the tree
#**************************
prevCond<-function(tree,i){
  if(i %in% tree$right_daughter){
		id<-which(tree$right_daughter==i)
		cond<-paste(tree$split_var[id],">",tree$split_point[id])
	  }
	  if(i %in% tree$left_daughter){
    id<-which(tree$left_daughter==i)
		cond<-paste(tree$split_var[id],"<",tree$split_point[id])
  }

  return(list(cond=cond,id=id))
}

#remove spaces in a word
collapse<-function(x){
  x<-sub(" ","_",x)

  return(x)
}


data(iris)
require(randomForest)
mod.rf <- randomForest(Species ~ ., data=iris)
tree<-getTree(mod.rf, k=1, labelVar=TRUE)
#rename the name of the column
colnames(tree)<-sapply(colnames(tree),collapse)
rules<-getConds(tree)
print(rules)

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X