分类模型的再考以及随机森林的应用

一、进行分类建模前的准备

在上一篇博客里我们应用了逻辑回归和LDA方法来判别|预测一个对象的分类,其中逻辑回归多应用于只有两种类型(Yes或者No)的分类,LDA可用于2种类型及2种以上类型的分类。但是不论逻辑回归还是LDA,最后在验证数据集上的预测效果都很糟糕,甚至不如随机分配的正确率来的高。那么为什么会这样呢?
我们再来看看购买了年卡(YesPass)和没有购买年卡(NoPass)的消费者在两个预测变量Channel和Promo所构成的空间中的分布情况。

library(ggplot2)
ggplot(pass_fact,aes(Channel,Promo))+
  geom_jitter(aes(color=Pass),alpha=0.5)+geom_point(color="blue",size=4)
#geom_jitter让数据分离看来,其实原来数据应该集中在六个蓝点所在的位置上。

输出:
这里写图片描述

可以看到,除了在(NoBundle|Email)的位置,NoPass占了绝大多数之外,其他位置YesPass和NoPass很好地混合在一起,在这样的情况下,希望通过一个判别模型将Nopass和YesPass很好地区分开来是很不容易的。这就好比,我们很难将蜂蜜从一杯蜂蜜水中分离出来一样,因为蜂蜜和水完美地混合在了一起。为了方便起见,在下文中我会把这种问题称为“蜂蜜水问题”
另外一个影响分类效果的要素是数据的不对称性。如果不同类别的数据在数量上差别很大的话,同样也会影响到模型的预测效果。下面我们先来看一下NoPass和YesPass这两类消费者的数量。

table(pass_fact$Pass)

输出:

  NoPass YesPass 
   1567    1589   

可以看到NoPass和YesPass的数量差不多,这样可以说用来建模的数据是对称的或平衡的。当数据不平衡的时候就要格外注意了。
下面我们将带着上面的思考来进行数据的分类。

二、数据的准备

用于分类的数据来自于mlbench包中的BrestCancer,其中包含了包括肿瘤细胞大小、形状在内的多个变量,以及患者的重量的性状(良性或恶性)。我们将通过几种分类算法来判断患者肿瘤的性状,在此之前,我们可以通过clustr包中clusplot对不同类型的肿瘤在预测变量空间的分布状况进行探查。

library(mlbench)
library(tidyr)
data("BreastCancer")
data.Breastcancer<-drop_na(BreastCancer[,-1])#去掉患者ID
#View(data.Breastcancer)

library(cluster)
clusplot(data.Breastcancer[,-10],data.Breastcancer$Class,shade = T,color = T,labels=4,lines = 2,main = "Distribution of two breast cancer type")

输出:
这里写图片描述

clusplot通过了PCA算法把数据映射到了由两个主成分构成的平面上。底部显示了,两个主成分对原始数据地还原状况,可以看到,主成分1和主成分2还原原数据了74%的方差。所以该图较好地反映了数据在真实预测空间地分布状况。
可以看到,良性肿瘤(benign)和恶性肿瘤(malignant)虽然出现了很大部分的重叠,但是如果仔细查看的话,良性肿瘤(空心圆)和恶性肿瘤(三角形)还是很好地区分开来了,除了两个大圈相交的地方。所以在这个例子中,“蜂蜜水”问题并不严重。
下面,在使用决策树方法之前,做为对比我们将尝试使用朴素贝叶斯(NaiveBayes)分类方法。

三、朴素贝叶斯(NaiveBayes)分类法的应用

在应用朴素贝叶斯方法建立模型之前,依照惯例,我们将把数据分成训练集和验证集。

set.seed(828)
train.prob<-0.65

train<-sample(nrow(data.Breastcancer),nrow(data.Breastcancer)*train.prob,replace = F)

BC_train<-data.Breastcancer[train,]
BC_test<-data.Breastcancer[-train,]

应用naiveBayes函数

library(e1071)
BC_nb<-naiveBayes(Class~.,data=BC_train)

