Py学习  »  机器学习算法

【机器学习】“垃圾”数据如何玩出新高度?

科研猫 • 3 年前 • 277 次点击  



前面的文章中,我们花了很多时间给大家讲解了机器学习的基础概念(掌握机器学习,引领科研潮流),以及机器学习的算法基础(机器学习算法基础,从聚类开始)。很多同学说我们的内容实在丰富,非常实用。小编心里暖暖的,心想那肯定必须的呀,科研猫的技术团队何时让粉丝失望过?


言归正传,还记得上次的文章中我们讲过:算法是机器学习的基础和核心,而且给大家罗列了常用的十几种算法。说到分类模型,有很多种算法,比如KNN、SVM、RF等等。今天我们就来讲讲其中一个非常重要的分类算法-随机森林(Random forest, RF)。


在这里,再跟大家强调一下“分类”和“聚类”的概念,别搞混淆了哦,具体的我就不再展开了。“分类”的概念我们每天都会用到,比如某个物品,属于A类,还是B类;或者某个病人,属于高危组还是低危组;这些都是我们在科研工作中每天遇到的问题,也是极度困扰我们的问题,比如在临床上,正确的分组能够极大地提高诊断的准确率,避免漏诊。所以,近年来,在很多顶级杂志中,机器学习和新型的分类模型收到极大的追捧,同样的数据,用老套的分类方法,诊断效能一般,投稿也是撑死了1-2分,加上机器学习,立马就换个样子,投稿3-5分易如反掌,运气好的还能冲刺10分,这样的例子数不胜数。


在我们的周围,有很多没有条件进行基础实验的科研人员,收集了各种各样的数据,但是无从下手,不妨看看这几年用机器学习做预测或者分类模型的文章有多少,你就会知道这个领域有多火爆。看看下面的发文数量,简直就是指数增长,2019年发表“机器学习预测模型”相关文章2600篇左右,2020年仅第一季度已发表900多篇,远超去年同期。所以,赶紧上手“机器学习”,让你手上的“垃圾”一样闪耀出钻石一样的光芒。





基础概念


好了,下面回归我们今日的主角“随机森林”,首先,什么是随机森林?根据官方定义:随机森林是一种平均多个决策树的方法,在同一训练集的不同部分进行训练,目的是克服单个决策树的过拟合问题。换句话说,随机森林是一种用于分类和回归的集成学习方法,其操作方法是在训练时构建大量的决策树,并且其输出的类别是由个别树输出的类别的众数而定。读完这段话,你是否有许多问号???



由于本人也非数学专业出身,很难解释的很通俗易懂,我来说说我的理解吧:首先,我们要了解什么是决策树,这里有一张简图,可以发现,决策树的构建非常简单,很像我们在高中学过的算法流程图。



这里有一些关键的问题,比如说开始这个Root该如何选择和确定,接下来的叶节点又该如何取舍?聪明的统计学家考虑到这个问题,创造了一种叫Gini的方法,Gini用于衡量每一个决策树的impurity(不纯净度),Gini值越低越好,这是什么意思呢?


我们不用过于在意公式的具体算法,而应该更加关心这个公式想衡量什么东西,总的来说,当一个变量把样本总体一份为二时,我们通过Gini impurity就可以量化变量这样分类是否合理,从而确定是否要继续往下生长。因此决策树首先从根节点开始,逐一尝试所有选项(自变量),并选择一个最佳的选项作为根节点;然后限定根节点,再逐一尝试剩余选项(自变量),并选择一个最佳的选项作为内部节点;以此类推,直到完成全部的节点构建。


对决策树有个大概认识后,我们再讲到随机森林,随机森林,顾名思义=随机+森林,先它使用自助抽样的方法构建新的数据集,然后使用随机抽取特定数量的变量子集的办法来构建决策树,而且上述过程会重复很多次,构建大量的决策树。人多成众,树多成林,因此非常形象的叫随机森林。通过大量决策树举手表决,支持某一结局的树越多,则越有理由去得出相应的结论。


