Wie werden feature_importances in RandomForestClassifier ermittelt?

125

Ich habe eine Klassifizierungsaufgabe mit einer Zeitreihe als Dateneingabe, wobei jedes Attribut (n = 23) einen bestimmten Zeitpunkt darstellt. Neben dem absoluten Klassifizierungsergebnis möchte ich herausfinden, welche Attribute / Daten in welchem ​​Umfang zum Ergebnis beitragen. Deshalb benutze ich nur das feature_importances_, was für mich gut funktioniert.

Ich würde jedoch gerne wissen, wie sie berechnet werden und welche Kennzahl / welcher Algorithmus verwendet wird. Leider konnte ich zu diesem Thema keine Dokumentation finden.

user2244670
quelle
10
Woah drei Core-Entwickler in einem SO-Thread. Das muss eine Art Rekord sein ^^
Andreas Mueller

Antworten:

158

Es gibt in der Tat mehrere Möglichkeiten, um "Wichtigkeiten" zu erhalten. Wie so oft gibt es keinen strengen Konsens darüber, was dieses Wort bedeutet.

Beim Scikit-Lernen implementieren wir die Wichtigkeit wie in [1] beschrieben (oft zitiert, aber leider selten gelesen ...). Es wird manchmal als "Gini-Wichtigkeit" oder "mittlere Abnahme der Verunreinigung" bezeichnet und ist definiert als die Gesamtabnahme der Knotenverunreinigung (gewichtet mit der Wahrscheinlichkeit, diesen Knoten zu erreichen (die durch den Anteil der Proben, die diesen Knoten erreichen, angenähert wird), gemittelt über alle Bäume des Ensembles.

In der Literatur oder in einigen anderen Paketen finden Sie auch Feature-Wichtigkeiten, die als "mittlere Abnahmegenauigkeit" implementiert sind. Grundsätzlich besteht die Idee darin, die Abnahme der Genauigkeit von OOB-Daten zu messen, wenn Sie die Werte für diese Funktion zufällig permutieren. Wenn die Abnahme gering ist, ist die Funktion nicht wichtig und umgekehrt.

(Beachten Sie, dass beide Algorithmen im randomForest R-Paket verfügbar sind.)

[1]: Breiman, Friedman, "Classification and Regression Tree", 1984.

Gilles Louppe
quelle
48
Es könnte großartig sein, wenn diese Antwort in der Dokumentation der Wichtigkeitsattribute / des Beispiels erwähnt würde.
Ich habe auch schon
2
Es scheint, dass die Wichtigkeitsbewertung im relativen Wert liegt? Zum Beispiel ist die Summe der Wichtigkeitswerte aller Merkmale immer 1 (siehe das Beispiel hier scikit-learn.org/stable/auto_examples/ensemble/… )
RNA
5
@RNA: Ja, standardmäßig werden variable Wichtigkeiten in scikit-learn so normalisiert, dass sie sich zu eins summieren. Sie können dies umgehen, indem Sie die einzelnen Basisschätzer durchlaufen und aufrufen tree_.compute_feature_importances(normalize=False).
Gilles Louppe
2
@ GillesLouppe Verwenden Sie die Out-of-Bag-Proben, um die Verringerung der MSE für einen Wald von Entscheidungsbaum-Regressoren in jedem Baum zu messen? Oder alle im Baum verwendeten Trainingsdaten?
Cola
1
Zwei nützliche Ressourcen. (1) blog.datadive.net/… ein Blog von Ando Saabas implementiert sowohl "mittlere Abnahme der Verunreinigung" als auch "mittlere Abnahme der Genauigkeit", wie von Gilles erwähnt. (2) Laden Sie die These von Gilles Louppe herunter und lesen Sie sie.
Mark Teese
54

Die übliche Methode zum Berechnen der Merkmalswichtigkeitswerte eines einzelnen Baums lautet wie folgt:

  1. Sie initialisieren ein Array feature_importancesaller Nullen mit Größe n_features.

  2. Sie durchlaufen den Baum: Für jeden internen Knoten, der sich nach einem Feature iaufteilt, berechnen Sie die Fehlerreduzierung dieses Knotens multipliziert mit der Anzahl der Stichproben, die an den Knoten weitergeleitet wurden, und addieren diese Menge zu feature_importances[i].

Die Fehlerreduzierung hängt von dem von Ihnen verwendeten Verunreinigungskriterium ab (z. B. Gini, Entropy, MSE, ...). Es ist die Verunreinigung der Reihe von Beispielen, die an den internen Knoten weitergeleitet wird, abzüglich der Summe der Verunreinigungen der beiden durch die Aufteilung erzeugten Partitionen.

Es ist wichtig, dass diese Werte relativ zu einem bestimmten Datensatz sind (sowohl die Fehlerreduzierung als auch die Anzahl der Stichproben sind datensatzspezifisch), daher können diese Werte nicht zwischen verschiedenen Datensätzen verglichen werden.

Soweit ich weiß, gibt es alternative Möglichkeiten, um Merkmalsbedeutungswerte in Entscheidungsbäumen zu berechnen. Eine kurze Beschreibung der obigen Methode findet sich in "Elements of Statistical Learning" von Trevor Hastie, Robert Tibshirani und Jerome Friedman.

Peter Prettenhofer
quelle
12

Dies ist das Verhältnis zwischen der Anzahl der Stichproben, die an einen Entscheidungsknoten weitergeleitet werden, an dem dieses Merkmal in einem der Bäume des Ensembles beteiligt ist, und der Gesamtzahl der Stichproben im Trainingssatz.

Merkmale, die an den Knoten der obersten Ebene der Entscheidungsbäume beteiligt sind, sehen tendenziell mehr Stichproben und haben daher wahrscheinlich eine größere Bedeutung.

Bearbeiten : Diese Beschreibung ist nur teilweise richtig: Gilles und Peters Antworten sind die richtige Antwort.

Ogrisel
quelle
1
Wissen Sie, ob es Papier / Dokumentation über die genaue Methode gibt? z.B. Breiman, 2001. Es wäre großartig, wenn ich ein geeignetes Dokument hätte, das ich für die Methodik zitieren könnte.
user2244670
@ogrisel Es wäre großartig, wenn Sie Ihre Antwort eindeutig als Erklärung für die "Gewichtung" markieren könnten. Die Gewichtung allein bestimmt nicht die Merkmalsbedeutung. Die "Verunreinigungsmetrik" ("Gini-Wichtigkeit" oder RSS) in Kombination mit den über Bäume gemittelten Gewichten bestimmt die Gesamtmerkmalbedeutung. Leider ist die Dokumentation zu scikit-learn hier: scikit-learn.org/stable/modules/… nicht korrekt und erwähnt fälschlicherweise "Tiefe" als Verunreinigungsmetrik.
Ariel
11

Wie @ GillesLouppe oben ausgeführt hat, implementiert scikit-learn derzeit die Metrik "mittlere Abnahme der Verunreinigung" für Feature-Wichtigkeiten. Ich persönlich finde die zweite Metrik etwas interessanter, bei der Sie die Werte für jedes Ihrer Features nach dem Zufallsprinzip einzeln permutieren und sehen, wie viel schlechter Ihre Out-of-Bag-Leistung ist.

Da Sie mit der Wichtigkeit von Merkmalen danach streben, wie viel jedes Merkmal zur Vorhersageleistung Ihres Gesamtmodells beiträgt, gibt Ihnen die zweite Metrik tatsächlich ein direktes Maß dafür, während die "mittlere Abnahme der Verunreinigung" nur ein guter Indikator ist.

Wenn Sie interessiert sind, habe ich ein kleines Paket geschrieben, das die Permutations-Wichtigkeitsmetrik implementiert und zur Berechnung der Werte aus einer Instanz einer zufälligen Waldklasse mit Scikit-Lernfunktion verwendet werden kann:

https://github.com/pjh2011/rf_perm_feat_import

Bearbeiten: Dies funktioniert für Python 2.7, nicht für 3

Peter
quelle
Hallo @Peter, wenn ich Ihren Code verwende, wird folgende Fehlermeldung angezeigt: NameError: Name 'xrange' ist nicht definiert.
Aizzaac
Hallo @Aizzaac. Es tut mir leid, dass ich neu im Schreiben von Paketen bin. Ich hätte also feststellen sollen, dass ich es für Python 2.7 geschrieben habe. Versuchen Sie def xrange (x): Geben Sie iter (range (x)) zurück, bevor Sie es ausführen
Peter
2

Lassen Sie mich versuchen, die Frage zu beantworten. Code:

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

Decision_Tree-Plot: Geben Sie
hier die Bildbeschreibung ein.
Wir können compute_feature_importance erhalten: [0. , 0.01333333,0.06405596,0.92261071]
Überprüfen Sie den Quellcode:

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

Versuchen Sie, die Funktionsbedeutung zu berechnen:

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

Wir erhalten feature_importance: np.array ([0,1.332,6.418,92.30]).
Nach der Normalisierung können wir ein Array erhalten ([0., 0.01331334, 0.06414793, 0.92253873]), dies ist dasselbe wie clf.feature_importances_.
Seien Sie vorsichtig, alle Klassen sollten Gewicht eins haben.

tengfei li
quelle
1

Für diejenigen, die einen Verweis auf die Dokumentation von scikit-learn zu diesem Thema oder einen Verweis auf die Antwort von @GillesLouppe suchen:

In RandomForestClassifier ist das estimators_Attribut eine Liste von DecisionTreeClassifier (wie in der Dokumentation erwähnt ). Um die feature_importances_für den RandomForestClassifier im Quellcode von scikit-learn zu berechnen , werden alle feature_importances_Attribute des Schätzers (alle DecisionTreeClassifer) im Ensemble gemittelt .

In der Dokumentation von DecisionTreeClassifer wird erwähnt, dass "die Wichtigkeit eines Merkmals als (normalisierte) Gesamtverringerung des durch dieses Merkmal hervorgerufenen Kriteriums berechnet wird. Es wird auch als Gini-Wichtigkeit bezeichnet [1]."

Hier ist ein direkter Link für weitere Informationen zur Variablen- und Gini-Wichtigkeit, wie in der folgenden Referenz von scikit-learn angegeben.

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

Makan
quelle