如何衡量变量重要性?
为了挑出优质变量,我们可能会考虑:
变量的预测能力
变量之间的相关性
变量的简单性(容易生成和使用)
变量的健壮性(适用于各种情形)
变量在业务上的可解释性(被挑战时可以解释的通)
其中,预测能力是最主要的影响因素。
如何衡量变量的预测能力呢,可以采用通用方法:计算IV、信息增益或基尼系数等等;也可以为特定模型设计特定的计算方法,本文针对线性模型和随机森林模型,解释了变量重要性是如何计算的。
一、通用计算方法
Information Value(IV),信息值,可以用来衡量自变量的预测能力。类似的指标还有信息增益、基尼系数等,它们的原理类似。
计算这类指标时,并不需要考虑具体使用的模型算法是什么。
IV的原理是什么?如何计算?
①首先,只有类别变量才能计算IV,因此,连续变量需要先分箱(分区间)
②对于类别变量,需要计算该变量中每一个类别的WOE(weight of evidence)
计算公式为:
woe计算
WOE表示的含义即是"当前分组中响应客户占所有响应客户的比例"和"当前分组中没有响应的客户占所有没有响应客户的比例"的差异。
③计算变量中每个类别对应的IV
计算公式为:
类别 i 的IV值
④计算整个变量的IV
很简单,加总所有类别的IV值。
计算公式为:
变量的IV值
python实现IV计算
Python中没有现成的功能模块,本人写了一个函数,有兴趣可以参考一下:
def woe_iv(data, feature, label):
'''
:param data: DataFrame,
data files contain feature and label
:param feature: String
a predict variable
:param label: String
the object variable
:return: information value of given feature
'''
data = data[[feature, label]]
cato_num = data.groupby(feature).count().reset_index()
default_num = data.groupby(feature).sum().reset_index()
all_number = data.shape[0]
default_number = data[label].sum()
normal_number = all_number - default_number
iv = 0
for i in np.arange(cato_num.shape[0]):
p_default = default_num[label][i]/default_number
p_normal = (cato_num[label][i] - default_num[label][i])/normal_number
if p_default == 0 or p_normal == 0:
print('woe_{}_{} is not avalible'.format(feature, cato_num[feature][i]))
else:
locals()['woe_{}'.format(cato_num[feature][i])] = \
np.log(p_normal / p_default)
print('woe_{}: {}'.format(cato_num[feature][i],
locals()['woe_{}'.format(cato_num[feature][i])]))
iv = iv + (p_normal - p_default) * locals()['woe_{}'.format(cato_num[feature][i])]
print('iv of {}: '.format(feature), iv)
return iv
测试一波~
import numpy as np
# 生成data,包括x1,x2,x3三个自变量
x1 = np.random.randint(-3, 3, (1000))
x2 = 1.5*np.random.randint(-3, 3, (1000))
x3 = 0.5*np.random.randint(-3, 3, (1000))
y = (1 + x1 + x2 + x3 + np.random.randn()) > 0
X = np.column_stack([x1, x2, x3])
data = pd.DataFrame(X, columns=['x1', 'x2', 'x3'])
data['y'] = y
woe_iv(data, 'x1', 'y')
woe_iv函数能输出变量的每个类别的woe值,并返回iv值。
二、在模型中计算变量重要性
1.线性模型及逻辑回归
线性模型及逻辑回归中,给定一个变量,衡量它的影响力的最简单的量化方法就是,将变量的系数乘以该变量的标准差。
import numpy as np
from sklearn.linear_model import LogisticRegression
x1 = np.random.randn(100)
x2 = 4*np.random.randn(100)
x3 = 0.5*np.random.randn(100)
y = (3 + x1 + x2 + x3 + 0.2*np.random.randn()) > 0
X = np.column_stack([x1, x2, x3])
m = LogisticRegression()
m.fit(X, y)
# 逻辑回归估计的参数都接近1:
print(m.coef_)
# 以下输出说明了X2有更强的预测能力,符合预期
print(np.std(X, 0)*m.coef_)
乘以变量标准差是为了消除变量量纲带来的影响。
另一种更常见的做法是,在建模之前将变量标准化,这种情况下,变量的系数即可以直接作为变量重要性的判断指标。
2.随机森林
先简单介绍一下随机森林算法,它是基于决策树的集成算法,以下是构建一个随机森林模型的具体过程:
随机森林算法步骤:
①用有抽样放回的方法(bootstrap)从样本集中选取n个样本作为一个训练集
②用抽样得到的样本集生成一棵决策树。在生成的每一个结点: 随机不重复地选择d个特征 利用这d个特征分别对样本集进行划分,找到最佳的划分特征(可用基尼系数、增益率或者信息增益判别)
③重复步骤1到步骤2共k次,k即为随机森林中决策树的个数。
④用训练得到的随机森林对测试样本进行预测,并用票选法决定预测的结果。
简单示意图:
回到正题,讲述计算随机森林变量重要性的两种方法:
1.Gini指数法
①第i棵树中,节点m的Gini指数是:
其中,K表示m节点中有K个类别,Pmk表示节点m中类别k所占的比例。
②节点m分枝前后的Gini指数变化量为:
其中, 后两项分别表示分枝后两个新节点的Gini指数。
Gini指数变化量还不能直接使用,考虑到节点的样本数量,需要进行加权处理,权重就是节点的样本数量(n)除以总样本数量(N):
③特征X𝑗在节点m的重要性为:
④如果特征X𝑗在决策树i中出现的节点在集合M中,那么X𝑗在第i棵树的重要性为:
⑤假设RF中共有n棵树,那么:
⑥最后,把所有求得的重要性评分做一个归一化处理即可:
Python中,随机森林模型中变量重要性计算,采用的就是这种方法,有现成的函数可以直接调用。
2.精度下降法(Mean Decrease in Accuracy)
①.对每一颗决策树,选择相应的袋外数据(out of bag,OOB)计算袋外数据误差,记为errOOB1
②.随机对袋外数据OOB所有样本的特征X加入噪声干扰(可以随机改变样本在特征X处的值),再次计算袋外数据误差,记为errOOB2
③. 假设森林中有N棵树,则特征X的重要性=∑(errOOB2-errOOB1)/N。这个数值之所以能够说明特征的重要性是因为,如果加入随机噪声后,袋外数据准确率大幅度下降(即errOOB2上升),说明这个特征对于样本的预测结果有很大影响,进而说明重要程度比较高。
PS:所谓袋外数据是指,每次建立决策树时,通过重复抽样得到一个数据用于训练决策树,这时还有大约1/3的数据没有被利用,没有参与决策树的建立。这部分数据可以用于对决策树的性能进行评估,计算模型的预测错误率,称为袋外数据误差。
三、总结
1.几乎任何情况下,都可以通过计算IV值来衡量变量重要性(只要可以转化为类别变量),但是在某些情况下,把所有变量都转化为类别变量并不是一件容易的事,而且转化方法的差异也会影响计算结果。
2.针对特定模型,采用特定的变量重要性算法,在计算效率上显然更高了。但这种方法下得出的结果,是变量在“大环境”下对结果的贡献度,而非单独进行观测(除非事先保证变量的独立性),因此难以排除变量间的相关性影响。
上文中用线性模型和随机森林模型为例,概括了变量重要性的主要计算方法和原理,其它可以计算变量重要性的还有神经网络模型、决策树、贝叶斯网络模型、判别分析模型、SVM以及最近相邻元素(KNN) 模型等等。
PS:一些特征选择/缩减方法,如主成分分析、L1正则化,逐步回归等等,并不能量化变量的重要程度,但能达到选择重要变量的目的。