随机森林有哪些天然的优势呢?

  1. 在数据集上表现良好,两个随机性的引入,使得随机森林不容易陷入过拟合(就是在训练集上表现优良,在测试集上就不尽如人意,这种模型应用于实际就不大合理了)。在生成每棵树的时候,每个树选取的特征都仅仅是随机选出的少数特征,一般默认取特征总数m的开方。而一般的决策树则是会选取全部的特征进行建模。因此,不但特征是随机的,也保证了特征随机性

  2. 它能够处理很高维度(feature很多)的数据,并且不用做特征选择,对数据集的适应能力强。(这一点尤其适合处理RNA-seq数据,因为我们受限于课题经费(穷),很多情况下样本只有十来个,然而我们得到的mRNA大约是20000个,倘若使用其他类型的算法,并不能很好的找出哪些mRNA是和表型高度相关的。而随机森林可以较好的解决这样的问题。



实例操练


如何将随机森林应用于自己的课题呢?我想这个问题应该是大家最关心的,任何模型的应用其实无外乎以下三点:

  1. 模型该如何构建(我的数据能进行建模吗?需要做哪些准备?)

  2. 如何评价该模型的优劣(做出模型,总要评估一下效能吧)

  3. 如何进行优化(如何提高精确度和稳定性?)


对于这些问题,我觉得与其干巴巴的讲理论不如直接用实例说话,下面,我来带大家使用R语言去领略随机森林在医学领域的一点点应用,希望对大家的课题能有所启发!


首先载入需要包和所需数据集,本次数据集是来自克利夫兰医学中心的303例样本数据,为了能让大家更加便于理解这个数据,我们将各变量的名称及注释如下:



下面就是代码操作了,在这里再啰嗦一下(虽然你可能觉得有点烦,不过我们必须照顾一下初学者),符合以下几种情形的,请对号入座,自觉补充R语言基础知识:

  • R和RStudio使用不熟练的

  • 不知道何为R包、无法正确安装R包的

  • 不能读懂和修改简单R代码的

以上同学,请先收藏本篇,暂缓本篇内容的学习,然后从我们的R语言系列课程:《R语言从入门到精通》开始补充R语言基础知识,R系列课程共18篇,最起码看完前3个章节再继续下面的内容。打好基础,磨刀不误砍柴工,否则就算你能跑出来下面的代码,不会用到自己的数据上,没有任何意义!




Step1:数据预处理


很多人在处理数据的过程中,极其粗糙,觉得只要读入数据,丢到R包里面一算就结束了,看着跑出来的结果还沾沾自喜,殊不知,早已千错万错。这里,我们的技术大牛结合数据实例,给大家分享数据分析过程中应该避的坑。首先我们要读入数据,然后通过str()函数查看一下数据的类型。这里至关重要!!!很多同学读入数据之后,就一股脑开始后续分析,殊不知你想要的数据已经变了样。熟悉R语言的应该知道,读入数据表后默认为数据框,字符串会默认转换成因子,而因子在很多计算中可能会转变成数值型向量,换句话说,好好的文字,在读入R语言之后,很可能变成一堆数字。这样的数值可以看到我们的数据格式并不符合实际情况,许多分类变量被当成了连续变量。这个问题很重要!很重要!很重要!千万别忽视。那么,应该怎么办,别偷懒,第一步是逐个规定变量的属性。代码如下:


1# read in data
2data"data.csv",header=T,row.names=1)
3str(data)
4
5# 可以看到我们的数据格式并不符合实际情况,
6# 许多分类变量被当成了连续变量,所以首先第一步是规定变量的属性 
7data$cp  8data$fbs  9data$restecg 10data$exang 11data$slope 12data$ca 13data$ca 14data$thal 15data$thal 16data$hd 17str(data)


这样就符合实际情况了,下面就是缺失值的处理。缺失值在R中用NA表示,很多人不在乎NA值,觉得无所谓,其实NA值也是影响我们的计算结果的关键点。不同的处理方法得到的结果完全不同,遇到NA值,可以删除,也可以补全。下面是数据中是缺失值的处理:


1# remove NAs
2data.test=na.omit(data)
3dim(data.test)
4
5# 填补缺失
6# 随机森林中有一个函数`rfImpute()`专门用于补充缺失值,
7# 它是根据相似度进行填补的一种迭代算法
8data.infer 5
)


