RandomForestClassifier'daki feature_importances nasıl belirlenir?


125

Veri girişi olarak bir zaman serisine sahip bir sınıflandırma görevim var, burada her bir öznitelik (n = 23) zamanda belirli bir noktayı temsil ediyor. Mutlak sınıflandırma sonucunun yanı sıra, hangi niteliklerin / tarihlerin sonuca ne ölçüde katkıda bulunduğunu öğrenmek istiyorum. Bu nedenle ben sadece feature_importances_benim için iyi çalışan kullanıyorum .

Ancak, nasıl hesaplandıklarını ve hangi ölçü / algoritmanın kullanıldığını bilmek istiyorum. Maalesef bu konuyla ilgili herhangi bir belge bulamadım.


10
Bir SO iş parçacığında üç çekirdek geliştirici Woah. Bu bir çeşit rekor olmalı ^^
Andreas Mueller

Yanıtlar:


158

Özellik "önemlerini" almanın gerçekten birkaç yolu vardır. Çoğu zaman, bu kelimenin ne anlama geldiğine dair kesin bir fikir birliği yoktur.

Scikit-learn'de, önemi [1] 'de açıklandığı gibi uygularız (sıklıkla alıntılanır, ancak maalesef nadiren okunur ...). Bazen "gini önemi" veya "ortalama kirlilik azalması" olarak adlandırılır ve düğüm kirliliğindeki toplam azalma olarak tanımlanır (bu düğüme ulaşma olasılığı ile ağırlıklandırılır (bu düğüme ulaşan örneklerin oranıyla yaklaşık olarak belirlenir)) topluluğun ağaçları.

Literatürde veya diğer bazı paketlerde, "ortalama azalma doğruluğu" olarak uygulanan özellik önemlerini de bulabilirsiniz. Temel olarak fikir, o özelliğin değerlerine rastgele izin verdiğinizde OOB verilerindeki doğruluktaki düşüşü ölçmektir. Azalma düşükse, özellik önemli değildir ve bunun tersi de geçerlidir.

(Her iki algoritmanın da randomForest R paketinde bulunduğunu unutmayın.)

[1]: Breiman, Friedman, "Sınıflandırma ve regresyon ağaçları", 1984.


48
Önem niteliklerinin / örneğinin belgelerinde bu cevaba değinilmiş olsaydı harika olabilirdi. Bunu bir süredir arıyordum :)
d1337

2
Görünüşe göre önem puanı göreceli değerde mi? Örneğin, tüm özelliklerin önem puanlarının toplamı her zaman 1'dir (buradaki örneğe bakın scikit-learn.org/stable/auto_examples/ensemble/… )
RNA

5
@RNA: Evet, varsayılan olarak değişken ithalatları scikit-learn'de normalleştirilir, böylece bire toplanırlar. Bireysel temel tahmin ediciler üzerinde döngü oluşturarak ve arayarak bunu aşabilirsiniz tree_.compute_feature_importances(normalize=False).
Gilles Louppe

2
@GillesLouppe Her ağaçtaki karar ağacı gerileyicilerinden oluşan bir orman için MSE'deki azalmayı ölçmek için torba dışı örnekleri kullanıyor musunuz? Veya ağaçta kullanılan tüm eğitim verileri?
Kola

1
İki faydalı kaynak. (1) blog.datadive.net/… Ando Saabas tarafından hazırlanan bir blog, Gilles tarafından belirtildiği gibi hem "ortalama kirlilik azalması" hem de "doğrulukta ortalama düşüş" uygular. (2) Gilles Louppe'un tezini indirin ve okuyun.
Mark Teese

54

Tek bir ağacın özellik önem değerlerini hesaplamanın genel yolu aşağıdaki gibidir:

  1. feature_importancesboyutu ile tamamen sıfırlardan oluşan bir dizi başlatırsınız n_features.

  2. ağacın üzerinden geçersiniz: özelliği bölen her bir dahili düğüm için i, o düğümün hata azaltımını, düğüme yönlendirilen örnek sayısı ile çarpılır ve bu miktarı eklersiniz feature_importances[i].

Hata azaltma, kullandığınız kirlilik kriterine bağlıdır (örn. Gini, Entropy, MSE, ...). Dahili düğüme yönlendirilen örnekler kümesinin safsızlığı eksi bölünmenin yarattığı iki bölümün safsızlıklarının toplamıdır.

Bu değerlerin belirli bir veri kümesine göre olması önemlidir (hem hata azaltma hem de örnek sayısı veri kümesine özgüdür), bu nedenle bu değerler farklı veri kümeleri arasında karşılaştırılamaz.

