Esta entrada la hago por petición popular y para rematar de alguna manera lo que incoé hace unos días. Seré breve hasta lo telegráfico:
- Tomo las observaciones con scorings más altos (en un árbol construido con
ranger
y cariño). - Veo cuáles son los árboles que les asignan scorings más altos.
- Anoto las variables implicadas en las ramas por donde bajan las observaciones (1) en los árboles (2).
- Creo una matriz positiva: filas = casos, columnas = variables, valores = conteos.
- Y la descompongo (vía NMF).
- Etc.
Es hasta paquetizable.
Notas:
- No me interesa (al menos en el caso de uso que motivó el desarrollo del algoritmo anterior) explicar todas las predicciones sino solamente las que tienen scorings más altos. El resto, no se usan para nada.
- Los métodos al uso para explicar predicciones lo hacen en términos de las variables del modelo. Sin embargo, los usuarios finales de la explicación pueden no tener mucha idea de qué puede llegar a significar una variable como
max_call_device_usage_period
. Porque también existen conjuntos de datos que no sonTitanic
. Se hace necesario postprocesar reglas basadas en la intervención de variables de ese estilo en motivos comprensibles. - Podría añadirse el sentido del corte en las variables, es decir, registrar no solo que la observación ha pasado por una bifurcación de un árbol en que interviene
edad
sino también si lo ha hecho por la rama del>
o del<
.
El último paso lo de ver si es izqda o derecha no lo había pensado , pero molaría.
Gracias por compartir tu sabiduría. Mi ignorancia aumenta cada día.
¿A partir de rg$predictions y de ranger::treeInfo obtuviste los registros y las variables más representativas del Random Forest? ¡Menudo trabajo!
library(titanic) # Data
library(ranger) # Random forest
titanic <- titanic_train[!is.na(titanic_train$Age),] ## remove missing data
rg <- ranger(Survived ~ ., data = titanic, importance = "impurity",write.forest=TRUE,keep.inbag=TRUE)
summary(rg)
head(rg$predictions) ## Check the most scored values
rg$num.trees ## (500 trees)
treeInfo(rg,3) ## Analyse this tree
Algo así. Pero tampoco es tan duro, ¿no?
No es tan duro. Yo me entretuve en hacerlo una tarde.
Funciones para sacar nodos terminales dado un árbol, guardar las variables(nodos padres) que llevan a cada nodo y luego iterar. Se puede paralelizar también. Pero la idea genial desde luego es de Carlos. Muy interesante.