sklearn中获取特征重要度最直接的方式是DecisionTreeClassifier的feature_importances_属性,它基于不纯度减少加权平均计算,总和为1; criterion='entropy'时近似信息增益语义,但不等价;单棵树结果不稳定,推荐用RandomForest取均值或mutual_info_classif替代。

用 sklearn.tree.DecisionTreeClassifier 获取特征重要度最直接
树模型内置的 feature_importances_ 属性就是标准答案,它本质是基于不纯度减少(如基尼不纯度或信息熵)加权平均得到的,和信息增益强相关但不完全等价。训练完模型后直接访问即可:
from sklearn.tree import DecisionTreeClassifier from sklearn.datasets import make_classification <p>X, y = make_classification(n_samples=1000, n_features=4, n_informative=2, random_state=42) clf = DecisionTreeClassifier(criterion='entropy', random_state=42) clf.fit(X, y) print(clf.feature<em>importances</em>) # 输出长度为4的数组,对应每个特征的相对重要度
- 必须设
criterion='entropy'才能对齐信息增益语义;用'gini'时计算的是基尼不纯度下降,数值不可比 - 重要度总和恒为 1,是归一化后的相对值,不能直接当“信息增益比特数”解读
- 单棵树结果不稳定,若需鲁棒性,建议改用
RandomForestClassifier并取均值
手动算单个特征的信息增益要自己实现分割与熵计算
sklearn 不提供单特征 IG 的独立接口,得手写。核心是:对每个特征遍历所有可能分割点,计算划分前后的信息熵差,取最大值作为该特征的信息增益。
import numpy as np
from sklearn.metrics import mutual_info_score
<p>def info_gain(X_col, y):</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill11526" title="Python Hardener"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20dbae7c507.jpg" alt="Python Hardener" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill11526" title="Python Hardener">Python Hardener</a>
<p>通过完整的安全审查、代码整洁重构、健壮的错误处理、正确的日志记录以及完整的文档字符串覆盖,强化 Python 脚本。</p>
</div>
<a href="/xiazai/skill11526" title="Python Hardener" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><h1>简化版:仅支持二值分割(如中位数切分),实际需枚举所有唯一值或分位点</h1><pre class="brush:php;toolbar:false;">thresh = np.median(X_col)
y_left = y[X_col <= thresh]
y_right = y[X_col > thresh]
if len(y_left) == 0 or len(y_right) == 0:
return 0
ent_parent = entropy(y)
ent_left = entropy(y_left)
ent_right = entropy(y_right)
return ent_parent - (len(y_left)/len(y))*ent_left - (len(y_right)/len(y))*ent_rightdef entropy(y): _, counts = np.unique(y, return_counts=True) probs = counts / len(y) return -np.sum([p * np.log2(p) for p in probs if p > 0])
- 真实场景中,连续特征需离散化(如
pd.cut或KBinsDiscretizer),否则枚举分割点开销大 - 分类特征若为字符串,必须先用
LabelEncoder转成整数,否则entropy计算会出错 - 这个函数返回的是“最大单一分割带来的信息增益”,不是 sklearn 树中使用的加权平均路径增益
mutual_info_classif 是更省事的替代方案
如果你真正想要的是“特征和标签之间的互信息”(连续特征也能用),sklearn.feature_selection.mutual_info_classif 是更合适的选择——它底层用 KNN 估计互信息,对连续值友好,且无需预设模型结构。
立即学习“Python免费学习笔记(深入)”;
from sklearn.feature_selection import mutual_info_classif <p>mi_scores = mutual_info_classif(X, y, random_state=42) print(mi_scores) # 每个特征对应的互信息估计值(单位:nats,非比特)
- 结果不归一化,数值大小只反映相对强度;不同数据集之间不可比
- 默认使用 3 个近邻,样本少时容易高估,可调
n_neighbors参数压低噪声 - 注意它返回的是 互信息,数学上等于“平均信息增益”,但和决策树中按分裂节点累加的 IG 含义不同
别把 feature_importances_ 当成信息增益的精确替代
很多人误以为 feature_importances_ 就是各特征的信息增益值,其实它是在整棵树所有节点上、按样本权重加权求和的结果。同一个特征在不同路径上可能贡献多次,且受树深度、剪枝、随机性影响极大。
- 两棵结构相似的树,
feature_importances_可能相差 20% 以上,尤其小样本时 - 如果特征间存在强相关(如 X1 和 X2 高度共线),其中一个可能被树“随机选中”,另一个得分接近 0,但这不代表后者不重要
- 真要解释单特征预测力,
mutual_info_classif或排列重要度(permutation_importance)更透明、更可控

















