Bagaimana feature_importances di RandomForestClassifier ditentukan?

125

Saya memiliki tugas klasifikasi dengan serangkaian waktu sebagai input data, di mana setiap atribut (n = 23) mewakili titik waktu tertentu. Selain hasil klasifikasi absolut, saya ingin mencari tahu, atribut / tanggal mana yang berkontribusi pada hasil sejauh mana. Karena itu saya hanya menggunakan feature_importances_, yang berfungsi dengan baik untuk saya.

Namun, saya ingin tahu bagaimana mereka dihitung dan ukuran / algoritma apa yang digunakan. Sayangnya saya tidak dapat menemukan dokumentasi tentang topik ini.

pengguna2244670
sumber
10
Woah tiga pengembang inti dalam satu utas SO. Itu pasti semacam rekaman ^^
Andreas Mueller

Jawaban:

158

Memang ada beberapa cara untuk mendapatkan fitur "kepentingan". Seperti sering, tidak ada konsensus ketat tentang apa arti kata ini.

Dalam scikit-learning, kami mengimplementasikan pentingnya seperti yang dijelaskan dalam [1] (sering dikutip, tetapi sayangnya jarang membaca ...). Kadang-kadang disebut "gini pentingnya" atau "berarti penurunan pengotor" dan didefinisikan sebagai penurunan total pengotor simpul (dibobot oleh probabilitas mencapai simpul itu (yang diperkirakan oleh proporsi sampel mencapai simpul itu)) rata-rata atas semua pohon ansambel.

Dalam literatur atau dalam beberapa paket lain, Anda juga dapat menemukan pentingnya fitur diimplementasikan sebagai "akurasi penurunan rata-rata". Pada dasarnya, idenya adalah untuk mengukur penurunan akurasi pada data OOB ketika Anda secara acak mengubah nilai untuk fitur itu. Jika penurunannya rendah, maka fitur itu tidak penting, dan sebaliknya.

(Perhatikan bahwa kedua algoritma tersedia dalam paket R randomForest.)

[1]: Breiman, Friedman, "Klasifikasi dan pohon regresi", 1984.

Gilles Louppe
sumber
48
Bisa jadi hebat jika jawaban ini disebutkan dalam dokumentasi atribut / contoh penting.
Sedang
2
Tampaknya skor pentingnya adalah nilai relatif? Misalnya, jumlah skor penting dari semua fitur selalu 1 (lihat contoh di sini scikit-learn.org/stable/auto_examples/ensemble/… )
RNA
5
@RNA: Ya, secara default variabel impor dinormalisasi di scikit-learn, sehingga semuanya berjumlah satu. Anda dapat mengelak dari ini dengan mengulangi penaksir dan basis panggilan individual tree_.compute_feature_importances(normalize=False).
Gilles Louppe
2
@GillesLouppe Apakah Anda menggunakan sampel dari kantong untuk mengukur pengurangan MSE untuk hutan pembuat keputusan di setiap pohon? Atau semua data pelatihan digunakan di pohon?
Kokas
1
Dua sumber daya yang bermanfaat. (1) blog.datadive.net/... sebuah blog oleh Ando Saabas mengimplementasikan baik "berarti mengurangi ketidakmurnian" dan juga "berarti mengurangi keakuratan" seperti yang disebutkan oleh Gilles. (2) Unduh dan baca tesis Gilles Louppe.
Mark Teese
54

Cara biasa untuk menghitung nilai pentingnya fitur dari satu pohon adalah sebagai berikut:

  1. Anda menginisialisasi array feature_importancessemua nol dengan ukuran n_features.

  2. Anda melintasi pohon: untuk setiap node internal yang terbagi pada fitur iAnda menghitung pengurangan kesalahan dari node yang dikalikan dengan jumlah sampel yang diarahkan ke node dan menambahkan jumlah ini ke feature_importances[i].

Pengurangan kesalahan tergantung pada kriteria pengotor yang Anda gunakan (mis. Gini, Entropy, MSE, ...). Ini adalah pengotor dari sekumpulan contoh yang dialihkan ke simpul internal dikurangi jumlah pengotor dari dua partisi yang dibuat oleh split.

Penting bahwa nilai-nilai ini relatif terhadap dataset tertentu (baik pengurangan kesalahan dan jumlah sampel spesifik dataset) sehingga nilai-nilai ini tidak dapat dibandingkan antara dataset yang berbeda.

Sejauh yang saya tahu ada cara alternatif untuk menghitung fitur nilai penting dalam pohon keputusan. Penjelasan singkat tentang metode di atas dapat ditemukan dalam "Elemen Pembelajaran Statistik" oleh Trevor Hastie, Robert Tibshirani, dan Jerome Friedman.

