Come vengono determinati feature_importances in RandomForestClassifier?


125

Ho un compito di classificazione con una serie temporale come input di dati, in cui ogni attributo (n = 23) rappresenta un momento specifico. Oltre al risultato di classificazione assoluto, vorrei scoprire quali attributi / date contribuiscono al risultato in che misura. Quindi sto solo usando il feature_importances_, che funziona bene per me.

Tuttavia, vorrei sapere come vengono calcolati e quale misura / algoritmo viene utilizzato. Purtroppo non sono riuscito a trovare documentazione su questo argomento.


10
Woah tre sviluppatori principali su un thread SO. Dev'essere una specie di disco ^^
Andreas Mueller,

Risposte:


158

Esistono in effetti diversi modi per ottenere "importanti" funzionalità. Come spesso, non esiste un rigoroso consenso sul significato di questa parola.

In scikit-learn, implementiamo l'importanza come descritto in [1] (spesso citato, ma purtroppo raramente letto ...). A volte viene chiamato "importanza gini" o "impurità di diminuzione media" ed è definito come la diminuzione totale dell'impurità del nodo (ponderata dalla probabilità di raggiungere quel nodo (che è approssimata dalla percentuale di campioni che raggiungono quel nodo)) mediata su tutto alberi dell'ensemble.

In letteratura o in altri pacchetti, puoi anche trovare le importazioni di funzionalità implementate come "accuratezza di riduzione media". Fondamentalmente, l'idea è quella di misurare la diminuzione della precisione dei dati OOB quando si autorizzano casualmente i valori per quella funzione. Se la riduzione è bassa, la funzione non è importante e viceversa.

(Si noti che entrambi gli algoritmi sono disponibili nel pacchetto randomForest R.)

[1]: Breiman, Friedman, "Alberi di classificazione e regressione", 1984.


48
Potrebbe essere fantastico se questa risposta fosse menzionata nella documentazione degli attributi / esempi di importanza. Lo
cercavo