使用朴素贝叶斯模型进行预测

BC_nb_class<-predict(BC_nb,newdata=BC_test)

mean(BC_nb_class==BC_test$Class)
#97.1%

prop.table(table(BC_nb_class,BC_test$Class),1)

输出:

[1] 0.9708333

BC_nb_class     benign  malignant
  benign    1.00000000 0.00000000
  malignant 0.07608696 0.92391304

可以看到模型地误差只有97.1%表现还是非常好的。

四、随机森林

随机森林是决策树的一种演进算法。原理很简单,我们以切蛋糕的为例:比如一个蛋糕里随机混合了三种小点心,分别为巧克力、曲奇饼、坚果,怎样切才能使每一块蛋糕仅能地只含有较少种类的小点心呢(当然又一个前提是,每款蛋糕至少要包含一定数量的点心,不然的话切成每一块蛋糕只含有一个小点心的方法就行了)?这个场景就是分类型决策树(classification tree)的一个应用。最后达到的目的就是使每一块蛋糕(对应决策树的node或这leaf)含有类型尽可能少的点心。在实际的应用中,可以把数据看成这个蛋糕,无非是要把多维度的数据沿着各个维度上的具体的值进行切割,比如按照性别,或者按照收入的高低。
在此基础上,随机森林只选取了部分变量,在分类的场合,只选取选取sqrt{p}(p为变量数),以此减少模型实际预测时产生的误差。特别是当变量之间存在着较强的相关性时(上诉的BreastCancer数据便是如此),然后结合bootstrap方法(也就是bagging),可以得到一个随机森林模型。关于决策树和随机森林低介绍,可以参考《An introdunction to statistical learning》的第八章。以下将是它在r中的应用。

library(randomForest)

set.seed(831)
BC_rf<-randomForest(Class~.,data=BC_train,importance=T)

把BC_rf应用在testdata上:

BC_rf_class<-predict(BC_rf,newdata = BC_test)

mean(BC_rf_class==BC_test$Class)

输出结果:

[1] 0.9666667

和朴素贝叶斯方法的正确率相当。如果我们想要知道变量的相对重要性该怎么办?由于我们在建立BC_rf模型时,设立了importance=T参数,所以BC_rf带有一个显示变量相对重要性的数据表。我么可以将此结果可视化。

BC_rf_im<-as.data.frame(BC_rf$importance)
BC_rf_im$Var<-rownames(BC_rf_im)


library(ggplot2)
library(dplyr)
BC_rf_im%>%
  select(Var,MeanDecreaseGini)%>%
  ggplot(.,aes(MeanDecreaseGini,reorder(Var,MeanDecreaseGini)))+geom_point()+labs(y="Variables")

输出结果:
这里写图片描述
可以看到Cell.size、Cell.shape以及Bare.nucle三个变量的相对重要性最大。

五、小结

结合上一篇的分类模型的预测表现,我们探讨了“蜂蜜水问题”对分类模型的影响。为了快速辨别一个数据表是不是存在着“蜂蜜水问题”,我们通常可以使用clustr包中的clusplot进行判别。如果出现了这样的问题的话,我们应该可以预想到最后的模型,特别是逻辑回归和LDA这一类线性判定模型可能在预测的表现不会太好。首先,我们需要反思在数据变量的选取时是不是应该增加新的变量?因为现在的变量对区分不同类别没有很好的帮助。另外也可以选用一些kmeans、朴素贝叶斯、决策树之类的灵活性更好的模型进行预测,但是这一类模型的一个重要问题是结果不太好解释(相较于逻辑回归)。
最后我们结合了mlbench包中的一个关于乳房肿瘤类型的判断,应用并且比较了朴素贝叶斯和随机森林的预测表现。因为原始数据数据没有“蜂蜜水问题”,所以模型预测的准确率都很高。其中在对随机森林模型的重要性进行分析之后,发现Cell.size、Cell.shape以及Bare.nucle三个变量的相对重要性最大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值