मैं स्केलेर कोड का उपयोग करूँगा , क्योंकि यह आमतौर पर R
कोड की तुलना में बहुत अधिक क्लीनर है ।
यहां ग्रेडिएंटबॉस्टिंगक्लासीफायर के फीचर_इम्पोर्टेंस प्रॉपर्टी का कार्यान्वयन (मैंने वैचारिक सामान के रास्ते में आने वाली कोड की कुछ पंक्तियों को हटा दिया)
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
यह समझना बहुत आसान है। self.estimators_
बूस्टर में अलग-अलग पेड़ों से युक्त एक सरणी है, इसलिए लूप के लिए अलग-अलग पेड़ों पर चलना है। वहाँ के साथ एक hickup है
stage_sum = sum(tree.feature_importances_
for tree in stage) / len(stage)
यह गैर-द्विआधारी प्रतिक्रिया मामले का ध्यान रख रहा है। यहां हम एक-बनाम-सभी तरीके से प्रत्येक चरण में कई पेड़ों को फिट करते हैं। बाइनरी केस पर ध्यान केंद्रित करने के लिए इसकी सबसे सरल अवधारणा है, जहां योग का एक सारांश है, और यह बस है tree.feature_importances_
। तो बाइनरी केस में, हम यह सब फिर से लिख सकते हैं
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
तो, शब्दों में, व्यक्तिगत पेड़ों के फीचर इंपोर्टेंस को योग करें, फिर पेड़ों की कुल संख्या से विभाजित करें । यह देखने के लिए रहता है कि एकल पेड़ के लिए फीचर आयात की गणना कैसे करें।
एक पेड़ की महत्वपूर्ण गणना को साइथन स्तर पर लागू किया गया है , लेकिन यह अभी भी अनुसरण करने योग्य है। यहाँ कोड का एक साफ किया गया संस्करण है
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
यह बहुत आसान है। पेड़ के नोड्स के माध्यम से Iterate। जब तक आप एक पत्ती नोड पर नहीं होते हैं, तब तक इस नोड पर विभाजन से नोड शुद्धता में भारित कमी की गणना करें, और इसे उस विशेषता के लिए विशेषता दें जिस पर विभाजित किया गया था
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)
फिर, जब किया जाता है, तो इसे डेटा के कुल वजन से विभाजित करें (ज्यादातर मामलों में, टिप्पणियों की संख्या)
importances /= nodes[0].weighted_n_node_samples
यह याद रखने योग्य है कि अशुद्धता मीट्रिक का उपयोग करने के लिए एक सामान्य नाम है जब यह निर्धारित किया जाता है कि एक पेड़ उगते समय क्या विभाजन करना है। उस प्रकाश में, हम बस इस बात पर विचार कर रहे हैं कि प्रत्येक विशेषता पर विभाजन ने हमें पेड़ में सभी विभाजन को कम करने की अनुमति दी है।
ग्रेडिएंट बूस्टिंग के संदर्भ में, ये पेड़ हमेशा रिग्रेशन ट्री होते हैं (स्क्वैयर एरर को लालच से कम करके) नुकसान फंक्शन के ग्रेडिएंट में फिट होते हैं।