我有一个分类任务,时间序列作为数据输入,其中每个属性(n = 23)代表一个特定的时间点。除了绝对分类结果我想知道,哪些属性/日期对结果的贡献程度如何。因此我只使用feature_importances_
,这对我很有用。
但是,我想知道如何计算它们以及使用哪种度量/算法。很遗憾,我找不到关于这个主题的任何文档。
答案 0 :(得分:130)
确实有几种方法可以获得“重要性”功能。通常,对于这个词的含义没有严格的共识。
在scikit-learn中,我们实现了[1]中描述的重要性(经常被引用,但遗憾的是很少阅读......)。它有时被称为“基尼重要性”或“平均减少杂质”,并被定义为节点杂质的总减少量(通过到达该节点的概率加权(通过到达该节点的样本的比例近似))合奏的树木。
在文献或其他一些软件包中,您还可以找到以“平均降低精度”实现的特征重要性。基本上,当您随机置换该功能的值时,我们的想法是测量OOB数据的准确性降低。如果降低量较低,则该特征不重要,反之亦然。
(请注意,这两种算法都可以在randomForest R包中找到。)
[1]:Breiman,Friedman,“分类和回归树”,1984年。
答案 1 :(得分:49)
计算单个树的特征重要性值的常用方法如下:
初始化大小为feature_importances
的所有零的数组n_features
。
遍历树:对于在功能i
上拆分的每个内部节点,您计算该节点的错误减少量乘以路由到节点的样本数并将此数量添加到{ {1}}。
错误减少取决于您使用的杂质标准(例如Gini,Entropy,MSE,......)。它是路由到内部节点的一组示例中的杂质减去由分割创建的两个分区的杂质之和。
重要的是这些值与特定数据集相关(误差减少和样本数量都是特定于数据集),因此无法在不同数据集之间比较这些值。
据我所知,还有其他方法可以在决策树中计算特征重要性值。上述方法的简要描述可以在Trevor Hastie,Robert Tibshirani和Jerome Friedman的“统计学习元素”中找到。
答案 2 :(得分:11)
它是在集合的任何树中路由到涉及该特征的决策节点的样本数与训练集中的样本总数之间的比率。
决策树的顶级节点中涉及的功能往往会看到更多样本,因此可能更重要。
编辑:此说明仅部分正确:Gilles和Peter的答案是正确答案。
答案 3 :(得分:10)
正如@GillesLouppe上面指出的那样,scikit-learn目前正在实施"平均减少杂质"功能重要性的度量标准。我个人觉得第二个指标更有趣,你可以逐个随机地对每个功能的值进行置换,看看你的包外性能有多差。
由于您在具有重要性的重要性之后,每个功能对整体模型的预测性能有多大贡献,第二个指标实际上可以直接衡量这一点,而"意味着减少杂质"只是一个很好的代理。
如果你有兴趣,我写了一个小包,它实现了Permutation Importance指标,可以用来计算scikit-learn随机森林类的实例中的值:
https://github.com/pjh2011/rf_perm_feat_import
编辑:这适用于Python 2.7,而非3
答案 4 :(得分:1)
让我尝试回答这个问题。 代码:
DateTime startDate = DateTime.Parse("2018-06-24 06:00");
DateTime endDate = DateTime.Parse("2018-06-24 11:45");
while (startDate.AddMinutes(15) <= endDate)
{
Console.WriteLine(startDate.ToString("yyyy-MM-dd HH:mm"));
startDate = startDate.AddMinutes(15);
}
decision_tree图:
enter image description here
我们可以得到compute_feature_importance:[0。 ,0.01333333,0.06405596,0.92261071]
检查源代码:
iris = datasets.load_iris()
X = iris.data
y = iris.target
clf = DecisionTreeClassifier()
clf.fit(X, y)
尝试计算功能重要性:
cpdef compute_feature_importances(self, normalize=True):
"""Computes the importance of each feature (aka variable)."""
cdef Node* left
cdef Node* right
cdef Node* nodes = self.nodes
cdef Node* node = nodes
cdef Node* end_node = node + self.node_count
cdef double normalizer = 0.
cdef np.ndarray[np.float64_t, ndim=1] importances
importances = np.zeros((self.n_features,))
cdef DOUBLE_t* importance_data = <DOUBLE_t*>importances.data
with nogil:
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
if normalize:
normalizer = np.sum(importances)
if normalizer > 0.0:
# Avoid dividing by zero (e.g., when root is pure)
importances /= normalizer
return importances
我们获得feature_importance:np.array([0,1.332,6.418,92.30])。
归一化后,我们可以得到数组([0.,0.01331334,0.06414793,0.92253873]),它与print("sepal length (cm)",0)
print("sepal width (cm)",(3*0.444-(0+0)))
print("petal length (cm)",(54* 0.168 - (48*0.041+6*0.444)) +(46*0.043 -(0+3*0.444)) + (3*0.444-(0+0)))
print("petal width (cm)",(150* 0.667 - (0+100*0.5)) +(100*0.5-(54*0.168+46*0.043))+(6*0.444 -(0+3*0.444)) + (48*0.041-(0+0)))
相同。
请注意,所有班级的体重都应该为一。
答案 5 :(得分:0)
对于那些希望参考该主题的scikit-learn文档或@GillesLouppe的答案的人们:
在RandomForestClassifier中,estimators_
属性是DecisionTreeClassifier的列表(如documentation中所述)。为了计算scikit-learn's source code中RandomForestClassifier的feature_importances_
,它对集合中所有估算器(所有DecisionTreeClassifer的)feature_importances_
属性的值进行平均。
在DecisionTreeClassifer的documentation中,提到了“特征的重要性是作为该特征带来的标准的(规范化)总缩减而计算的。这也被称为基尼重要性[1]。 “
Here是直接链接,以获取有关变量和基尼重要性的更多信息,如以下scikit-learn的参考资料所述。
[1] L. Breiman和A. Cutler,“随机森林”,http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm