令人讨厌的非平衡数据

有没有遇到过这样的头疼问题,在某个分类问题中发现数据存在严重的偏倚,即0-1分类比例严重失调。如欺诈问题中,欺诈类观测毕竟占总样本中少数;如客户流失问题,流失客户往往也是占少部分;如会员对某波活动的响应问题,同样正真响应的只占很少比例。


如果你的数据存在这种不平衡,分析得出的结论也一定是有偏的,往往分类结果会偏向于较多观测的类。对于这种问题该如何处理呢?起先我的想法很简单,构造1:1的数据,要么将多的那一类砍掉一部分,要么将少的那一类进行Bootstrap简单复制。但这样做是存在问题的,对于第一种方式,砍掉的数据会导致某些隐含信息的丢失;对于第二种方式,简单复制,又会使模型产生过拟合问题。那该怎么办?


在网络中寻找求解办法,发现2002年Chawla就提出了SMOTE算法(合成少数过采样技术),而且该方法目前是处理非平衡数据的常用手段,受到学术界的一致认同。下面就讲讲该算法的思想:


1)采样最邻近算法,计算出每个少数类样本的K个近邻

0?wx_fmt=jpeg
2)从K个近邻中随机挑选N个样本进行随机线性插值

3)构造新的少数类样本

构造公式:

0?wx_fmt=jpeg
4)将新样本与原数据合成,产生新的训练集


为了说明SMOTE算法的思路,我们举个简单例子

如果有一个少数类的样本点为(2,3,10,7),从K个近邻中随机挑选2个点分别为(1,1,5,8)和(2,1,7,6),参数的随机数为0.3,那么构造的2个新样本点为:

0?wx_fmt=jpeg
上面我们介绍了关于SMOTE算法实现数据平衡的理论思想,在R语言中该如何实现这样的理论呢?DMwR包中的SMOTE()函数就可以实现这样的功能,具体函数的语法和参数含义如下:


SMOTE(form, data, perc.over = 200, k = 5, perc.under = 200,

      learner = NULL, ...)

form:为一个公式形式,类似于y~x1+x2+x3

data:为不平衡的数据框

perc.over:定义过采样的抽样次数,即对于少数类样本点,需要为每个点重新构造多少个点。默认值为200,即重新为每个少数类样本点构造200/100=2个点。

k:指定K邻近算法中的参数K值,即选取K个最邻近的点,默认值为5

perc.under:定义欠采样的抽样次数,即从多数类样本中选择perc.under倍于新生成的样本数量,默认为200,即从多数类样本中选择200/100=2倍于新生成样本的数量


下面就使用实例数据来验证一下非平衡数据处理前后的模型结果,数据来源于C50包中的客户流失数据:

```{r}

library(C50)

data(churn)

train = churnTrain

test = churnTest


#查看一下训练集和测试集数据的平衡状态

table(train$churn)

prop.table(table(train$churn))


table(test$churn)

prop.table(table(test$churn))

```

0?wx_fmt=png
训练集和测试集中的流失客户与非流失客户比例在1:6左右,存在明显的偏倚状态。


首先我们不对数据做任何处理,仍然保持原来的非平衡状态,看看C5.0决策树算法在该数据集中的预测能力:

```{r}

#构建C5.0决策树算法

model1 <- C5.0(formula = churn ~ ., data = train)

#在测试集中做预测

predict1 <- predict(object = model1, newdata = test[,-20])

#构造模型评估的混淆矩阵

Freq1 <- table(test[,20], predict1)

Freq1

#计算预测精度

Accuracy1 <- sum(diag(Freq1))/sum(Freq1)

Accuracy1

```

0?wx_fmt=png
虽然模型的准确率近95%,但模型的准确率更偏向于非流失客户而流失客户的预测准确率并不高,仅146/(146+78)=65%。


下面我们再来看看模型预测的ROC曲线:

```{r}

library(pROC)

library(ggplot2)

roc_curve01 <- roc(as.numeric(test$churn), as.numeric(predict1))

print(roc_curve01)

#绘制ROC曲线

x1 <- 1-roc_curve01$specificities

y1 <- roc_curve01$sensitivities


p <- ggplot(data = NULL, mapping = aes(x= x1, y = y1))

p + geom_line(colour = 'red', size = 2) +geom_abline(intercept = 0, slope = 1)+ annotate('text', x = 0.4, y = 0.5, label=paste('AUC=',round(roc_curve01$auc,2)), size = 6) + labs(x = '1-specificities',y = 'sensitivities', title = 'ROC Curve')

```

0?wx_fmt=png
通过计算,曲线下方的面积AUC为0.82

接下来我们对非平衡数据做平衡化处理,即采用SMOTE算法实现数据集的平衡:


```{r}

set.seed(1234)

library(DMwR)

train2 <- SMOTE(form = churn ~ ., data = train, perc.over = 200, k = 5, perc.under = 150)

#查看数据的平衡状态

table(train2$churn)

prop.table(table(train2$churn))

```

0?wx_fmt=png
现在数据集已经平衡了,下面我们就使用这个新的测试数据集建模,看看建模后的预测能力:


```{r}

#构建C5.0决策树算法

model2 <- C5.0(formula = churn ~ ., data = train2)

#在测试集中做预测

predict2 <- predict(object = model2, newdata = test[,-20])

#构造模型评估的混淆矩阵

Freq2 <- table(test[,20], predict2)

Freq2

#计算预测精度

Accuracy2 <- sum(diag(Freq2))/sum(Freq2)

Accuracy2

```

0?wx_fmt=png
从上面的结果可知,虽然总体的预测精度有所下降,但带来的一个好处是,流失样本的预测精度有了大幅提高,即162/(162+62)=72%。同样我们来看一看ROC曲线是否有所改善:


```{r}

library(pROC)

library(ggplot2)

roc_curve02 <- roc(as.numeric(test$churn), as.numeric(predict2))

print(roc_curve02)

#绘制ROC曲线

x2 <- 1-roc_curve02$specificities

y2 <- roc_curve02$sensitivities


p <- ggplot(data = NULL, mapping = aes(x= x2, y = y2))

p + geom_line(colour = 'red', size = 2) +geom_abline(intercept = 0, slope = 1)+ annotate('text', x = 0.4, y = 0.5, label=paste('AUC=',round(roc_curve02$auc,2)), size = 6) + labs(x = '1-specificities',y = 'sensitivities', title = 'ROC Curve')

```

0?wx_fmt=png
结果显示,模型的AUC相比于之前的AUC有所提升,所以我们认为该模型更值得选择,之所以能够选择该模型,是因为对原始数据做了平衡处理。


参考资料:

http://www.itnose.net/detail/6185647.html

http://www.doc88.com/p-7314389829640.html

https://www.jair.org/media/953/live-953-2037-jair.pdf


每天进步一点点2015

学习与分享,取长补短,关注小号!

0?wx_fmt=jpeg

   长按识别二维码à马上关注

长按识别二维码à马上关

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值