Sklearn kodunu kullanacağım , çünkü genellikle R
koddan 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).