特征筛选【IV和WOE】
1.概述
IV
和WOE
通常是用在对模型的特征筛选中,在模型刚建立时,变量往往很多,IV
和WOE
可以帮助我们衡量什么变量应该进入模型什么变量应该舍弃。- 用
IV
和WOE
值来进行判断,值越大表示该特征的预测能力越强,则该特征应该加入到模型的训练中
2.应用
- 变量筛选。选取比较重要的变量加入模型,预测强度可以作为我们判断变量是否重要的依据。
- 指导变量离散化,在建模过程中,时常需要对连续变量进行离散化处理,如将年龄里进行分段。但是变量不同的离散化结果会对模型产生不同影响,因此,可以根据指标所反映的预测强度,调整变量离散化结果。(对一些取值很多的分类变量,在需要时也可以对其进行再分组,实现降维)
3. 计算方法
3.1WOE
WOE(Weight Of Evidence)
用来衡量特征的预测强度;- 使用
WOE
,首先要对特征进行分箱;- 分箱:将一种特征的组成元素进行分组;
- 分箱之后,对于其中第i组的
WOE
值公式如下:
-
py_i
表示该组中的正例占负例样本的比例,pn_i
表示整体的正例占负例样本的比例 -
例子
- 把变量离散化为了4个分段:<100元,[100,200),[200,500),>=500元。首先,根据WOE计算公式,这四个分段的WOE分别为:
-
结果的正负值分析,根据ln函数的特性,当这个组中响应样本的比例比总体的响应比例小时为负数,相等时为0,大于时为整数
-
把这个变量的所有分组的
WOE
值的绝对值加起来,这个可以在一定程度上表示这个变量的预测能力,但是一般不会这么做,因为对于分组中的样本数量相差悬殊的场景,WOE
值可能不能很好的表示出这个变量的预测能力,一边会用到另一个值:IV值。IV在计算的时候,比WOE
值多考虑了一层该变量下该分组占该变量下所有样本的比例
3.2IV
-
IV值的计算公式在WOE的基础上多乘了一个(
py_i-pn_i
),py_i
表示该组中的正例占负例样本的比例,pn_i
表示整体的正例占负例样本的比例
-
把上面的IV1,IV2,IV3,IV4加起来,就是变量的IV值,然后把所有的变量IV值都算出来,就可以根据IV值的大小来看出变量的预测能力
4.分箱
-
数据分箱(也称为离散分箱或分段)是一种数据预处理技术,用于减少次要观察误差的影响,是一种将多个连续值分组为较少数量的"分箱"的方法,就是将连续型特征进行离散化
-
分箱的作用和意义
- 离散特征的增加和减少都很容易,易于模型的快速迭代,提升计算速度
- 特征离散化后,模型会更稳定
- 比如:对年龄离散化,20-30为一个区间,不会因为一个用户年龄增长了一岁就变成了一个完全不同的人
- 特征离散化后,起到了简化模型的作用,可以适当降低模型过拟合的风险
-
注意:
- 对特征进行分箱后,需要对分箱后的每组(箱)进行woe编码,然后才能放进模型训练
- 分箱的数据不一定必须是数字,可以是任意类型的值,如"狗","猫"等,分箱也用于图像处理,通过将相邻像素组合成单个像素,它可用于减少数据量
4.1 pandas实现数据分箱
-
pd.cut()
import numpy as np import pandas as pd from pandas import Series,DataFrame score_list=np.random.randint(30,100,size=20) # [92 73 73 49 62 35 56 90 81 84 84 89 96 94 54 51 91 43 54 98] #设置分箱:方式一 bins=[0,59,70,80,100] score_cat=pd.cut(score_list,bins)#指定分箱数据的范围 print(pd.value_counts(score_cat)) # Categories (4, interval[int64]): [(0, 59] < (59, 70] < (70, 80] < (80, 100]] # (0, 59] 9 # (80, 100] 4 # (70, 80] 4 # (59, 70] 3 # dtype: int64 #设置分箱:方式2 bins = 3#指定分箱数据的范围的个数 score_cat = pd.cut(score_list, bins,labels=range(3))#labels设置分箱的每一个范围标识 print(score_cat) print(pd.value_counts(score_cat)) # [0, 2, 0, 1, 1, ..., 0, 0, 2, 2, 0] # Length: 20 # Categories (3, int64): [0 < 1 < 2] # 0 9 # 2 7 # 1 4 # dtype: int64
import sklearn.datasets as ds bc=ds.load_breast_cancer() feature=bc.data target=bc.target #查看第一列数据范围,判定是连续数据 feature[:,1].min(),feature[:,1].max()#(9.71, 39.28) #对其进行分箱处理,将其离散化 fea_bins=pd.cut(feature[:,1],bins=5,labels=range(5)) fea_bins.value_counts() #0 113 # 1 299 # 2 129 # 3 25 # 4 3 # dtype: int64 #对分箱后的特征进行woe编码 gi=pd.crosstab(fea_bins,target) gb=pd.Series(data=target).value_counts() bgi=(gi[1]/gi[0])/(gb[1]/gb[0]) # row_0 # 0 7.794118 # 1 1.164157 # 2 0.257330 # 3 0.755793 # 4 0.296919 # dtype: float64 woe=np.log(bgi) # row_0 # 0 2.053369 # 1 0.151997 # 2 -1.357398 # 3 -0.279987 # 4 -1.214297 # dtype: float64 #进行映射操作 dict=woe.to_dict() woe_bins=fea_bins.map(dict) woe_bins.tolist()