特征编码在风控建模中的应用(上篇)—WOE是否可以提升集成算法效果?

序言:

在风控模型开流程中,使用的场景分别有A卡、B卡、C卡等模型,常规使用最多的就是逻辑回归算法。使用逻辑回归算法80%会使用的编码方式就是WOE编码,相信做模型的同学对这种编码方式非常熟悉。

做WOE的编码的好处,无需多言,比如可解释性强,对于极端值还不需做处理,但在除逻辑回归的其它场景中是否也能使用这种编码方式?另外模型场景中还有哪些其它的编码方式?还有WOE是否可以提升集成算法的效果?关于这些问题,本文,番茄风控给各位读者带来模型的编码方式汇总,且在集成算法中运用woe编码可以进一步提升模型的准确性。
本次整体的内容较多,除了公众号上的内容更会在知识星球上为大家提供本次内容所涉及的实操数据与代码,手把手实操带领大家领略整个模型编码方式的内容,本次整体目录如下:

PART 1.特征分类和常见的编码方式

1.1.特征介绍
1.2.常见的编码方法介绍
PART 2.特征编码的应用场景1–LR评分卡
PART 3.特征编码的应用场景2–集成模型
PART 4.实操–连续型特征和高基数特征的WOE编码(数据集+代码内容)

在风控模型开发中,特征编码是非常重要的一个步骤,本文将依托逻辑回归,集成模型的两个算法场景,介绍特征编码的实际应用方法。

Part1.特征分类和常见的编码方式
1.特征介绍
一般特征可分为连续型特征和离散型特征,连续型指在一定区间内可以任意取值,相邻的两个数值可作无限分割,例如身高可以是185,也可以是185.3,而离散型的取值之间不可做分割,只能用整数,字符等来表示类别。大多数的编码方法都是针对离散型特征的,离散型特征又可分为:

  • 按照是否为数值:数值型和字符型
  • 按照是否有顺序关系:有序和无序型
  • 按照类别的数量:高基类和低基类,高基数特征的类别数一般在几百甚至几千个以上,例如城市名,IP地址,低基数特征的类别数就比较少,只有几个或几十个,例如学历,省份。
    每种特征适用的编码方法是不一样的,下面会具体介绍到。

2.常见的编码方法介绍:
1)独热编码:主要针对无序低基数类的离散特征,例如性别[男,女],通过独热编码变成是否男,是否女的0,1特征,转换后的特征又称为哑变量。独热编码解决了算法不能处理属性数据的问题,也起到了扩充特征的作用,但缺点是不适合处理高基数特征,基数过大会带来过很多列的稀疏特征,消耗内存和训练时间。
2)标签编码:适用于有序字符型的离散特征,例如学历,从高中到博士有顺序关系,标签编码直接将其类别映射成数字1,2,3…,实现形式简单且对于低基数特征也很有效,但不建议用在高基数的特征上。
3)woe编码:woe代表了特征对于Y标签的预测能力,通常被描述为区分好客户和坏客户的衡量标准,是风控建模中应用最广泛的编码方法,不管是连续型还是离散型,类别数多还是少,woe编码都能适用,本文也会着重讲它的应用方法。
4)平均数编码:对于高基数类特征,平均数编码是一种高效的编码方法,近几年也在各类竞赛中被应用,在后面集成模型的场景中会具体介绍到。
5)模型编码:目前的集成算法中,只有lightgbm和catboost支持处理类别型的特征,lightgbm采用的是GS编码,将类别特征转为累积值 (一阶偏导数之和/二阶偏导数之和)再进行直方图特征排序,而catboost使用Ordered TS编码,既利用了TS省空间和速度的优势,也使用Ordered的方式缓解预测偏移问题,需要注意的是,在算法训练前,需要将字符型的特征映射成数值。

