前言
笔者公司最近鼓捣了算法赛,主题是信贷违约风险预测,根据公司给的一部分数据集判断用户信贷违约的风险。
赛题本身没什么说的,就是一个典型赛题,数据是典型的表格型数据,因此模型方面采用的就是xgboost/lightgbm。做大量的特征工程,然后使用树类模型本身的特征筛选功能找重要特征,再拿重要特征重新做模型训练得到最终模型。
但事实上,树类模型(gbdt/xgboost/lightgbm等)本身给出的重要特征,可能是有bias的,为了解决这个问题,Strobl大佬在200年提出了Permutation importance,以解决树类模型再找重要性特征时的bias问题。
1. 模型默认的Feature Importance存在什么问题?
Strobl et al[3]在2007年就提出:树类模型默认的Feature Importance会偏好连续型变量或高基数(high cardinality)的类型型变量。这也很好理解,因为连续型变量或高基数的类型变量在树节点上更容易找到一个切分点,换言之更容易过拟合。
ps. 高基数变量指的是本身虽然是离散型,但是取值茫茫多的变量,如用户id,信用卡id,订单id这种可能每行数据的取值都不同的变量
另外一个问题是,Feature Importance体现的是训练完成的模型对特征的依赖程度,它说明的是训练集的信息,但不代表特征在测试集上的泛化能力。特别当训练集和测试集的分布有显著差异时,模型默认的Feature Importance的偏差和测试集实际需要的特征可能有极大的差异。
举一个极端的例子,如果我们随机生成一些X和二分类标签y,并用XGB不断迭代。随着迭代次数的增加,训练集的AUC将接近1,但是验证集上的AUC仍然会在0.5附近徘徊。如果我们查看模型的Feature Importance,就会发现,即使全部训练数据都是随机生成的,仍然会有一些特征的重要性特别高。这些特征导致模型过拟合,从而在训练集上实现了接近1的AUC。但实际上这些特征是无意义的。
2. 什么是Permutation Importance?
上一节提到,树类模型的Feature Importance主要有两个问题:
- 会偏好连续型变量或高基数(high cardinality)的类型型变量。
- 无法代表特征在测试集上的泛化能力
Permutation Importance是一种特征筛选的方法。它有效地解决了上述提到的两个问题。
Permutation Importance将特征随机打乱来破坏特征和数据标签原有的关系。如果打乱一个特征显著增加了模型在验证集上的loss,说明该特征很重要。如果打乱一个特征对模型在验证集上的loss没有影响,甚至还降低了loss,那么说明该特征对模型不重要。
变量重要性的具体计算步骤如下:
-
- 将数据分为训练集和验证集
-
- 在训练集上训练模型,在验证集计算指标(如AUC)
-
- 循环计算每个变量的重要性:
- (3.1) 在validation上对单个变量随机打乱;
- (3.2)使用第2步训练好的模型,重新在validation做预测,并评价模型;
- (3.3)计算第2步和第3.2步validation上模型评价的差异,得到该变量的重要性指标
Python代码步骤(model表示已经训练好的模型):
def permutation_importances(model, X, y, metric):
baseline = metric(model, X, y)
imp = []
for col in X.columns:
save = X[col].copy()
X[col] = np.random.permutation(X[col])
m = metric(model, X, y)
X[col] = save
imp.append(baseline - m)
return np.array(imp)
3 Permutation Importance的优劣势是什么?
3.1 优势
- 可以在任何模型上使用。不只是在基于决策树的模型,在线性回归,神经网络,任何模型上都可以使用,来判断重要特征,去除无用特征
- 不存在对连续型变量或高基数类别型变量的偏好。
- 体现了变量的泛化能力,当训练集和测试集数据分布差异较大时,该方法就会很有效
- 相较于循环的增加或剔除变量,不需要对模型重新训练,极大地降低了成本。但是循环地对模型做预测仍然会花费不少时间。
3.2 劣势
- 对变量进行随机打乱。这就要求随机打乱需要重复多次,以保证统计的显著性。
- 对相关性高的变量会低估重要性,模型默认的Feature Importance同样存在该问题。
4 Amex数据实例验证
我们直接以Kaggle的Amex数据作为实例,验证下Permutation Importance的效果。这里因为已经有人进行试验,所以就直接使用了已有的实验结果
考虑到Permutation Importance的随机性,我们将数据划分为10个fold,并且每个变量随机打乱10次,所以每个变量总共打乱100次,再计算打乱后模型评价差异的平均值,以保证统计上的显著性。之后我们可以再谈谈如何更好地随机打乱以节省资源。
这里我们分别对比3种变量重要性的排序:
- 模型默认的Feature Importance
- Permutation Importance
- 标准化后的Permutation Importance:Permutation Importance / 随机100次的标准差。这考虑到了随机性。如果在Permutation Importance差不多的情况下,标准差更小,说明该变量的重要性结果是更稳定的。
为了简化实验,这里随机筛选了总共300个变量。使用300个变量时,模型10 fold AUC为0.9597。
下表是不同变化重要性排序下,模型AUC随着变量个数增加的变化情况:
不同变量重要性排序下,模型效果的变化情况
由此我们可以得到如下结论:
- Permutation Importance相较于模型默认的Feature Importance具有更好的排序性。当变量个数小于250个时,使用Permutation Importance排序的变量模型效果都更好。
- 随着变量个数的增加,模型默认的Feature Importance和Permutation Importance两种排序的模型AUC差异逐渐减小。这也间接说明Permutation Importance的重要性排序更好。因为在变量个数少的时候,两种排序筛选的变量差异会更大。随着变量的增加,两种排序下变量的重合逐渐增加,差异逐渐减小。
- 标准化后的Permutation Importance效果仅略微好于Permutation Importance,这在真实业务场景意义较低,在建模比赛中有一定价值