sklearn RandomForestClassifier如何衡量单棵决策树的重要性
单棵树重要性衡量方法(匹配「响应最多训练样本」的定义)
可以直接通过sklearn随机森林训练后自带的内置属性计算,不需要修改训练流程,按统计粒度分两种可直接复用的实现:
- 统计单棵树覆盖的不重复训练样本数
这个口径最贴合「响应最多训练样本」的定义:即统计有多少个不同的训练样本,实际参与了这棵树的训练过程。
随机森林默认采用有放回自助采样(bootstrap)生成每棵树的训练集,训练完成后可通过clf.estimators_samples_属性拿到每棵树的采样掩码:该属性是长度等于树总数的列表,每个元素是长度等于训练集总样本量的布尔数组,标记对应位置的训练样本是否被当前树的采样集命中。对布尔数组求和即可得到单棵树覆盖的不重复样本数,按数值降序排序就能得到树的重要性排名。
参考实现代码:# clf为已训练完成的RandomForestClassifier实例 tree_cover_count = [] for sample_mask in clf.estimators_samples_: cover_num = sample_mask.sum() tree_cover_count.append(cover_num) # 按覆盖样本数降序排序,返回对应树在clf.estimators_中的索引 sorted_tree_indices = sorted( range(len(tree_cover_count)), key=lambda x: tree_cover_count[x], reverse=True ) # 例如取覆盖样本数Top10的重要树 top_important_trees = [clf.estimators_[idx] for idx in sorted_tree_indices[:10]] - 统计单棵树训练输入的总样本量(含重复采样)
如果不需要对重复采样的样本去重,要统计自助采样阶段总共为这棵树抽取了多少个样本(同一样本被多次抽中会重复计数),不需要额外遍历采样掩码,直接读取每棵树根节点的样本计数属性即可——所有树的根节点索引固定为0,根节点的n_node_samples属性值就是这棵树训练时输入的总样本量。
参考实现代码:tree_total_sample_num = [] for single_tree in clf.estimators_: # 读取根节点记录的训练样本总数 total_num = single_tree.tree_.n_node_samples[0] tree_total_sample_num.append(total_num) # 排序逻辑和上述口径一致
注意:如果训练时手动指定参数
bootstrap=False,所有决策树都会用全量训练集训练,每棵树覆盖的样本数完全一致,这套衡量标准就会失效;默认参数bootstrap=True下计算结果完全准确。
补充说明:你观察到的「高重要性特征不一定出现在根节点,也可能出现在靠近叶节点的位置」是随机森林的正常表现——训练时每个节点分裂只会从随机抽取的特征子集里选最优分裂特征,就算是全局高重要性的特征,也可能因为当前树采样到的样本子集分布、节点分裂时特征随机采样未命中的原因,出现在深层分支中,和单棵树覆盖的样本量没有直接关联。
内容的提问来源于stack exchange,提问作者buchbinder92
相关产品推荐
相关产品推荐

