¿Cómo se determinan las características_importancias en RandomForestClassifier?

125

Tengo una tarea de clasificación con una serie temporal como entrada de datos, donde cada atributo (n = 23) representa un punto específico en el tiempo. Además del resultado de clasificación absoluta que me gustaría averiguar, qué atributos / fechas contribuyen al resultado en qué medida. Por lo tanto, solo estoy usando el feature_importances_, que funciona bien para mí.

Sin embargo, me gustaría saber cómo se calculan y qué medida / algoritmo se utiliza. Lamentablemente no pude encontrar ninguna documentación sobre este tema.

usuario2244670
fuente
10
Woah tres desarrolladores principales en un hilo SO. Eso tiene que ser algún tipo de registro ^^
Andreas Mueller

Respuestas:

158

De hecho, hay varias formas de obtener características "importantes". Como a menudo, no hay un consenso estricto sobre lo que significa esta palabra.

En scikit-learn, implementamos la importancia como se describe en [1] (a menudo citado, pero desafortunadamente raramente leído ...). A veces se denomina "importancia de Gini" o "impureza de disminución media" y se define como la disminución total de la impureza del nodo (ponderada por la probabilidad de llegar a ese nodo (que se aproxima por la proporción de muestras que llegan a ese nodo)) promediada sobre todo Árboles del conjunto.

En la literatura o en algunos otros paquetes, también puede encontrar características importantes implementadas como la "precisión de disminución media". Básicamente, la idea es medir la disminución en la precisión de los datos OOB cuando permutas aleatoriamente los valores de esa característica. Si la disminución es baja, entonces la función no es importante, y viceversa.

(Tenga en cuenta que ambos algoritmos están disponibles en el paquete randomForest R).

[1]: Breiman, Friedman, "Árboles de clasificación y regresión", 1984.

Gilles Louppe
fuente
48
Podría ser genial si esta respuesta se mencionara en la documentación de los atributos / ejemplo de importancia. Lo
he
2
Parece que la puntuación de importancia está en valor relativo? Por ejemplo, la suma de los puntajes de importancia de todas las características es siempre 1 (vea el ejemplo aquí scikit-learn.org/stable/auto_examples/ensemble/… )
ARN
55
@RNA: Sí, por defecto, las importancias variables se normalizan en scikit-learn, de modo que suman una. Puede evitar esto haciendo un bucle sobre los estimadores de base individuales y llamando tree_.compute_feature_importances(normalize=False).
Gilles Louppe
2
@GillesLouppe ¿Utiliza las muestras fuera de bolsa para medir la reducción en MSE para un bosque de regresores de árboles de decisión en cada árbol? ¿O todos los datos de entrenamiento utilizados en el árbol?
Golpea el
1
Dos recursos útiles. (1) blog.datadive.net/… un blog de Ando Saabas implementa "impureza de disminución media" y también "disminución de precisión promedio" como lo menciona Gilles. (2) Descargue y lea la tesis de Gilles Louppe.
Mark Teese
54

La forma habitual de calcular los valores de importancia de las características de un solo árbol es la siguiente:

  1. Inicializa una matriz feature_importancesde todos los ceros con tamaño n_features.

  2. atraviesa el árbol: para cada nodo interno que se divide en función i, calcula la reducción de errores de ese nodo multiplicada por el número de muestras que se enrutaron al nodo y agrega esta cantidad feature_importances[i].

La reducción de errores depende del criterio de impureza que utilice (por ejemplo, Gini, Entropy, MSE, ...). Es la impureza del conjunto de ejemplos que se enruta al nodo interno menos la suma de las impurezas de las dos particiones creadas por la división.

Es importante que estos valores sean relativos a un conjunto de datos específico (tanto la reducción de errores como el número de muestras son específicos del conjunto de datos), por lo tanto, estos valores no se pueden comparar entre diferentes conjuntos de datos.

Hasta donde sé, hay formas alternativas de calcular los valores de importancia de las características en los árboles de decisión. Una breve descripción del método anterior se puede encontrar en "Elementos de aprendizaje estadístico" de Trevor Hastie, Robert Tibshirani y Jerome Friedman.

Peter Prettenhofer
fuente
12

Es la relación entre el número de muestras enrutadas a un nodo de decisión que involucra esa característica en cualquiera de los árboles del conjunto sobre el número total de muestras en el conjunto de entrenamiento.

Las características que están involucradas en los nodos de nivel superior de los árboles de decisión tienden a ver más muestras, por lo tanto, es probable que tengan más importancia.

Editar : esta descripción es solo parcialmente correcta: las respuestas de Gilles y Peter son la respuesta correcta.

