本站原创文章,转载请说明来自《老饼讲解-机器学习》www.bbbdata.com
本文讲解sklearn决策树中特征权重feature_importances是什么
并根据feature_importances的计算逻辑,用代码重现sklearn的feature_importances计算
本节介绍决策树的feature_importances是什么,以及feature_importances的计算流程
决策树的feature_importances是什么
在sklearn中,使用clf=sklearn.tree.DecisionTreeClassifier()构建决策树后
可以通过clf.feature_importances查看各个特征的重要性指标,即各个特征对模型的贡献性占比
例如, feature_importances=[0 , 0, 0.05, 0.95]
则代表第1、2个对象对模型的贡献为0,第3个特征贡献度为5% ,第4个特征贡献度为95%
那么,feature_importances是怎么计算出来的呢?下面进行讲解
决策树的feature_importances的公式推导
在决策树中,变量的特征权重指的是该变量对降低树的不纯度所作的贡献
特征权重feature_importances的推导与计算逻辑如下:
先考虑单节点,特征对单个节点分裂带来的不纯度降低量(即贡献)为:
这里的impurity为不纯度评估值 (gini/熵)
如果考虑节点的权重,则为
特征的权重为使用该特征分裂节点的贡献总和:
将所有特征的权重归一化后即得到特征权重:
决策树的feature_importances的计算流程
feature_importances的计算流程如下:
1. 计算每个分枝节点分枝带来的不纯度的降低量。
2. 把节点的不纯度降低量累加到对应的特征贡献上(节点分裂使用的特征)
3. 计算完所有节点后,对特征贡献作归一化即得到特征权重。
本节讲解如何用代码自行计算决策树的feature_importances
自行计算feature_importances
下面我们按以上计算逻辑,编写代码计算feature_importances,
再与sklearn给出的feature_importances作比较,验证以上逻辑就是sklearn中的逻辑
具体代码如下:
# -*- coding: utf-8 -*-
from sklearn.datasets import load_iris
from sklearn import tree
import numpy as np
#----------------数据准备----------------------------
iris = load_iris() # 加载数据
#---------------模型训练---------------------------------
clf = tree.DecisionTreeClassifier(random_state=0,max_depth=3)
clf = clf.fit(iris.data, iris.target)
#---------------提取模型结构数据--------------------------
children_left = clf.tree_.children_left # 左节点编号
children_right = clf.tree_.children_right # 右节点编号
feature = clf.tree_.feature # 分割的变量
threshold = clf.tree_.threshold # 分割阈值
impurity = clf.tree_.impurity # 不纯度(gini)
n_node_samples = clf.tree_.n_node_samples # 样本个数
value = clf.tree_.value # 样本分布
n_features = clf.tree_.n_features # 特征个数
total_n = n_node_samples[0] # 样本总个数
feature_importances = np.zeros(n_features) # 初始化特征权重全为0
for i in range(len(feature)): # 逐节点计算
use_feature = feature[i] # 当前节点使用的特征
if(use_feature<0): # 如果是叶子,则跳过
continue
left_idx = children_left[i] # 左节点索引
right_idx = children_right[i] # 右节点索引
left_impurity = impurity[left_idx] # 左节点不纯度
right_impurity = impurity[right_idx] # 右节点不纯度
node_impurity = impurity[i] # 节点不纯度
node_n = n_node_samples[i] # 节点样本数
left_n = n_node_samples[left_idx] # 左节点样本数
right_n = n_node_samples[right_idx] # 右节点样本数
importances = (node_n/total_n)*( node_impurity - (left_n/node_n)*left_impurity - (right_n/node_n)*right_impurity)
feature_importances[use_feature] += importances # 将权重累计到对应的变量上
feature_importances = feature_importances/feature_importances.sum() # 归一化
#---------------打印结果------------------------------------
print("模型计算结果feature_importances:",clf.feature_importances_)
print("自行计算结果feature_importances:",feature_importances)
注意:如果样本是带权重的,则计算过程中应用 样本权重个数 替代 样本个数
代码运行结果如下:
从结果可见,自行计算与模型输出结果一致
End