特征重要性:Permutation Importance
方法简介
一个最基本的问题大概会是什么特征对我模型预测的影响最大呢?我们有很多方法来衡量特征的重要性,这里呢,将会介绍一种方法:排列重要性。
工作原理
排列重要性,一定是在model训练完成后,才可以计算的。简单来说,就是改变数据表格中某一列的数据的排列,保持其余特征不动,看其对预测精度的影响有多大。
注意事项
- 事先排除相关性大的特征。
- 对于类别型特征,不适用。
- 对于类别特征做完one-hot编码之后,不太适用(因为有大量0,不能保证全部打乱,并且会导致一个样本有多个值为1),应该在做one-hot编码之前打乱顺序做。但是如何操作呢?:我现在还不知道。
两种方式
方式一
在数据集上训练并计算特征重要性。cv=None,或者k-fold,还可以用于与selectModel、RFE结合用于特征选择。
方式二
- 在数据集A上训练一个模型model
- 在数据集B上测试这个模型,得到MSE(回归)或者logloss(分类,或者auc)
- 对数据集B中的某一个特征中的值打乱(随机置换,random permute),再用模型进行预测,得到新的指标,这个指标在步骤2和3之间的差值,就是这个特征的重要性
- 把上一个步骤中打乱的column复原,换下一个column重复上一个步骤,直到所有column都算一遍。
代码
参数
- estimator:已经训练好的模型、未训练的模型
- cv值:有三种模式:prefit,None,k-fold.其中prefit适合检验模型、None、k-fold还可以用于与selectModel、RFE结合用于特征选择。prefit意味需要传入的是已经训练好的模型,对应的数据集可以是训练数据或者验证数据,它不再训练模型,只是在数据集上计算特征重要性,如果用于验证数据,则输出的特征重要性表征的是一般化的特征的重要性;None,训练和计算特征重要性在同一组数据集,输出的不是一般化的特征重要性;k-fold训练模型,并在一系列的训练测试集上计算特征重要性,最终的特征重要性返回的是平均值,不是最终模型的特征重要性,但是是一般化的特征重要性。
- refit:如果使用交叉验证,是否在所有数据集上训练模型,默认是True。
- n_iter:默认为5,迭代次数,降低该值以提高速度,增加以获得更精确的估计。
scoring:评价指标。
属性
feature_importances_:特征重要性,返回的是当每列被随机打乱后和打乱前的差值。
- feature_importances_std_:特征重要性方差。
- results_:所有实验的所有差值。
- scores_s:所有实验的所有初始值。
estimator_:如果模型传入时是未训练好的模型时,返回训练后的模型。
代码说明
eli5.show_weights好像用不了,建议自己实现。
- 本代码没有设置cv值,默认是prefit,所以此处传入的是已经训练好的模型。
- 问题/疑问:在训练集和测试集上分别计算重要性,差别较大(特征未处理,可能存在相关性、类别特征),是什么原因呢?应该用哪个数据集来做呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
import eli5 # python计算permutation importance工具包
from eli5.sklearn import PermutationImportance
path = 'data.csv'
data = pd.read_csv(path)
#...省略数据预处理过程
X_train, X_test, y_train, y_test = train_test_split(df, y, test_size=0.2, random_state = 400)
# 训练XGBoost模型
model = xgb.XGBClassifier(
learning_rate =0.05,
n_estimators=100,
max_depth=3,
min_child_weight=1,
gamma=0.3,
subsample=0.8,
colsample_bytree=0.8,
objective= 'multi:softprob',
nthread=4,
scale_pos_weight=1,
num_class=2,
seed=27
).fit(X_train, y_train)
## 默认是prefit,所以此处传入的是已经训练好的模型。
perm = PermutationImportance(model, random_state = 1).fit(X_test, y_test)
## 可视化:这个现在好像不能用。建议自己实现。
eli5.show_weights(perm, feature_names = X_test.columns.tolist())
源码
https://github.com/TeamHG-Memex/eli5/blob/master/eli5/sklearn/permutation_importance.py#L202