python - sklearn - scikit learn tutorial
Intérprete Lime vs Tree para interpretar el árbol de decisión (1)
Fuente de cal: https://github.com/marcotcr/lime
Fuente del intérprete de árbol : intérprete de árbol
Estoy tratando de entender cómo el DecisionTree
hizo sus predicciones usando Lime y treeinterpreter. Si bien ambos afirman que son capaces de interpretar el árbol de decisiones en su descripción. Parece que ambos interpretan el mismo DecisionTree
de diferentes maneras. Es decir, el orden de contribución característica. ¿Cómo es eso posible? Si ambos están mirando lo mismo y están tratando de describir el mismo evento pero asignan importancia en orden de diferencia.
¿En quién debemos confiar? Especialmente donde la característica superior sí importa en la predicción.
El codigo para arbol
import sklearn
import sklearn.datasets
import sklearn.ensemble
import numpy as np
import lime
import lime.lime_tabular
from __future__ import print_function
np.random.seed(1)
from treeinterpreter import treeinterpreter as ti
from sklearn.tree import DecisionTreeClassifier
iris = sklearn.datasets.load_iris()
dt = DecisionTreeClassifier(random_state=42)
dt.fit(iris.data, iris.target)
n = 100
instances =iris.data[n].reshape(1,-1)
prediction, biases, contributions = ti.predict(dt, instances)
for i in range(len(instances)):
print ("prediction:",prediction)
print ("-"*20)
print ("Feature contributions:")
print ("-"*20)
for c, feature in sorted(zip(contributions[i],
iris.feature_names),
key=lambda x: ~abs(x[0].any())):
print (feature, c)
El código para la cal.
import sklearn
import sklearn.datasets
import sklearn.ensemble
import numpy as np
import lime
import lime.lime_tabular
from __future__ import print_function
np.random.seed(1)
from sklearn.tree import DecisionTreeClassifier
iris = sklearn.datasets.load_iris()
dt = DecisionTreeClassifier(random_state=42)
dt.fit(iris.data, iris.target)
explainer = lime.lime_tabular.LimeTabularExplainer(iris.data, feature_names=iris.feature_names,
class_names=iris.target_names,
discretize_continuous=False)
n = 100
exp = explainer.explain_instance(iris.data[n], dt.predict_proba, num_features=4, top_labels=2)
exp.show_in_notebook(show_table=True, predict_proba= True , show_predicted_value = True , show_all=False)
Veamos primero la salida del árbol .
Así que una correctamente dijo que era una virginica . Sin embargo, al asignar la importancia en
1) ancho del pétalo (cm) luego longitud del pétalo (cm)
Ahora veamos la salida de la cal.
Sí, dice que el algoritmo predijo Virginica, sin embargo, al ver cómo se hizo esa clasificación, vemos claramente lo siguiente
1) longitud del pétalo (cm)> ancho del pétalo (cm) en cal en lugar de longitud del pétalo (cm) <ancho del pétalo (cm) como se muestra en el árbol
2) donde el ancho del sépalo y el largo del sépalo se predijeron en cero, las reclamaciones de cal de cierto valor, como se muestra en las imágenes cargadas
Que está sucediendo aquí ?
El problema crece cuando las características son más de 1000 donde cada dígito importa para tomar una decisión.
¿Por qué es posible que los dos enfoques tengan resultados diferentes?
Lime : Una breve explicación de cómo funciona, tomada de su https://github.com/marcotcr/lime :
Intuitivamente, una explicación es una aproximación lineal local del comportamiento del modelo. Si bien el modelo puede ser muy complejo a nivel mundial, es más fácil aproximarlo alrededor de una instancia particular. Mientras tratamos el modelo como una caja negra, perturbamos la instancia que queremos explicar y aprendemos un modelo lineal disperso a su alrededor, como una explicación. La siguiente figura ilustra la intuición para este procedimiento. La función de decisión del modelo está representada por el fondo azul / rosa y es claramente no lineal. La cruz roja brillante es la instancia que se explica (llamémosla X). Tomamos muestras de instancias en torno a X y las ponderamos según su proximidad a X (el peso aquí se indica por tamaño). Luego aprendemos un modelo lineal (línea discontinua) que se aproxima bien al modelo cerca de X, pero no necesariamente a nivel global.
Hay información mucho más detallada en varios enlaces en la página de github.
treeinterpreter : una explicación de cómo funciona éste está disponible en http://blog.datadive.net/interpreting-random-forests/ (esto es para regresión; puede encontrar un ejemplo de clasificación, que funciona de manera muy similar, here ).
En resumen: supongamos que tenemos un nodo que compara la característica F
con algún valor y divide las instancias en función de eso. Supongamos que el 50% de todas las instancias que llegan a ese nodo pertenecen a la clase C
Supongamos que tenemos una nueva instancia y que se asigna al elemento secundario izquierdo de este nodo, donde ahora el 80% de todas las instancias pertenecen a la clase C
Luego, la contribución de la característica F
para esta decisión se calcula como 0.8 - 0.5 = 0.3
(más términos adicionales si hay más nodos a lo largo del camino a la hoja que también usan la característica F
).
Comparación: lo importante a tener en cuenta es que la cal es un método independiente del modelo (no específico de los árboles de decisión / RF), que se basa en la aproximación lineal local. El intérprete de árboles, por otro lado, opera específicamente de una manera similar al Árbol de Decisión en sí mismo, y realmente observa qué características son realmente utilizadas en las comparaciones por el algoritmo. Así que realmente están haciendo cosas muy diferentes. La cal dice que "una característica es importante si la movemos un poco y esto da como resultado una predicción diferente". El intérprete de árbol dice que "una característica es importante si se comparó con un umbral en uno de nuestros nodos y esto nos llevó a una división que cambió drásticamente nuestra predicción".
¿En cuál confiar?
Esto es difícil de contestar definitivamente. Probablemente ambos sean útiles a su manera. Intuitivamente, puede inclinarse a inclinarse hacia el intérprete de árboles a primera vista, porque fue creado específicamente para los árboles de decisión. Sin embargo, considere el siguiente ejemplo:
- Nodo raíz : 50% de las instancias clase 0, 50% clase 1. SI
F <= 50
, vaya a la izquierda; de lo contrario, vaya a la derecha. - Hijo izquierdo : 48% de las instancias, clase 0, 52%, clase 1. Subárbol debajo de este.
- Hijo derecho : 99% de las instancias, clase 0, 1% de las instancias, clase 1. Subárbol debajo de este.
Este tipo de configuración es posible si la mayoría de los casos se van a la izquierda, solo algunos a la derecha. Ahora supongamos que tenemos una instancia con F = 49
que se asignó a la izquierda y finalmente se asignó a la clase 1. A el intérprete de árboles no le importará que F
esté realmente cerca de terminar al otro lado de la ecuación en el nodo raíz, y solo asigne una baja contribución de 0.48 - 0.50 = -0.02
. Lime notará que cambiar F
solo un poco cambiaría completamente las probabilidades.
¿Cuál es la correcta? Eso no está muy claro. Se podría decir que F
fue realmente importante porque si hubiera sido un poco diferente, la predicción sería diferente (entonces gana la cal). También podría argumentar que F
no contribuyó a nuestra predicción final porque apenas nos acercamos a una decisión después de inspeccionar su valor, y después tuvimos que investigar muchas otras características. Luego el interprete de arbol gana.
Para tener una mejor idea aquí, también puede ser útil trazar el propio Árbol de Decisión aprendido. Luego, puede seguir manualmente su camino de decisión y decidir qué características considera importantes y / o ver si puede entender por qué tanto Lime como el intérprete de árboles dicen lo que dicen.