可以发现,数据中是有缺失值的,这种问题在我们实际收集资料是也经常出现,关于缺失值的处理估计写下去又是洋洋洒洒一大块,我简单概括下:一是删,二是补。删的意思很好理解,剔除可能的影响,但是很有可能我们辛辛苦苦收了好几个月的数据,删来删去,地主家也没有余粮了~~那么第二种方式就是补,怎么补呢,要么根据临床经验补充,要么就根据相似患者的数据补充或者根据最有可能出现的情况进行补充,随机森林中有一个函数rfImpute()专门用于补充缺失值,它是根据相似度进行填补的一种迭代算法,我个人觉得这是一种比较合理的替代方法,它根据所有患者的记录来相似比较补充。接下来我们也用它来补充缺失值。


Step2: 模型构建


关键的内容来了,讲了这么多,数据也处理好了,如何构建随机森林模型呢?其实到这一步反而简单了,通过一个函数即可搞定。


1# 随机森林,一行就搞定 
2model TRUE
,importance=TRUE
3 print(model) 


没错,只要我们把需要进行分类的变量(因变量)和用来构建模型的数值(自变量)告诉randomForest()函数即可,输出的结果是这样的:



Step3: 模型评价


模型是创建好了,那么接下来该如何评价这个模型的优劣呢?随机森林通过自助抽样和随机子集的方法产生大量的随机数据集,从而形成随机森林。由于是有放回的抽样,所以每一个子数据集中绝大部分都会有重复样本,也就是说原始数据集中的一些样本不在子数据集中,这些样本称为“Out-of-bag Dataset(OOB)”(袋外数据),而OOB恰好为我们评价模型的稳定性提供了可能。



1oob.error  2  Trees=rep(1:nrow(model$err.rate), times=3),
3  Type=rep(c("OOB""Healthy""Unhealthy"), 
4           each=nrow(model$err.rate)),
5  Error=c(model$err.rate[,"OOB"],
6          model$err.rate[,"Healthy"],
7          model$err.rate[,"Unhealthy"]))
8
9#画个图
10ggplot(oob.error, aes(x=Trees, y=Error)) + 
11  geom_line(aes(color=Type))+
12  theme_classic()
13#可以看到当树达到300以上时,模型表现的十分稳定。



Step4:模型测试


如果有小伙伴熟悉数据挖掘的话可能会有疑问,这个模型在这个数据上表现良好,那么它是否具有推广价值呢?我能否代入测试数据来看看这一模型在不同的数据上是否具有应用价值?OK,这个问题我来帮你解决!怎么测试呢?很简单,把数据分成两半,一半作为traing set(训练数据集),一半作为test set(测试数据集),即可完成测试。



1#分割数据集 0.5, 即按照1:1的比例去将数据分为训练集和测试集
2inTrain0.5
,list=F)
3test 4train 5
6max=0
7num=0
8fc 9mod_pre10model TRUE,importance=TRUE)
11model_pre"prob")
12fc13mod_pre1])
14df


这里,我们是用predict()函数做的测试。如果你觉得不够直观,怎么办呢?如果是二分类变量,我们还可以绘制个ROC曲线来观察比较,这是最直观的方法,也是很多文章中最后对模型进行比较时所采用的方法。关于ROC的基础知识,我们不再展开,在我们的ROC专栏中有讲解,还记得我们的ROC史上最强分析代码吗?参见:ROC曲线(2):一码到底。下面是我们这次的模型评估ROC曲线:



测试集上的结果AUC达到了0.899,非常不错的结果。在模型构建的过程中,用到来很多观察值,那么到底哪个值更重要呢?换句话说,哪些变量对模型贡献最大呢?通过varlmpPlot()函数就可以实现了。



好了,随机森林的初步应用到这里就结束了,赶紧动手操练起来吧,一定会给各位带来不一样的启发的!




本期干货


- 随机森林代码及数据 -

·

关注“科研猫”公众号,联系客服

胖雨小姐姐

or

折耳猫小姐姐

领取


更多科研新鲜资讯、文献精读和生物信息技能

请关注科研猫公众号

未经许可,严禁转载,版权事宜由上海辰明律师事务所提供法务支持。


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/57326
 
277 次点击