处理不平衡分类问题R实践指导

浏览: 3227

什么是不平衡问题

    不平衡数据一直是业务场景比较常见的问题之一,癌症数据、欺诈数据、不合格产品数据等都是不平衡数据问题的典型应用。对于一个分类不平衡问题属于有监督机器学习问题,主要指因变量具有不平衡的构成比例问题,或者说在不同分类上,数据具有不相等的数据分布。

机器学习算法需要处理不平衡数据的原因

  1. 由于因变量非同分布,ML需要调整准确性

  2. 由于多数类的存在,导致现存的分类偏向多数类;

  3. ML算法以准确性为驱动(如最小化总误差),这将导致少数类对误差的贡献率小;

  4. ML算法假设不同分类数据的分类错误的代价相同。

处理不平衡数据的方法

  • 下采样;即减少多数类观测值使数据达到平衡。适用于数据集巨大,减少训练样本可提高运算时间和空间问题。下采样方法具体又可分为随机下采样和基于先验信息的下采样(EasyEnsemble & BalanceCascade)。下采样主要缺点是会使训练样本损失多数类的重要信息。

  • 过采样;即重复少数观测值使数据达到平衡。过采样具体方法同下采样。该方法优点是没有信息损失,缺点是易导致过拟合,且一致性(外推性)不足,受异常值影响大。

  • 人工数据合成;属于过采样的一种,通过生成手动数据使少数类达到平衡。使用最广泛方法是synthetic minority oversampling technique(SMOTE),人工数据生成基于少数类样本特征空间(而非数据空间)的相似性,运用booststrapping和k-nearest,在一些位置相近的少数类样本中插入新样本达到平衡样本目的。新的少数样本Pj=x(原始少数样本)+rand(0,1) *(yj-x),yj为第j个x的最近邻样本。可以用DMwR包或ROSE包实现。

  • 代价敏感学习(Cost Sensitive Learning(CSL))一般的学习算法通过最小化分类损失使分类错误率最小化,而代价敏感学习则以最小化分类代价为目标,需构造代价敏感损失。

衡量模型准确性指标

  • Accuracy: (TP + TN)/(TP+TN+FP+FN)

  • Error Rate = 1 - Accuracy = (FP+FN)/(TP+TN+FP+FN)

  • Precision = TP / (TP + FP)

  • Recall = TP / (TP + FN)

  • F measure = ((1 + β)² × Recall × Precision) / ( β² × Recall + Precision ),β 为衡量recall和precision重要性参数,一般为1.

  • ROC曲线,曲线下面积越大,准确度越高。

不平衡数据ROSE包实现

library(ROSE)
data(hacide)
table(hacide.train$cls)
##   0   1 
## 980  20
prop.table(table(hacide.train$cls))
##    0    1 
## 0.98 0.02
    数据为不平衡数据集,仅仅有2%的因变量cls为阳性,98%为阴性。对于这种严重不平衡数据,我们先用决策树看看这种不平衡对模型准确性的影响。
library(rpart)
tree <- rpart(cls ~ .,data = hacide.train)
pred.tree <- predict(tree,newdata = hacide.test)
    ROSE包中accurary.meas()函数可以计算precision、recall、F值等模型准确性指标。
accuracy.meas(hacide.test$cls,pred.tree[,2])
## Call: 
## accuracy.meas(response = hacide.test$cls, predicted = pred.tree[,2])
## Examples are labelled as positive when predicted is greater than 0.5
## precision: 1.000
## recall: 0.200
## F: 0.167
    结果可以看出以0.5为截断点,模型精确度为100%,即没有假阳性;非常低的recall=0.2表明模型具有非常高的假阴性值;F=0.167也说明模型预测准确性很低。
roc.curve(hacide.test$cls,pred.tree[,2],plotit = TRUE)

                                            

## Area under the curve (AUC): 0.600
    最终ROC曲线下面积AUC=0.6也说明模型在截断点为0.5的条件下具有较差的得分。
让我们运用采样技术对不平衡数据进行处理,以提高模型准确性。

不平衡数据处理方法

data_balanced_over <- ovun.sample(cls ~ ., data = hacide.train,method = "over",N = 1960)$data
table(data_balanced_over$cls)
##   0   1 
## 980 980
    运行“过采样”技术,通过重抽样增加较少分组(阳性组)的数量,使数据达到平衡。同样的代码,可以实现“下采样”和同时过采样和下采样。运用ROSE()函数实现SMOTE方法。