Part2.特征编码的应用场景1–LR评分卡
1.woe的计算过程
WOE = ln (第i个分箱的坏人数 / 总坏人数) - ln (第i个分箱的好人数 / 总好人数)
这个公式可以理解为每个箱体坏人分布相比于好人分布的差异性
将这个公式变换一下:
WOE = ln (第i个分箱的坏人数 / 第i个分箱的好人数) - ln (总坏人数 / 总好人数)
此时可以理解为每个箱体的好坏比(bin_odds)跟总体的好坏比(all_odds)的差异性,woe可表示箱体对于Y标签的预测能力,如果woe为正且值越大,则箱体的坏用户概率越高,woe为负值越大则箱体的好用户概率越高,所以说woe有很好的业务解释性。在woe的计算基础上,还能计算出IV:
IV=sum([(第i个分箱的坏人数 / 总坏人数) - (第i个分箱的好人数 / 总好人数)]*woe),IV体现了整个特征对于Y标签的预测能力。
以年龄这个特征为例,展示下woe的计算过程:
第一步:对年龄进行分箱,计算每个箱体的坏用户数和好用户数
在这里插入图片描述

第二步:计算各个箱体的好坏比
在这里插入图片描述

第三步:通过好坏比计算每个箱体的woe和每个箱的IV,最后将每个箱的IV加总就是这个特征的IV
在这里插入图片描述

2.LR中做woe编码的好处
1)woe编码要做对特征分箱离散化,而特征离散化之后,起到了简化模型的作用,使模型变得更稳定,降低了模型过拟合的风险,并且离散化之后的特征对异常数据有很强的鲁棒性。
2)woe可代表分箱跟总体的好坏比差异,有很好的解释性,另外在风控建模中,我们习惯于用线性判断特征的作用,例如当特征X越大,Y越小,但经常X与Y存在着非线形关系,此时woe编码就能处理这个问题。
3)woe能处理缺失值,由于LR不能直接处理缺失,woe可以把缺失单独分为一箱,提高了数据的利用率。
4)由于编码后特征的取值变少,在训练模型时能更快的收敛,提高了训练速度。
5)woe化之后可以计算每个特征的IV值,用来筛选特征。

3.woe在分箱时需要注意的地方
1)分箱时样本量要充足,保证其统计意义。
2)要朝着IV最大化的目标进行分箱,分箱方法有最优分箱,卡方分箱,决策树分箱,等频和等距不太适用。
3)分箱的个数不要太多也不要太少,一般控制在4-8个,且每箱的样本不能太少,至少占总量的5%。
4)相邻的箱体如果woe相同,或者某个箱体只有坏用户或好用户,则需要做合并拆分的处理。
5)箱体之间woe变化要符合业务解释,例如逾期次数越多,坏的概率越大,那分箱的woe也要保持这个逻辑,一般最后的分箱逻辑都要手动调整过。
6)需要验证跨时间上分箱的合理性,如果在训练集上woe是单调的,但在OOT上不单调,说明分箱不合理,需要做调整。

4.woe一定要单调吗?
woe不一定要单调,只要在业务上解释的通就行。举个例子,年龄这个特征,年轻人和老年人的还款能力会比中年人的要低,风险也因此更高,不是呈单调的关系。另外有些我们认为应该单调的特征实际表现却不单调,例如多头特征,一般认为是多头越多越坏,但结合目前的信贷环境,多头次数多可能是因为用户资质好才能借到更多的机构,所以实际的woe表现也能带给我们新的思考,打破之前的固有思维。

5.woe是否存在过拟合的问题
会容易造成过拟合,但不是woe编码的问题,而是分箱及用到了Y标签导致。如果我们用等频/等距这种无监督分箱,过拟合的风险会大大降低,但等距受分布影响,等频对离散值不友好,并且前文提到要朝着IV最大化的目标,所以会用卡方,决策树这种引入Y标签的算法来指导分箱。woe编码+LR其实类似集成学习的原理,集成学习就是把第一层模型的结果做为第二层模型的输入,两层模型都是以Y标签为目标的,LR中的第一层模型就是woe分箱编码,所以也跟集成算法一样容易过拟合。实际开发LR时,我们不会直接用卡方/决策树的分箱结果,而会手动对分箱做调整,一方面为了解释性,另一方面就是约束分箱的条件来降低过拟合风险。