2
Sembra che il punteggio di importanza sia in valore relativo? Ad esempio, la somma dei punteggi di importanza di tutte le funzionalità è sempre 1 (vedere l'esempio qui scikit-learn.org/stable/auto_examples/ensemble/… )
RNA

5
@RNA: Sì, per impostazione predefinita le importanza delle variabili sono normalizzate in scikit-learn, in modo tale che si sommino a una. È possibile aggirare il problema eseguendo il loop sui singoli stimatori di base e chiamando tree_.compute_feature_importances(normalize=False).
Gilles Louppe,

2
@GillesLouppe Usi i campioni out of bag per misurare la riduzione del MSE per una foresta di regressori dell'albero delle decisioni in ogni albero? O tutti i dati di allenamento utilizzati sull'albero?
Coca cola

1
Due risorse utili. (1) blog.datadive.net/… un blog di Ando Saabas implementa sia la "riduzione dell'impurità", sia la "riduzione dell'accuratezza", come indicato da Gilles. (2) Scarica e leggi la tesi di Gilles Louppe.
Mark Teese,

54

Il solito modo per calcolare i valori di importanza delle caratteristiche di un singolo albero è il seguente:

  1. si inizializza un array feature_importancesdi tutti zeri con dimensione n_features.

  2. attraversi l'albero: per ogni nodo interno che si divide in una funzione icalcola la riduzione dell'errore di quel nodo moltiplicata per il numero di campioni che sono stati instradati al nodo e aggiungi questa quantità a feature_importances[i].

La riduzione dell'errore dipende dal criterio di impurità utilizzato (ad es. Gini, Entropy, MSE, ...). È l'impurità dell'insieme di esempi che viene instradato al nodo interno meno la somma delle impurità delle due partizioni create dalla divisione.

È importante che questi valori siano relativi a un set di dati specifico (sia la riduzione degli errori che il numero di campioni sono specifici del set di dati), pertanto questi valori non possono essere confrontati tra set di dati diversi.

Per quanto ne so ci sono modi alternativi per calcolare i valori di importanza delle caratteristiche negli alberi delle decisioni. Una breve descrizione del metodo sopra riportato può essere trovata in "Elements of Statistical Learning" di Trevor Hastie, Robert Tibshirani e Jerome Friedman.


12

È il rapporto tra il numero di campioni instradati verso un nodo decisionale che coinvolge quella caratteristica in uno degli alberi dell'insieme rispetto al numero totale di campioni nel set di addestramento.

Le caratteristiche che sono coinvolte nei nodi di livello superiore degli alberi delle decisioni tendono a vedere più campioni, quindi hanno probabilmente più importanza.

Modifica : questa descrizione è solo parzialmente corretta: le risposte di Gilles e Peter sono la risposta corretta.


1
Sai se c'è qualche documento / documentazione sul metodo esatto? per esempio. Breiman, 2001. Sarebbe bello se avessi un documento adeguato, che potrei citare per la metodologia.
user2244670

@ogrisel sarebbe bello se tu potessi contrassegnare chiaramente la tua risposta come la spiegazione della "ponderazione". La ponderazione da sola non determina l'importanza della caratteristica. La "metrica di impurità" ("importanza gini" o RSS) combinata con i pesi, mediata sugli alberi, determina l'importanza generale delle caratteristiche. Sfortunatamente la documentazione su scikit-impara qui: scikit-learn.org/stable/modules/… non è accurata e menziona erroneamente "profondità" come metrica dell'impurità.
Ariel,

11

Come sottolineato da @GillesLouppe sopra, scikit-learn attualmente implementa la metrica "media riduzione dell'impurità" per le importazioni di feature. Personalmente trovo la seconda metrica un po 'più interessante, in cui permetti casualmente i valori per ciascuna delle tue caratteristiche uno per uno e vedo quanto peggiori le tue prestazioni fuori borsa.

Dal momento che ciò che stai cercando con l'importanza delle funzionalità è quanto ciascuna funzionalità contribuisce alle prestazioni predittive del tuo modello complessivo, la seconda metrica ti fornisce una misura diretta di ciò, mentre la "media riduzione dell'impurità" è solo un buon proxy.

Se sei interessato, ho scritto un piccolo pacchetto che implementa la metrica sull'importanza delle permutazioni e può essere utilizzato per calcolare i valori da un'istanza di una classe di foresta casuale di scikit-learn:

https://github.com/pjh2011/rf_perm_feat_import

Modifica: funziona con Python 2.7, non 3


Ciao @Peter quando uso il tuo codice, visualizzo questo errore: NameError: il nome 'xrange' non è definito.
Aizzaac,

Ciao @Aizzaac. Mi dispiace, sono nuovo a scrivere pacchetti, quindi avrei dovuto notare che l'ho scritto per Python 2.7. Prova def xrange (x): return iter (range (x)) prima di eseguirlo
Peter

2

Lasciami provare a rispondere alla domanda. codice:

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

grafico decision_tree:
inserisci la descrizione dell'immagine qui
Possiamo ottenere compute_feature_importance: [0. , 0.01333333,0.06405596,0.92261071]
Verifica il codice sorgente:

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

Prova a calcolare l'importanza della funzione:

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

Otteniamo feature_importance: np.array ([0,1.332,6.418,92,30]).
Dopo la normalizzazione, possiamo ottenere l'array ([0., 0.01331334, 0.06414793, 0.92253873]), è uguale a clf.feature_importances_.
Fai attenzione che tutte le classi dovrebbero avere un peso.


1

Per coloro che cercano un riferimento alla documentazione di scikit-learn su questo argomento o un riferimento alla risposta di @GillesLouppe:

In RandomForestClassifier, l' estimators_attributo è un elenco di DecisionTreeClassifier (come indicato nella documentazione ). Per calcolare il valore feature_importances_di RandomForestClassifier, nel codice sorgente di scikit-learn , esegue la media su tutti gli stimatori (tutti DecisionTreeClassifer)feature_importances_ attributi dello nell'insieme.

Nella documentazione di DecisionTreeClassifer , si afferma che "L'importanza di una caratteristica è calcolata come riduzione totale (normalizzata) del criterio introdotto da quella caratteristica. È anche nota come importanza di Gini [1]."

Ecco un link diretto per maggiori informazioni sulla variabile e sull'importanza di Gini, come indicato di seguito dal riferimento di scikit-learn.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.