data_balanced_under <- ovun.sample(cls ~ .,data = hacide.train,method = "under",N = 40,seed = 1)$data
table(data_balanced_under$cls)
##  0  1 
## 20 20
data_balanced_both <- ovun.sample(cls ~ ., data = hacide.train,method = "both", p = 0.5,N = 1000,seed = 1)$data
table(data_balanced_both$cls)
##   0   1 
## 520 480
data.rose <- ROSE(cls ~.,data = hacide.train,seed = 1)$data
table(data.rose$cls)
##   0   1 
## 520 480

对不同抽样技术进行比较

    分别对4种不同抽样数据集拟合决策树函数,通过绘制ROC曲线比较抽样技术处理不平衡数据方法的好坏。
#build decision tree models
tree.rose <- rpart(cls ~ ., data = data.rose)
tree.over <- rpart(cls ~ ., data = data_balanced_over)
tree.under <- rpart(cls ~ ., data = data_balanced_under)
tree.both <- rpart(cls ~ ., data = data_balanced_both)
#make predictions on unseen data
pred.tree.rose <- predict(tree.rose, newdata = hacide.test)
pred.tree.over <- predict(tree.over, newdata = hacide.test)
pred.tree.under <- predict(tree.under, newdata = hacide.test)
pred.tree.both <- predict(tree.both, newdata = hacide.test)
#AUC ROSE
roc.curve(hacide.test$cls, pred.tree.rose[,2])
## Area under the curve (AUC): 0.989
#AUC Oversampling
roc.curve(hacide.test$cls, pred.tree.over[,2],add.roc = TRUE,col = "red")
## Area under the curve (AUC): 0.798
#AUC Undersampling
roc.curve(hacide.test$cls, pred.tree.under[,2],add.roc = TRUE,col = "blue")
## Area under the curve (AUC): 0.867
#AUC Both
roc.curve(hacide.test$cls, pred.tree.both[,2],add.roc = TRUE,type = "o")

                                  

## Area under the curve (AUC): 0.798
    由模型比较可知,ROSE()函数运用SMOTE方法(基于随机森林和boosting)得到的“平衡数据”,模型准确性最高(AUC= 0.989)。ROSE()函数也可以指定检验模型准确性的方法,如holdout和bagging。extr.pred参数用于提取属于阳性类的概率。
ROSE.holdout <- ROSE.eval(cls ~.,data = hacide.train,learner = rpart,method.assess = "holdout",extr.pred = function(obj) obj[,2],seed = 1)
ROSE.holdout
## Call: 
## ROSE.eval(formula = cls ~ ., data = hacide.train, learner = rpart,
##     extr.pred = function(obj) obj[, 2], method.assess = "holdout",
##     seed = 1)
## Holdout estimate of auc: 0.985
    但是在截断点为0.5条件下,模型F值仍然较低。我们尝试调整不同截断点,使模型准确性最好。由结果可以看出,截断点设置在0.868时,模型准确率最高(precision: 1.000,recall: 0.600,F: 0.375)。
c <- roc.curve(hacide.test$cls, pred.tree.rose[,2])

                                

accuracy <- function(x){
       accuracy.meas(hacide.test$cls, pred.tree.rose[,2],threshold = x)}a <- list()for(i in c$thresholds[2:5])  {
       a=accuracy(i)
       print(a)}
## Call: 
## accuracy.meas(response = hacide.test$cls, predicted = pred.tree.rose[,
##     2], threshold = x)
## Examples are labelled as positive when predicted is greater than 0.8687
## precision: 1.000
## recall: 0.600
## F: 0.375

参考资料

  • MANISH SARASWAT,Analytics Vidhya,Practical Guide to deal with Imbalanced Classification Problems in R

  • SMOT算法在不平衡数据中的应用,孙涛,首都医科大学学术论文征文集

  • 代价敏感性学习方法研究,刘胥影,南京大学博士学位论文 -砍柴问樵夫,数据快速处理—data.table包简单介绍 -SCAN:mlr: Machine Learning in R -Bernd Bischl,et al.mlr - Machine Learning in R,JMLR,17(170):1−5, 2016.

推荐 0
本文由 余文华 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册