Part3.特征编码的应用场景2–集成模型
1.集成模型中应用独热编码的注意点
前文提到,独热编码(one-hot)的最大缺点在于,对于类别数很多的特征,直接onehot会生成高维的稀疏特征,而集成模型面对高维稀疏特征,划分次数容易增多,树的层级容易加深,这样会导致过拟合,所以独热编码在集成模型里适用于类别数少的特征,一般类别数要在5以下。另外还会面临两种情况:
1)测试集出现训练集中没有的新类别,那新类别的onehot特征是没有在入模字段里的,可以忽略掉
2)训练集中的类别没有在测试集中出现,那这个类别的onehot特征在测试集里的值都设为0处理

2.lightgbm自身处理类别型特征的逻辑
为了解决上述独热编码的问题,lgb采用GS编码,即Many vs Many的切分方式,简单来说,是通过对每个类别取值进行数值编码,根据编码的数值寻找较优切分点,实现了类别特征集合的较优切分,具体的实现逻辑为:
1)当特征的类别数<=4(参数max_cat_to_onehot),会直接onehot编码,逐个扫描每一个bin容器,找出最佳分裂点。
2)当特征的类别数>4,会统计各个类别对应样本的一阶和二阶梯度之和,以一阶梯度之和 / (二阶梯度之和 + 正则化系数)作为该特征取值的编码。将类别转化为数值编码后,从大到小排序,遍历直方图寻找最优的切分点,例如对于类别为A-E的特征,取值为A,C的梯度较大(分类难度高),则最优的分割点为[A,C] vs [B,D,E]。

在用lgb自带的编码时,如果特征为字符型,需要先将字符映射为非负整数值(标签编码)再带到模型里训练,将类别型特征list放在fit参数中的categorical_feature即可。
在这里插入图片描述

3.集成模型是否有必要对连续型特征编码
是没有必要的,不同于LR,集成模型底层算法是决策树,决策树本身就是寻找最优分割点来划分样本,相当于做了分箱操作,如果提前对连续型特征做了分箱,那可能就找不到最优分割点了,且特征取值变少集成模型的梯度提升优势会减弱,导致模型效果的下降。不过我们可以换一种思路,通过连续特征离散化构建组合交叉的新特征,引入更多的非线性,说不定能提升模型的效果。

4.高基数特征怎么处理比较好
高基数特征的例子:IP地址,城市名,家庭住址,设备id等,这类特征的类别数至少是成百上千的,用独热和标签编码都不太行,这里提供三种解决方法:
1)直接用lightgbm,catboost自带的编码方法,优点是操作简单,缺点是特征基数太多容易过拟合,且会消耗运算时间,最好是先做一下经验的合并减少类别数,模型效果可能会更好。
2)用woe编码来做合并,减少类别数。先限制好合并后的类别数和类别的最小占比,然后计算每个类别的badrate并排序,根据badrate组内差异小,组间差异大的原则进行类别之间的合并,直到满足限定条件停止合并,然后将合并后的新类别映射为woe值,这样做相当于对高基数特征做了分箱处理,具体的代码实现过程在实操part中会讲到。我们实验比较过woe编码和模型编码对于高基数特征的处理效果,woe编码会更好一点。
3)用平均数编码,平均数编码跟woe一样也是有监督的编码方法,它用到了先验和后验概率的思想,假设某个高基数特征A有N个类别,具体某个类别用n表示:
先验概率:P(Y=1) = Y为1的数量 / 样本量
后验概率:特征属于某一类别时的概率P(y=1|A=n) = Y为1且A为n的数量 / A为n的数量
平均编码的思想就是将特征A中每个类别n,都表示为估算的y的概率p(估算的用小写P表示),将n映射为p完成编码。估算的p应当是先验概率与后验概率的一个凸组合,由此我们引入先验概率的权重t来计算p。
p(A=n) = t*P(Y=1) + (1-t)*P(y=1|A=n)
权重t有以下的特性:

  • 如果测试集中出现了新的类别(未在训练集中出现),那么t=1。
  • 类别在训练集内出现的次数越多,后验概率的可信度越高,其权重t也越大
    平均数编码还用了交叉验证的方法来降低过拟合,目前被认为是处理高基数的一种有效手段,具体的代码实现大家可以在网上找找资料,这里不做赘述。
    最后做一下小结:
    1/2/3/4/5…
    (可以优先移步知识星球,参见详细内容)
    另外在第四部分,我们还会跟大家带来关于本次的实操内容(参见数据集与代码),一步步进行内容实操。主要的内容包括:
    1.决策树计算woe的编码
    2.高基数计算woe编码