Bildiğim kadarıyla karar ağaçlarında özellik önem değerlerini hesaplamanın alternatif yolları var. Yukarıdaki yöntemin kısa bir açıklaması Trevor Hastie, Robert Tibshirani ve Jerome Friedman tarafından yazılan "İstatistiksel Öğrenmenin Unsurları" nda bulunabilir.


12

Eğitim setindeki toplam örnek sayısı üzerinden topluluğun herhangi bir ağacındaki bu özelliği içeren bir karar düğümüne yönlendirilen örnek sayısı arasındaki orandır.

Karar ağaçlarının en üst düzey düğümlerinde yer alan özellikler daha fazla örnek görme eğilimindedir, bu nedenle büyük olasılıkla daha fazla önem taşır.

Düzenleme : Bu açıklama sadece kısmen doğrudur: Gilles ve Peter'ın cevapları doğru cevaptır.


1
Kesin yöntem hakkında bazı kağıt / belgeler olup olmadığını biliyor musunuz? Örneğin. Breiman, 2001. Metodoloji için alıntı yapabileceğim uygun bir belgem olsaydı harika olurdu.
user2244670

@ogrisel Yanıtınızı "ağırlıklandırma" nın açıklaması olarak açıkça işaretlerseniz harika olur. Tek başına ağırlıklandırma, özelliğin önemini belirlemez. Ağaçlara göre ortalaması alınan ağırlıklarla birleştirilmiş "safsızlık ölçüsü" ("gini-önem" veya RSS) genel özelliğin önemini belirler. Ne yazık ki burada scikit-learn ile ilgili dokümantasyon: scikit-learn.org/stable/modules/… doğru değildir ve safsızlık ölçütü olarak yanlış bir şekilde "derinlik" ten bahseder.
Ariel

11

@GillesLouppe'un yukarıda işaret ettiği gibi, scikit-learn şu anda özellik ithalatı için "ortalama kirlilik azalması" ölçüsünü uygulamaktadır. Ben şahsen ikinci ölçütü biraz daha ilginç buluyorum, burada her bir özelliğiniz için değerleri birer birer rastgele değiştiriyorsunuz ve çanta dışı performansınızın ne kadar kötü olduğunu görüyorsunuz.

Özellik önemi ile peşinde olduğunuz şey, her bir özelliğin genel modelinizin tahmin performansına ne kadar katkıda bulunduğu olduğundan, ikinci metrik aslında bunun doğrudan bir ölçüsünü verirken, "ortalama kirlilik azalması" sadece iyi bir temsilidir.

İlgileniyorsanız, Permütasyon Önem ölçüsünü uygulayan ve scikit-learn rastgele orman sınıfının bir örneğinden değerleri hesaplamak için kullanılabilecek küçük bir paket yazdım:

https://github.com/pjh2011/rf_perm_feat_import

Düzenleme: Bu, 3 için değil Python 2.7 için çalışır


Merhaba @Peter, kodunuzu kullandığımda şu hatayı alıyorum: NameError: name 'xrange' tanımlı değil.
Aizzaac

Merhaba @Aizzaac. Üzgünüm, paket yazma konusunda yeniyim, bu yüzden Python 2.7 için yazdığımı not etmeliydim. Def xrange (x) 'i deneyin: çalıştırmadan önce iter (aralık (x)) döndür
Peter

2

Soruyu cevaplamayı deneyeyim. kod:

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

karar_tree plot:
görüntü açıklamasını buraya girin
compute_feature_importance: [0. , 0.01333333,0.06405596,0.92261071]
Kaynak kodunu kontrol edin:

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

Özelliğin önemini hesaplamayı deneyin:

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

Feature_importance: np.array ([0,1.332,6.418,92.30]) alıyoruz.
Normalleştirildikten sonra, diziyi elde edebiliriz ([0., 0.01331334, 0.06414793, 0.92253873]), bu aynı clf.feature_importances_.
Dikkatli olun, tüm sınıfların bir ağırlığı olması gerekir.


1

Scikit-learn'ün bu konudaki belgelerine veya @GillesLouppe tarafından verilen yanıta referans arayanlar için:

RandomForestClassifier'da estimators_öznitelik, DecisionTreeClassifier'ın bir listesidir ( belgelerde belirtildiği gibi ). feature_importances_RandomForestClassifier için, scikit-learn'ün kaynak kodunda hesaplamak için, topluluktaki tüm tahmin edicinin (tüm DecisionTreeClassifer) feature_importances_özniteliklerinin ortalamasını alır.

DecisionTreeClassifer'in belgelerinde , "Bir özelliğin önemi, o özelliğin getirdiği kriterin (normalleştirilmiş) toplam azalması olarak hesaplanır. Gini önemi [1] olarak da bilinir."

İşte tarafından sağlanan değişken ve Gini önemine daha fazla bilgi için doğrudan bir bağlantı, aşağıda referans scikit-öğrenirler.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.