web-dev-qa-db-fra.com

Comment les particularités de feature_importances dans RandomForestClassifier sont-elles déterminées?

J'ai une tâche de classification avec une série chronologique comme entrée de données, où chaque attribut (n = 23) représente un moment spécifique. Outre le résultat absolu de la classification, j'aimerais savoir quels attributs/dates contribuent au résultat dans quelle mesure. Par conséquent, je n'utilise que le feature_importances_, qui fonctionne bien pour moi.

Cependant, j'aimerais savoir comment ils sont calculés et quelle mesure/algorithme est utilisé. Malheureusement, je n'ai trouvé aucune documentation sur ce sujet.

109
user2244670

Il y a en effet plusieurs façons d’obtenir une "importance" des fonctionnalités. Comme souvent, il n’ya pas de consensus strict sur la signification de cette Parole.

Dans scikit-learn, nous implémentons l’importance décrite dans [1] (souvent citée, mais malheureusement rarement lue ...). Il est parfois appelé "importance de Gini" ou "impureté de diminution moyenne" et est défini comme la diminution totale de l'impureté de nœud (pondérée par la probabilité d'atteindre ce nœud (approximée par la proportion d'échantillons atteignant ce nœud)) arbres de l'ensemble.

Dans la littérature ou dans d’autres progiciels, vous pouvez également trouver l’importance des fonctionnalités implémentée en tant que "précision de diminution moyenne". L'idée est essentiellement de mesurer la diminution de la précision des données hors bande lorsque vous permutez de manière aléatoire les valeurs de cette fonction. Si la diminution est faible, la fonctionnalité n'est pas importante et inversement.

(Notez que les deux algorithmes sont disponibles dans le package randomForest R.)

[1]: Breiman, Friedman, "Arbres de classification et de régression", 1984.

137
Gilles Louppe

La manière habituelle de calculer les valeurs d'importance des fonctionnalités d'un seul arbre est la suivante:

  1. vous initialisez un tableau feature_importances de tous les zéros de taille n_features.

  2. vous parcourez l'arborescence: pour chaque nœud interne qui se divise sur la fonction i, vous calculez la réduction d'erreur de ce nœud multipliée par le nombre d'échantillons acheminés vers le nœud et ajoutez cette quantité à feature_importances[i].

La réduction d'erreur dépend du critère d'impureté que vous utilisez (par exemple, Gini, Entropie, MSE, ...). C’est l’impureté de l’ensemble d’exemples acheminés vers le noeud interne moins la somme des impuretés des deux partitions créées par la scission.

Il est important que ces valeurs soient relatives à un ensemble de données spécifique (la réduction d'erreur et le nombre d'échantillons sont spécifiques à un ensemble de données). Par conséquent, ces valeurs ne peuvent pas être comparées entre différents ensembles de données.

Autant que je sache, il existe d'autres moyens de calculer les valeurs d'importance des fonctionnalités dans les arbres de décision. Vous trouverez une brève description de la méthode ci-dessus dans "Eléments d’apprentissage statistique" de Trevor Hastie, Robert Tibshirani et Jerome Friedman.

52

Il s'agit du rapport entre le nombre d'échantillons routés vers un nœud de décision impliquant cette fonctionnalité dans l'une des arborescences de l'ensemble par rapport au nombre total d'échantillons dans l'ensemble d'apprentissage.

Les entités impliquées dans les nœuds de niveau supérieur des arbres de décision ont tendance à voir plus d'échantillons, ce qui leur donne probablement plus d'importance.

Edit: cette description n’est que partiellement correcte: les réponses de Gilles et Peter sont la bonne réponse.

11
ogrisel

Comme @GillesLouppe l'a souligné ci-dessus, scikit-learn implémente actuellement la métrique "impureté de diminution moyenne" pour les importances de caractéristiques. Personnellement, je trouve la deuxième mesure un peu plus intéressante: vous permutez de manière aléatoire les valeurs de chacune de vos fonctions et vous constatez à quel point votre performance hors du sac est pire.

Étant donné que chaque élément contribue à la performance prédictive de votre modèle, la deuxième mesure vous en donne une mesure directe, alors que la "réduction moyenne de l'impureté" est simplement un bon indicateur.

Si vous êtes intéressé, j'ai écrit un petit package qui implémente la métrique Permutation Importance et peut être utilisé pour calculer les valeurs à partir d'une instance d'une classe de forêt aléatoire scikit-learn:

https://github.com/pjh2011/rf_perm_feat_import

Edit: Ceci fonctionne pour Python 2.7, pas 3

10
Peter

Laissez-moi essayer de répondre à la question. code:

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

decision_tree plot:
entrez la description de l'image ici
On peut obtenir compute_feature_importance: [0. , 0.01333333,0.06405596,0.92261071]
Vérifiez le code source:

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

Essayez de calculer l'importance de la fonctionnalité:

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)))

Nous obtenons feature_importance: np.array ([0,1.332,6.418,92.30]).
Après normalisation, nous pouvons obtenir un tableau ([0., 0.01331334, 0.06414793, 0.92253873]), ceci est identique à clf.feature_importances_.
Attention, toutes les classes sont supposées avoir le poids un.

1
tengfei li

Pour ceux qui recherchent une référence à la documentation de scikit-learn sur ce sujet ou une référence à la réponse de @GillesLouppe:

Dans RandomForestClassifier, estimators_ attribut est une liste de DecisionTreeClassifier (comme indiqué dans le documentation ). Afin de calculer le feature_importances_ pour RandomForestClassifier, dans le le code source de scikit-learn , il fait la moyenne de tous les estimateurs (tous de DecisionTreeClassifer) feature_importances_ attributs dans l’ensemble.

Dans documentation de DecisionTreeClassifer, il est mentionné que "L’importance d’une fonctionnalité est calculée en tant que réduction totale (normalisée) du critère apporté par cette fonctionnalité. Elle est également appelée importance de Gini [1]. "

Ici est un lien direct pour plus d’informations sur la variable et l’importance de Gini, comme indiqué par la référence de scikit-learn ci-dessous.

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

0
Makan