Yükseltme için göreceli değişken önemi


33

Göreceli değişken öneminin aşırı genel / basit olmayan Gradient Boostted Trees içinde nasıl hesaplandığına dair bir açıklama arıyorum:

Ölçümler, bir değişkenin bölünme için seçilme sayısına dayanır, her bölünmenin sonucu olarak karenin iyileştirilmesiyle ağırlıklandırılır ve tüm ağaçların ortalaması alınır . [ Elith ve diğ. 2008, Regresyon ağaçlarının güçlendirilmesi için bir çalışma rehberi ]

Ve bu daha az soyut:

benj2^(T)=Σt=1J-1bent2^1(vt=j)

Toplama terminal olmayan düğüm üzerinde olduğu zaman ait J terminal Düğüm ağacı T , V t bölme düğümü ile ilişkili değişken t ve ^ ı 2 t bölünme sonucu olarak kare hata gelen ampirik bir gelişmedir, tanımlanmış olarak ı 2 ( R l , R ' R ) = ağırlık l w rtJTvttbent2^, ¯ y l , ¯ y r , sırasıyla, sol ve sağ kızı tepki araçları, vewl,ağırlıkrağırlıklarının gelen toplamıdır. ben2(R,l,R,r)=wlwrwl+wr(yl¯-yr¯)2yl¯,yr¯wl,wr[Friedman 2001, Açgözlü fonksiyon yaklaşımı: bir gradyan artırma makinesi]

Son olarak, İstatistiksel Öğrenmenin Öğelerini (Hastie ve ark. 2008) çok yararlı buldum, çünkü ilgili bölüm (10.13.1 sayfa 367) yukarıdaki ikinci referansa çok benziyor (bu açıklanabilir). Friedman'ın kitabın yazarlarından biri olması gerçeğiyle).

PS: Ben göreli değişken önem önlemler tarafından verilmiştir biliyorum summary.gbm gbm R paketinde. Kaynak kodu araştırmaya çalıştım, ancak gerçek hesaplamanın gerçekleştiği yeri bulamıyorum.

Brownie noktaları: Bu arazileri R'de nasıl elde edeceğimi merak ediyorum .


Sadece yararlı olabilir sınıfı tarafından değişken önemini çizmek konusunda bağlantılı soruya yeni bir yanıt eklendi stackoverflow.com/a/51952918/3277050
see24

Yanıtlar:


55

Sklearn kodunu kullanacağım , çünkü genellikle Rkoddan daha temiz .

GradientBoostingClassifier öğesinin feature_importances özelliğinin uygulaması ( kavramsal öğelerin önüne geçen bazı kod satırlarını kaldırdım)

def feature_importances_(self):
    total_sum = np.zeros((self.n_features, ), dtype=np.float64)
    for stage in self.estimators_:
        stage_sum = sum(tree.feature_importances_
                        for tree in stage) / len(stage)
        total_sum += stage_sum

    importances = total_sum / len(self.estimators_)
    return importances

Bunu anlamak oldukça kolaydır. self.estimators_güçlendiricideki ayrı ağaçları içeren bir dizidir, bu nedenle for döngüsü tek tek ağaçların üzerinde yinelenir. İle bir hickup var

stage_sum = sum(tree.feature_importances_
                for tree in stage) / len(stage)

bu ikili olmayan cevap durumuyla ilgileniyor. Burada, her aşamada birden çok ağacı tek tek vs şeklinde sığdırıyoruz. Kavramsal olarak en basit olanı, toplamın bir toplamı olduğu ikili duruma odaklanmaktır tree.feature_importances_. İkili durumda, hepsini şöyle yeniden yazabiliriz.

def feature_importances_(self):
    total_sum = np.zeros((self.n_features, ), dtype=np.float64)
    for tree in self.estimators_:
        total_sum += tree.feature_importances_ 
    importances = total_sum / len(self.estimators_)
    return importances

Yani, kelimelerle, tek tek ağaçların özellik önemini özetleyin, ardından toplam ağaç sayısına bölün . Tek bir ağaç için özellik öneminin nasıl hesaplanacağını görmek için kalır.

Bir ağacın öneminin hesaplanması cython düzeyinde gerçekleştirilir , ancak yine de takip edilebilir. İşte kodun temizlenmiş bir sürümü

cpdef compute_feature_importances(self, normalize=True):
    """Computes the importance of each feature (aka variable)."""

    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

    return importances

Bu oldukça basit. Ağacın düğümleri boyunca yineleyin. Bir yaprak düğümünde olmadığınız sürece, düğüm düğümündeki düğüm saflığındaki ağırlıklı azalmayı bu düğümdeki bölünmeden hesaplayın ve bunu bölünmüş olan özelliğe ekleyin.

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)

Sonra, yapıldığında, hepsini verilerin toplam ağırlığına bölün (çoğu durumda, gözlem sayısı)

importances /= nodes[0].weighted_n_node_samples

Bir ağaç yetiştirirken hangi bölünmenin yapılacağının belirlenmesinde kirliliğin metriğin kullanması için ortak bir ad olduğunu hatırlamakta fayda var . Bu ışık altında, her bir özelliğe ne kadar ayrılmanın ağaçtaki bütün bölmelerdeki kirliliği azaltmamızı sağladığını basitçe özetliyoruz.

Gradyan yükseltme bağlamında, bu ağaçlar her zaman kayıp fonksiyonunun gradyanına uygun olan regresyon ağaçlarıdır (açılı kareli hatayı en aza indirirler).


Bu çok ayrıntılı cevap için çok teşekkür ederim. Kabul etmeden önce dikkatlice geçmesi için biraz zaman ver.
Antoine

4
Çeşitli kirlilik kriterlerinin kullanılabileceği gözükse de, Gini endeksi Friedman tarafından kullanılan kriter değildi. Benim sorumumda ve üçüncü bağlantınızın 878. satırında belirtildiği gibi Friedman, ortalama kare hata kirlilik kriterini iyileştirme puanıyla kullandı . Cevabınızın bu bölümünü güncelleyebilirseniz, bu harika olurdu. Ve evet, haklısınız, görünüşe göre ağırlıklar gerçekten gözlemlerin sayısı.
Antoine

3
ya da belki Gini endeksi ve Friedman'ın orijinal kriteri ile ilgili kısımları korumak, cevabınızı daha da iyi hale getirecek, birinci sınıflamanın ikincisinin regresyon için kullanıldığını vurgulayarak?
Antoine

Antoine, bu güncelleme için teşekkürler. Ortalama kare hatanın regresyon ağaçları için kullanılan iyileştirme kriterleri olduğunu bilmek gerçekten yararlıdır. Bunun sınıflandırma için nasıl kullanılacağı belli değildi. Bununla birlikte, sınıflandırma için gradyanı artırırken bile, sınıflandırma ağaçlarının aksine, regresyon ağaçlarının hala kullanılmakta olduğunu düşünüyorum. En azından python'da regresyon analizi, her bir yükseltme aşamasında mevcut hata üzerinde yapılır.
Oldukça İnek

Regresyon ağaçları konusunda haklısınız.
Matthew Drury
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.