Peter Prettenhofer
sumber
12

Ini adalah rasio antara jumlah sampel yang dialihkan ke simpul keputusan yang melibatkan fitur tersebut di salah satu pohon ansambel terhadap jumlah sampel dalam set pelatihan.

Fitur yang terlibat dalam node tingkat atas dari pohon keputusan cenderung melihat lebih banyak sampel sehingga cenderung lebih penting.

Sunting : deskripsi ini hanya sebagian benar: jawaban Gilles dan Peter adalah jawaban yang benar.

ogrisel
sumber
1
Apakah Anda tahu jika ada beberapa kertas / dokumentasi tentang metode yang tepat? misalnya. Breiman, 2001. Alangkah baiknya jika saya memiliki beberapa dokumen yang tepat, yang dapat saya kutip untuk metodologi.
user2244670
@ogrisel akan lebih bagus jika Anda bisa dengan jelas menandai respons Anda sebagai penjelasan untuk "bobot". Bobot saja tidak menentukan pentingnya fitur. "Metrik pengotor" ("gini-pentingnya" atau RSS) dikombinasikan dengan bobot, rata-rata di atas pohon menentukan keseluruhan fitur penting. Sayangnya dokumentasi pada scikit-pelajari di sini: scikit-learn.org/stable/modules/… tidak akurat dan salah menyebutkan "kedalaman" sebagai metrik pengotor.
Ariel
11

Seperti yang ditunjukkan @GillesLouppe di atas, scikit-learn saat ini mengimplementasikan metrik "mean reduction impurity" untuk kepentingan fitur. Saya pribadi menemukan metrik kedua sedikit lebih menarik, di mana Anda secara acak mengubah nilai untuk masing-masing fitur Anda satu per satu dan melihat seberapa buruk kinerja out-of-bag Anda.

Karena apa yang Anda kejar dengan pentingnya fitur adalah seberapa banyak masing-masing fitur berkontribusi pada kinerja prediktif keseluruhan model Anda, metrik kedua sebenarnya memberi Anda ukuran langsung dari ini, sedangkan "pengurang penurunan rata-rata" hanyalah proxy yang bagus.

Jika Anda tertarik, saya menulis sebuah paket kecil yang mengimplementasikan metrik Permutasi Penting dan dapat digunakan untuk menghitung nilai dari turunan kelas hutan acak scikit-learn:

https://github.com/pjh2011/rf_perm_feat_import

Sunting: Ini berfungsi untuk Python 2.7, bukan 3

Peter
sumber
Hai @ Peter ketika saya menggunakan kode Anda, saya mendapatkan kesalahan ini: NameError: name 'xrange' tidak didefinisikan.
Aizzaac
Hai @Aizzaac. Maaf saya baru menulis paket, jadi saya seharusnya mencatat saya menulisnya untuk Python 2.7. Coba def xrange (x): return iter (range (x)) sebelum menjalankannya
Peter
2

Biarkan saya coba jawab pertanyaannya. kode:

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

decision_tree plot:
masukkan deskripsi gambar di sini
Kita bisa mendapatkan compute_feature_importance: [0. , 0,01333333,0.06405596,0.92261071]
Periksa kode sumber:

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

Coba hitung kepentingan fitur:

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

Kami mendapatkan feature_importance: np.array ([0,1.332,6.418,92.30]).
Setelah dinormalisasi, kita bisa mendapatkan array ([0, 0,01331334, 0,06414793, 0,92253873]), ini sama dengan clf.feature_importances_.
Hati-hati semua kelas seharusnya memiliki berat satu.

tengfei li
sumber
1

Bagi mereka yang mencari referensi ke dokumentasi scikit-learn tentang topik ini atau referensi ke jawaban oleh @GillesLouppe:

Dalam RandomForestClassifier, estimators_atribut adalah daftar DecisionTreeClassifier (sebagaimana disebutkan dalam dokumentasi ). Untuk menghitung feature_importances_untuk RandomForestClassifier, dalam kode sumber scikit-learn , rata-rata semua feature_importances_atribut estimator (semua DecisionTreeClassifer) dalam ensemble.

Dalam dokumentasi DecisionTreeClassifer , disebutkan bahwa "Pentingnya fitur dihitung sebagai pengurangan total (normalisasi) dari kriteria yang dibawa oleh fitur itu. Ia juga dikenal sebagai kepentingan Gini [1]."

Berikut adalah tautan langsung untuk info lebih lanjut tentang variabel dan pentingnya Gini, seperti yang disediakan oleh referensi scikit-learn di bawah ini.

[1] L. Breiman, dan A. Cutler, “Hutan Acak”, http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm

Makan
sumber