4.2. 置换特征重要性#
置换特征重要性是一种模型检查技术,用于衡量每个特征对给定表格数据集上已拟合模型的统计性能的贡献。这项技术对于非线性或不透明的估计器特别有用,它涉及随机打乱单个特征的值并观察模型分数的下降[1]。通过破坏特征和目标之间的关系,我们可以确定模型在多大程度上依赖于特定特征。
在下图中,我们观察到置换特征对特征与目标之间的相关性以及对模型统计性能的影响。
在上图中,我们观察到置换预测特征会破坏特征和目标之间的相关性,从而降低模型的统计性能。在下图中,我们观察到置换非预测特征不会显着降低模型的统计性能。
置换特征重要性的一个关键优势在于它是模型无关的,即它可以应用于任何已拟合的估计器。此外,它可以多次使用特征的不同置换来计算,从而进一步提供对特定训练模型的估计特征重要性方差的度量。
下图显示了在 Titanic 数据集的增强版本上训练的RandomForestClassifier
的置换特征重要性,该数据集包含random_cat
和random_num
特征,即与目标变量没有任何相关性的类别和数值特征。
警告
对于糟糕的模型(低交叉验证分数),被认为不重要的特征对于良好的模型可能非常重要。因此,在计算重要性之前,始终使用保留集(或更好地使用交叉验证)评估模型的预测能力非常重要。置换重要性并不反映特征本身的内在预测值,而是该特征对于特定模型的重要性。
permutation_importance
函数计算给定数据集的估计器的特征重要性。n_repeats
参数设置特征随机打乱的次数,并返回特征重要性的样本。
让我们考虑以下训练好的回归模型
>>> from sklearn.datasets import load_diabetes
>>> from sklearn.model_selection import train_test_split
>>> from sklearn.linear_model import Ridge
>>> diabetes = load_diabetes()
>>> X_train, X_val, y_train, y_val = train_test_split(
... diabetes.data, diabetes.target, random_state=0)
...
>>> model = Ridge(alpha=1e-2).fit(X_train, y_train)
>>> model.score(X_val, y_val)
0.356...
其通过\(R^2\)分数衡量的验证性能明显高于偶然水平。这使得可以使用permutation_importance
函数来探测哪些特征最具预测性。
>>> from sklearn.inspection import permutation_importance
>>> r = permutation_importance(model, X_val, y_val,
... n_repeats=30,
... random_state=0)
...
>>> for i in r.importances_mean.argsort()[::-1]:
... if r.importances_mean[i] - 2 * r.importances_std[i] > 0:
... print(f"{diabetes.feature_names[i]:<8}"
... f"{r.importances_mean[i]:.3f}"
... f" +/- {r.importances_std[i]:.3f}")
...
s5 0.204 +/- 0.050
bmi 0.176 +/- 0.048
bp 0.088 +/- 0.033
sex 0.056 +/- 0.023
请注意,前几个特征的重要性值代表了 0.356 参考分数的大部分。
可以在训练集或保留的测试集或验证集上计算置换重要性。使用保留集可以突出显示哪些特征对被检查模型的泛化能力贡献最大。在训练集上重要但在保留集上不重要的特征可能会导致模型过拟合。
排列特征重要性取决于使用scoring
参数指定的评分函数。此参数接受多个评分器,这比使用不同的评分器依次调用permutation_importance
多次在计算上更高效,因为它会重用模型预测。
使用多个评分器的排列特征重要性示例#
在下面的示例中,我们使用指标列表,但正如使用多指标评估中所述,还可以使用更多输入格式。
>>> scoring = ['r2', 'neg_mean_absolute_percentage_error', 'neg_mean_squared_error']
>>> r_multi = permutation_importance(
... model, X_val, y_val, n_repeats=30, random_state=0, scoring=scoring)
...
>>> for metric in r_multi:
... print(f"{metric}")
... r = r_multi[metric]
... for i in r.importances_mean.argsort()[::-1]:
... if r.importances_mean[i] - 2 * r.importances_std[i] > 0:
... print(f" {diabetes.feature_names[i]:<8}"
... f"{r.importances_mean[i]:.3f}"
... f" +/- {r.importances_std[i]:.3f}")
...
r2
s5 0.204 +/- 0.050
bmi 0.176 +/- 0.048
bp 0.088 +/- 0.033
sex 0.056 +/- 0.023
neg_mean_absolute_percentage_error
s5 0.081 +/- 0.020
bmi 0.064 +/- 0.015
bp 0.029 +/- 0.010
neg_mean_squared_error
s5 1013.866 +/- 246.445
bmi 872.726 +/- 240.298
bp 438.663 +/- 163.022
sex 277.376 +/- 115.123
即使重要性值的尺度差异很大,不同指标的特征排名也大致相同。但是,这并非绝对保证,不同的指标可能会导致显著不同的特征重要性,特别是对于训练用于不平衡分类问题的模型,在这种情况下,分类指标的选择至关重要。
4.2.1. 排列重要性算法概述#
输入:拟合的预测模型\(m\),表格数据集(训练或验证)\(D\)。
计算模型\(m\)在数据\(D\)上的参考分数\(s\)(例如,分类器的准确率或回归器的\(R^2\))。
对于每个特征\(j\)(\(D\)的列)
对于\({1, ..., K}\)中的每个重复\(k\)
随机打乱数据集\(D\)的第\(j\)列,以生成名为\(\tilde{D}_{k,j}\)的数据的损坏版本。
计算模型\(m\)在损坏数据\(\tilde{D}_{k,j}\)上的分数\(s_{k,j}\)。
计算特征\(f_j\)的重要性\(i_j\),定义如下:
\[i_j = s - \frac{1}{K} \sum_{k=1}^{K} s_{k,j}\]
4.2.2. 与树中基于杂质的重要性之间的关系#
基于树的模型提供了另一种衡量基于平均杂质减少的特征重要性 (MDI) 的方法。杂质由决策树的分割标准量化(基尼系数、对数损失或均方误差)。但是,当模型过拟合时,这种方法可能会赋予可能在未见数据上不可预测的特征较高的重要性。另一方面,基于排列的特征重要性避免了这个问题,因为它可以在未见数据上计算。
此外,树的基于杂质的特征重要性存在严重偏差,并偏向于高基数特征(通常是数值特征),而不是低基数特征,例如二元特征或具有少量可能类别的分类变量。
基于排列的特征重要性不会表现出这种偏差。此外,基于排列的特征重要性可以使用模型预测的任何性能指标来计算,并且可以用于分析任何模型类别(不仅仅是基于树的模型)。
以下示例突出了基于杂质的特征重要性与基于排列的特征重要性的局限性:排列重要性与随机森林特征重要性 (MDI)。