12 votos

Rpart parámetro de complejidad confusión

Estoy un poco confundido con el cálculo de CP en el resumen de un objeto rpart.

Toma este ejemplo

df <- data.frame(x=c(1, 2, 3, 3, 3), 
                 y=factor(c("a", "a", "b", "a", "b")),
                 method="class")
mytree<-rpart(y ~ x, data = df, minbucket = 1, minsplit=1)
summary(mytree)

Call:
rpart(formula = y ~ x, data = df, minbucket = 1, minsplit = 1)
  n= 5 

    CP nsplit rel error xerror      xstd
1 0.50      0       1.0      1 0.5477226
2 0.01      1       0.5      2 0.4472136

Importancia de las variables
  x 
100 

Nodo número 1: 5 observaciones,    parámetro de complejidad=0.5
  clase predicha=a  pérdida esperada=0.4  P(nodo) =1
    recuento de clases:     3     2
   probabilidades: 0.600 0.400 
  hijo izquierdo=2 (2 obs) hijo derecho=3 (3 obs)
  Divisiones primarias:
      x < 2.5 a la izquierda,  mejora=1.066667, (0 faltantes)

Para el nodo raíz, habría pensado que el CP debería ser 0.4 ya que la probabilidad de clasificar erróneamente un elemento en la raíz es 0.4 y el tamaño del árbol en la raíz es 0. ¿Cómo es que 0.5 es el CP correcto?

12voto

Igor Stasenko Puntos 136

El parámetro de complejidad $\alpha$ especifica cómo se penaliza el costo de un árbol $C(T)$ por el número de nodos terminales $|T|$, resultando en un costo regularizado $C_{\alpha}(T)$ (ver http://cran.r-project.org/web/packages/rpart/vignettes/longintro.pdf, Sección 4).

$C_{\alpha}(T) = C(T) + \alpha |T|

Un $\alpha$ pequeño resulta en árboles más grandes y posibles sobreajustes, un $\alpha$ grande en árboles más pequeños y posibles subajustes.

7voto

digiguru Puntos 3305

Hasta donde sé, el parámetro de complejidad no es el error en ese nodo en particular. Es la cantidad por la cual dividir ese nodo mejoró el error relativo. Por lo tanto, en tu ejemplo, dividir el nodo raíz original redujo el error relativo de 1.0 a 0.5, por lo que el CP del nodo raíz es 0.5. El CP del siguiente nodo es solo 0.01 (que es el límite predeterminado para decidir cuándo considerar divisiones). Por lo tanto, dividir ese nodo solo resultó en una mejora de 0.01, por lo que la construcción del árbol se detuvo allí.

7voto

Francisco Canedo Puntos 899

No es particularmente fácil seguir los cálculos de rpart para la clasificación. Además, aunque la 'Introducción Larga' sugiere que se utiliza gini para la clasificación, parece que la poda por complejidad de costos (y por lo tanto los valores de cp) se informan en función de la precisión en lugar de gini. En este caso, podemos trabajar en los cálculos y replicar el 0.4 consultado en la pregunta original. En primer lugar, crear el árbol

df <- data.frame(x=c(1,2,3,3,3), y=factor(c("a", "a", "b", "a", "b")))
mytree <- rpart(y ~ x, data = df, minbucket = 1, minsplit=1, method="class")

y luego escribir

print(mytree)

obtenemos

nodo), split,  n, loss, yval, (yprob)
1)     root    5   2     a (0.6000000 0.4000000)  
2)     x< 2.5  2   0     a (1.0000000 0.0000000) *
3)     x>=2.5  3   1     b (0.3333333 0.6666667) *

La columna 'loss' no es gini (que podrías haber esperado). Es el número de errores cometidos.

El punto en el que este árbol de un solo split colapsa (basado en la precisión) es cuando

$$ 2 + \alpha * 1 = 1 + \alpha * 2$$

(donde el primer 2 arriba es la pérdida en el árbol podado y el segundo 2 es el número de nodos terminales en el árbol completo).

Al resolver para alpha, se obtiene un alpha de 1.

Como se mencionó en una respuesta anterior, en la cptable, el error en la primera línea se escala a 1 y luego cp se escala por la misma cantidad. El error en la primera línea es el número de errores en un árbol sin divisiones, es decir, 2. Por lo tanto, el alpha de 1 se escala dividiendo por 2 para dar 0.50.

Es difícil leer el código C en rpart, pero eso es lo que creo que está haciendo.

3voto

matthewhc Puntos 8

Escribo para validar aún más las respuestas de ambos @joran y @fernando, y ayudar a alguien como yo a aclarar aún más cómo interpretar la matriz cp en un objeto rpart. Si observas el siguiente código, verás que he ajustado un árbol de clasificación con dos posibles resultados introduciendo mi propia matriz de pérdida (FN tiene un costo dos veces mayor que FP).

Árbol de clasificación:
rpart(formula = Result ~ ., data = data, method = "class", parms = list(loss 
= PenaltyMatrix))                 

Error del nodo raíz: 174/343 = 0.50729

n= 343 

    CP     nsplit  rel error xerror   xstd
1 0.066092      0   1.00000 0.50000 0.046311
2 0.040230      2   0.86782 0.73563 0.065081
3 0.034483      4   0.78736 0.91379 0.075656
4 0.022989      5   0.75287 1.01149 0.080396
5 0.019157      7   0.70690 1.17241 0.086526
6 0.011494     10   0.64943 1.21264 0.087764
7 0.010000     12   0.62644 1.31609 0.090890

Ahora, si observas, por ejemplo, el paso 6 en la matriz, puedes ver que el número de divisiones aumentó en 3 (de 7 a 10), lo que dio como resultado un error relativo de 0.64943. Ahora, si restas este error del respectivo en el paso anterior, encontrarás una mejora de 0.05747, que a su vez, si se divide por el número de divisiones adicionales entre los pasos 5-6 (que es tres) resulta aproximadamente en 0.01957, que es el parámetro de complejidad del paso 5. ¡Esto se puede validar entre todos los pasos!

Ahora, si me permites, tengo una pregunta de dos partes para dirigirme a la comunidad.

  • Todavía me desconcierta ¿qué significa que el xerror aumente continuamente a medida que crece el tamaño del árbol?

  • Si sigo la llamada regla empírica, debo seleccionar el árbol con el tamaño más pequeño que tenga un xerror dentro de una desviación estándar del árbol con el xerror mínimo en la tabla. En mi caso, este sería el árbol en el paso 2 (porque este es el que tiene el xerror más pequeño y 0.73563+0.065081=0.800711, que no es cumplido por ningún otro árbol en la tabla). ¿Es esto correcto?

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