3.模型中的woe编码的提升效果对比

部分内容参考如下:

Part4.实操–连续型特征和高基数特征的WOE编码

导入数据(woe_data.csv),样本量为10000,包含id字段,y_label(Y标签),score(风险评分,连续型特征),city(用户定位城市,高基数类别特征),和其他匿名特征,对score我们采用基于决策树分箱的woe编码,对city通过基于合并的方法进行woe编码。
一.决策树分箱的woe编码
1.先定义生成决策树分箱逻辑…
2.定义分箱计算woe的函数…
3.调用函数输出…
(详见知识星球内容)

二.高基数特征的woe编码
1.定义合并类别的函数…
2.定义合并类别后计算woe的函数…
3… (详见知识星球内容)
在这里插入图片描述

三.woe编码和模型编码在集成模型中的效果对比
1/2/3…,实操部分详见知识星球内容
…剩下第第四部分,因篇幅关系,详情可以移步知识星球参考完整详版内容~
在这里插入图片描述

另外,关于近期番茄风控关于模型相关的实操内容,更可以同步至知识星球后台,查看完整版本数据集+代码内容,欢迎星球同学移步到知识星球查收完整内容:
在这里插入图片描述


~原创文章

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在决策树算法,使用woe转换可以将离散数据转换为连续数据,使得决策树算法可以更好地处理离散数据。以下是使用Python实现woe转换的示例代码: ```python import pandas as pd import numpy as np # 定义woe转换函数 def woe_transform(df, var, target): total = df[target].count() bad = df[target].sum() good = total - bad group = df[[var, target]].groupby(var).agg({target: ['count', 'sum']}) group.columns = ['total', 'bad'] group.reset_index(inplace=True) group['good'] = group['total'] - group['bad'] group['bad_prop'] = group['bad'] / bad group['good_prop'] = group['good'] / good group['woe'] = np.log(group['bad_prop'] / group['good_prop']) woe_dict = dict(zip(group[var], group['woe'])) df[var + '_woe'] = df[var].map(woe_dict) return df # 加载数据集 df = pd.read_csv('data.csv') # 进行woe转换 df = woe_transform(df, 'var1', 'target') df = woe_transform(df, 'var2', 'target') df = woe_transform(df, 'var3', 'target') # 输出结果 print(df.head()) ``` 在上述代码,我们通过定义一个函数 `woe_transform` 来实现woe转换。该函数首先计算出样本好、坏的数量,然后对每个离散变量进行分组,计算每组好、坏的数量以及其所占比例,最后计算woe值。我们将woe值保存在字典,并用 `map` 函数对每个离散变量进行woe转换。最后,我们通过调用 `woe_transform` 函数来实现woe转换,并将转换后的数据集保存在 `df` 并进行输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值