ogrisel
fuente
1
¿Sabes si hay algún documento / documentación sobre el método exacto? p.ej. Breiman, 2001. Sería genial si tuviera algún documento adecuado, que podría citar para la metodología.
user2244670
@ogrisel sería genial si pudieras marcar claramente tu respuesta como la explicación de la "ponderación". La ponderación por sí sola no determina la importancia de la característica. La "métrica de impureza" ("gini-importancia" o RSS) combinada con los pesos promediados sobre los árboles determina la importancia general de la característica. Desafortunadamente, la documentación sobre scikit-learn aquí: scikit-learn.org/stable/modules/… no es precisa y menciona incorrectamente "profundidad" como la métrica de impureza.
Ariel
11

Como @GillesLouppe señaló anteriormente, scikit-learn actualmente implementa la métrica "disminución media de impurezas" para las características importantes. Personalmente, considero que la segunda métrica es un poco más interesante, donde permutas aleatoriamente los valores de cada una de tus características una por una y ves cuánto peor es tu rendimiento de fábrica.

Dado que lo que busca con la importancia de la característica es cuánto contribuye cada característica al rendimiento predictivo de su modelo general, la segunda métrica en realidad le da una medida directa de esto, mientras que la "disminución de la impureza media" es solo un buen indicador.

Si está interesado, escribí un pequeño paquete que implementa la métrica Importancia de permutación y puede usarse para calcular los valores de una instancia de una clase de bosque aleatorio scikit-learn:

https://github.com/pjh2011/rf_perm_feat_import

Editar: Esto funciona para Python 2.7, no 3

Peter
fuente
Hola @Peter cuando uso tu código me sale este error: NameError: el nombre 'xrange' no está definido.
Aizzaac
Hola @Aizzaac Lo siento, soy nuevo en escribir paquetes, así que debería haber notado que lo escribí para Python 2.7. Pruebe def xrange (x): return iter (range (x)) antes de ejecutarlo
Peter
2

Déjame intentar responder la pregunta. código:

iris = datasets.load_iris()  
X = iris.data  
y = iris.target  
clf = DecisionTreeClassifier()  
clf.fit(X, y)  

decision_tree plot:
ingrese la descripción de la imagen aquí
. , 0.01333333,0.06405596,0.92261071]
Verifique el código fuente:

cpdef compute_feature_importances(self, normalize=True):
    """Computes the importance of each feature (aka variable)."""
    cdef Node* left
    cdef Node* right
    cdef Node* nodes = self.nodes
    cdef Node* node = nodes
    cdef Node* end_node = node + self.node_count

    cdef double normalizer = 0.

    cdef np.ndarray[np.float64_t, ndim=1] importances
    importances = np.zeros((self.n_features,))
    cdef DOUBLE_t* importance_data = <DOUBLE_t*>importances.data

    with nogil:
        while node != end_node:
            if node.left_child != _TREE_LEAF:
                # ... and node.right_child != _TREE_LEAF:
                left = &nodes[node.left_child]
                right = &nodes[node.right_child]

                importance_data[node.feature] += (
                    node.weighted_n_node_samples * node.impurity -
                    left.weighted_n_node_samples * left.impurity -
                    right.weighted_n_node_samples * right.impurity)
            node += 1

    importances /= nodes[0].weighted_n_node_samples

    if normalize:
        normalizer = np.sum(importances)

        if normalizer > 0.0:
            # Avoid dividing by zero (e.g., when root is pure)
            importances /= normalizer

    return importances

Intente calcular la importancia de la característica:

print("sepal length (cm)",0)
print("sepal width (cm)",(3*0.444-(0+0)))
print("petal length (cm)",(54* 0.168 - (48*0.041+6*0.444)) +(46*0.043 -(0+3*0.444)) + (3*0.444-(0+0)))
print("petal width (cm)",(150* 0.667 - (0+100*0.5)) +(100*0.5-(54*0.168+46*0.043))+(6*0.444 -(0+3*0.444)) + (48*0.041-(0+0)))

Obtenemos feature_importance: np.array ([0,1.332,6.418,92.30]).
Después de normalizado, podemos obtener una matriz ([0., 0.01331334, 0.06414793, 0.92253873]), esto es lo mismo que clf.feature_importances_.
Tenga cuidado, se supone que todas las clases tienen peso uno.

tengfei li
fuente
1

Para aquellos que buscan una referencia a la documentación de scikit-learn sobre este tema o una referencia a la respuesta de @GillesLouppe:

En RandomForestClassifier, el estimators_atributo es una lista de DecisionTreeClassifier (como se menciona en la documentación ). Para calcular el feature_importances_RandomForestClassifier, en el código fuente de scikit-learn , promedia todos los feature_importances_atributos del estimador (todos los DecisionTreeClassifer) en el conjunto.

En la documentación de DecisionTreeClassifer , se menciona que "La importancia de una característica se calcula como la reducción total (normalizada) del criterio traído por esa característica. También se conoce como la importancia de Gini [1]".

Aquí hay un enlace directo para obtener más información sobre la variable y la importancia de Gini, tal como lo proporciona la referencia de scikit-learn a continuación.

[1] L. Breiman y A. Cutler, "Random Forests", http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm

Makan
fuente