Tôi sẽ sử dụng mã sklearn , vì nó thường sạch hơn R
mã.
Đây là việc triển khai thuộc tính Feature_importances của GradientBoostingClassifier (Tôi đã xóa một số dòng mã cản trở các công cụ khái niệ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
Điều này là khá dễ hiểu. self.estimators_
là một mảng chứa các cây riêng lẻ trong booster, vì vậy vòng lặp for đang lặp trên các cây riêng lẻ. Có một cú hích với
stage_sum = sum(tree.feature_importances_
for tree in stage) / len(stage)
đây là chăm sóc của trường hợp phản ứng không nhị phân. Ở đây chúng tôi phù hợp với nhiều cây trong mỗi giai đoạn theo cách một đấu một. Về mặt khái niệm đơn giản nhất của nó là tập trung vào trường hợp nhị phân, trong đó tổng có một triệu và đây chỉ là một tree.feature_importances_
. Vì vậy, trong trường hợp nhị phân, chúng ta có thể viết lại tất cả như
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
Vì vậy, trong các từ, tổng hợp các tính năng quan trọng của từng cây, sau đó chia cho tổng số cây . Vẫn còn để xem làm thế nào để tính toán các tính năng quan trọng cho một cây.
Tính toán quan trọng của một cây được thực hiện ở cấp độ cython , nhưng nó vẫn tuân theo. Đây là phiên bản đã được dọn sạch của 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
Điều này khá đơn giản. Lặp lại thông qua các nút của cây. Miễn là bạn không ở một nút lá, hãy tính mức giảm độ tinh khiết của nút từ phần tách tại nút này và gán nó cho tính năng được tách trên
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)
Sau đó, khi hoàn tất, chia tất cả cho tổng trọng lượng của dữ liệu (trong hầu hết các trường hợp, số lượng quan sát)
importances /= nodes[0].weighted_n_node_samples
Cần nhắc lại rằng tạp chất là tên gọi chung cho số liệu sử dụng khi xác định phân chia để tạo ra khi trồng cây. Trong ánh sáng đó, chúng tôi chỉ đơn giản là tóm tắt mức độ phân chia trên mỗi tính năng cho phép chúng tôi giảm tạp chất trên tất cả các phần tách trong cây.
Trong bối cảnh tăng cường độ dốc, các cây này luôn là các cây hồi quy (giảm thiểu lỗi bình phương tham lam) phù hợp với độ dốc của hàm mất.