机器学习(八):样本分布不均衡问题的处理

这是一篇机器学习的介绍,本文不会涉及公式推导,主要是一些算法思想的随笔记录。
适用人群:机器学习初学者,转AI的开发人员。
编程语言:Python

自己在项目中拿到数据,大部分情况下都是自己切分训练集、测试集,对于训练集,经常会遇到正负样本比例很不均衡的情况,即偏斜类Skewed Class)问题,有些时候往往还很严重,比如数据量上负样本:正样本>=100,这是比较严重的偏斜类问题,下面针对这种问题,探讨一下:

解决方式

解决样本分布不平衡问题

对于偏斜类问题,主要有三种方式解决:

  1. 过采样/重采样(over-sampling):通过增加分类中少数类样本的数量来实现样本均衡,比较好的方法有SMOTE算法、ADASYN(自适应综合过采样)。缺点:这种方式可能导致过拟合。
  2. 欠采样(under-sampling):通过减少分类中多数类样本的数量来实现样本均衡。缺点:可能丢失多数类的重要信息。
  3. 调整权重:对于分类中不同样本数量的类别分别赋予不同的权重,一般是小样本量类别权重高,大样本量类别权重低。

除了上面三种常见的方式外,还可以转化问题思考角度:例如我们可以把那些小类的样本作为异常点(outliers),因此该问题便转化为异常点检测(anomaly detection)与变化趋势检测问题(change detection)。异常点检测即是对那些罕见事件进行识别。如:银行信用卡诈骗识别,几十万中样本中可能有几百个诈骗用户。这些事件相对于正常情况是很少见的。变化趋势检测类似于异常点检测,不同在于其通过检测不寻常的变化趋势来识别。如通过观察用户模式或银行交易来检测用户行为的不寻常改变。

分类中常见的类别不平衡问题解决方法

衡量指标

对于偏斜类问题,不再用精度accuracy作为模型好坏的衡量指标,因为数据量多的那个分类已经严重影响了整个accuracy,具体要看各个分类的召回率recall(一般我们关注正样本,即1的recall值),更推荐使用roc曲线的auc值(在sklearn中用roc_auc表示)作为衡量指标。

上层领导可能只知道精度,即准确率,即accuracy,并不知道recall、auc等,所以精度是领导关注的问题。

关于衡量指标的问题,以后会单独写一篇来介绍。

实际背景

经历的两个项目,都有严重的偏斜类问题。

第一个项目是正负样本数据量都足够(总量120w左右),且正样本:负样本=96:4,由于有足够的正样本,这不是什么棘手的问题,采用欠采样的方式就可以解决,按照原数据量的分布96:4共取了25w数据作为训练集(按原始数据量的分布是为了尽量符合线上场景,这样得出的accuracy更接近实际情况,取了数据量25w是由学习曲线得出,学习曲线后续篇章会单独介绍)左右的正样本和1,并且模型会有较好的表现。

第二个项目是正样本过少,只有1000左右,而负样本有100多万,这种正样本过少,是比较棘手的问题,对于这种问题,先尽量多采集些正样本,但是注意不能用太旧的数据(由于是投资问题,涉及到产品的更替等受时间影响),采集近半年或三个月(推荐)的数据,但是即便如此,正样本依旧很少,那么上述三种方式均可采用。下面先说一下训练集正负样本划分比例带来的影响。

训练集正负样本划分比例影响

对于正样本过少的偏斜类问题,我们每次采取不同量的负样本与全量的正样本,带来的效果如下(采用的xgboost算法,同样,也试用了svm,但是即便在数据量很少的情况下,xgboost的得分更高,当然,不排除过拟合的情况):

  • 数据量:负2w/正1k recall(1):30% accuracy:98%
  • 数据量:负1w/正1k recall(1):37% accuracy:96%
  • 数据量:负5k/正1k recall(1):48% accuracy:93.5%
  • 数据量:负1k/正1k recall(1):62% accuracy:91%
  • 数据量:负500/正1k recall(1):80% accuracy:89%

如上,负样本量越少,整体精度accuracy越少,但是正样本的recall越高。实际上,从accuracy和recall的计算公式来看,accuracy由量多的决定,虽然不断降低负样本量,正样本的recall会越高,但是整体数据量越少,对于整体模型的置信度(可靠性)就越少,毕竟,人们更愿意相信大数据,模型也会从大数据学到更多信息。

所以,需要找到合数的训练量,这一点可以从经验和学习曲线得到。

三种方式的解决

针对上面提到的第二个项目,尝试着用三种方式处理,并实际测试:

对正样本过采样

分两种思路:
a.将正样本复制累加
经过验证,这种方式是有效的,通过复杂少数样本,提高了少数样本的recall,进入提高了auc
b.SMOTE算法ADASYN(自适应综合过采样)
这里以SMOTE算法为例,SMOTE算法在sklearn中没有集成,需要单独下载lmblearn包,使用如下:

from imblearn.over_sampling import SMOTE
sm = SMOTE(random_state=42)  #随机因子,每次随机生成不要和上次一样
X_res,y_res = sm.fit_sample(X_train,y_train)

如上述代码,会将正样本生成新的值,使得num(正样本):num(负样本)=1:1

对负样本欠采样

这种方式会减少很多负样本的信息,为了保留这种信息,将负样本按1k或500切分10份,每份分别与全量正样本进行进行训练得到分类器,然后集成学习assemble的方式进行组合成一个分类器

调整权重

在训练的时候调节权重:
a.对于xgboost,因为xgboost不属于sklearn,需调节scale_pos_weight参数值,实测结果——改善不大,需要自己不断尝试权重值;
b.针对sklearn中的分类方法,如svm,调节class_weight参数

 from sklearn.svm import SVC
 model_svm=SVC(class_weight='balanced') #算法权衡权重
 model_svm.fit(x,y)

实测——将class_weight设置为‘balanced’,效果改善不明显

 from sklearn.svm import SVC
 model_svm=SVC(class_weight={0:1,1:10})  #自己设定正负样本权重
 model_svm.fit(x,y)

实测——将class_weight指定权重,会比设置为‘balanced’效果改善,但具体权重的值设定为什么数值,需要测试,可以结合网格搜索来找最优权重

XGBoost、LightGBM的详细对比介绍

总结

对于正样本量足够、负样本不足的偏斜类问题,由于有足够的正样本,采用欠采样的方式就可以解决;

对于正样本量严重不足、负样本过多的偏斜类问题,由于严重缺少正样本,可以采用上述的三种方式解决,如果采用调整权重的方式,权重的值需要不断尝试,若采用过采样方式,可以通过单纯的复制少数样本数据,也可以通过SMOTE算法生成少数样本,大家都可以尝试。

  • 6
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值