百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

数盟译文--如何使用R语言的Boruta包进行特征选择

ztj100 2025-02-10 15:16 11 浏览 0 评论

本文为数盟原创译文,转载时请务必注明出处为“数盟社区”,并将原文链接置于文首。

作者 Debrati

引言

变量选择是模型构建的一个重要方面,每个分析人员都必须学习。毕竟,它有助于排除相关变量、偏见和不必要噪音的限制来建立预测模型。

许多分析新手认为,保持所有(或更多)的变量就能产生最佳的模型,因为你不会丢失任何信息。可悲的是,他们错了!

从模型中删除一个变量,增加了模型的精度,这种事情你遇到过多少次?

至少,我已经碰到过很多次。这样的变量往往被发现是相关的,而且会妨碍实现更高的模型精度。今天,我们就来学习如何在R中摆脱这样的变量的方式之一。我必须强调的是,R有一个令人难以置信的公式库。在所有的软件包中,我们进行变量选择的软件包就是Boruta包。

在这篇文章中,我们将重点放在理解相关理论和Boruta包的使用上。我将用一个循序渐进的方法来帮助你更好地理解它。

另外,我还进行了Boruta与其他传统特征选择算法的比较。通过这个比较,你对特征的理解能够达到一个更有意义的新高度,它能为建立一个强大的预测模型奠定基础。“特征”、“变量”和“属性”这些术语会被多次使用,不要混淆哟!


什么是boruta算法?为什么它会有这么奇怪的名字?

Boruta是一种特征选择算法。精确地说,它是随机森林周围的一种包装算法。这个包的名字来源是斯拉夫神话中一个居住在松林的恶魔。

我们知道,特征选择是预测模型中很关键的一步。当构建一个数据集包含多个变量的模型时,这个步骤尤为重要。

当你有兴趣了解变量相关性的价值,而不是只局限于建立一个具有良好的预测精度黑盒的预测模型时候,用boruta算法来处理这些数据集无疑是最佳选择。

它是如何工作的?

下面是boruta算法运行的步骤:

1.首先,它通过创建混合副本的所有特征(即阴影特征)为给定的数据集增加了随机性。

2.然后,它训练一个随机森林分类的扩展数据集,并采用一个特征重要性措施(默认设定为平均减少精度),以评估的每个特征的重要性,越高则意味着越重要。

3.在每次迭代中,它检查一个真实特征是否比最好的阴影特征具有更高的重要性(即该特征是否比最大的阴影特征得分更高)并且不断删除它视为非常不重要的特征。

4.最后,当所有特征得到确认或拒绝,或算法达到随机森林运行的一个规定的限制时,算法停止。

是什么使它与传统的特征选择算法不同?

Boruta遵循所有相关的特征选择方法,它可以捕获结果变量有关的所有的特征。相比之下,大多数传统的特征选择算法都遵循一个最小的优化方法,它们依赖于特征的一个小的子集,会在选择分类上产生最小错误。

在对数据集进行随机森林模型的拟合时,你可以递归地处理每个迭代过程中表现不佳的特征。该方法最大限度地减少了随机森林模型的误差,这将最终形成一个最小化最优特征子集。这通过选择一个输入数据集的过度精简版本发生,反过来,会丢失一些相关的特征。

另一方面,Boruta找到所有的特征,无论其与决策变量的相关性强弱与否。这使得它非常适合被应用于生物医学领域,一部分人会感兴趣了解哪些人类的基因(特征)与某种程度上的特定的医疗条件(目标变量)相关。

R中Boruta的应用(实践)

到此,我们已经了解了Boruta包的理论知识。但这是不够的。真正的挑战现在才开始。让我们学习在R中运用这个包。

第一件事,让我们安装和调用这个包。

> install.packages("Boruta")

> library(Boruta)

现在,我们来加载数据集。本教程中我的数据集选自Practice Problem Loan Prediction

让我们来看看数据。

> setwd("../Data/Loan_Prediction")

> traindata <- read.csv("train.csv", header = T, stringsAsFactors = F)

gsub() 功能被用来将一种表达式用另一种方式代替。在这里我用underscore(_) 替代了blank(“”).

> str(traindata)

> names(traindata) <- gsub("_", "", names(traindata))

让我们来检查一下这个数据集是否有缺失值。

> summary(traindata)

我们发现,许多变量有缺失值。处理缺失值的优先级对实施boruta包是很重要的。此外,该数据集还具有空白值。让我们来清理这个数据集。

现在我们将用NA代替所有的空白。这将有助于我一次性处理所有的NA。

> traindata[traindata == ""] <- NA

在这里,我将用处理缺失值的最简单方法,即成列删除。更先进的缺失值插补的方法和包可以在这里找到。

> traindata <- traindata[complete.cases(traindata),]

让我们将分类变量转换为因子数据类型。

> convert <- c(2:6, 11:13)

> traindata[,convert] <- data.frame(apply(traindata[convert], 2, as.factor))

现在要实施和检查Boruta包的性能。Boruta语法类似于回归(LM)方法。

> set.seed(123)

> boruta.train <- Boruta(Loan_Status~.-Loan_ID, data = traindata, doTrace = 2)

> print(boruta.train)

Boruta performed 99 iterations in 18.80749 secs.

5 attributes confirmed important: ApplicantIncome, CoapplicantIncome,

CreditHistory, LoanAmount, LoanAmountTerm.

4 attributes confirmed unimportant: Dependents, Education, Gender, SelfEmployed.

2 tentative attributes left: Married, PropertyArea.

Boruta对变量数据集中的意义给出了明确的命令。在这种情况下,11种属性中的4个被拒绝,5个被确认,2个属性被指定为暂定。暂定属性的重要性非常接近最好的阴影属性,以至于Boruta无法对随机森林运行的默认数量作出有强烈信心的判定。

现在,我们用图表展示Boruta变量的重要性。

默认情况下,由于缺乏空间,Boruta绘图功能添加属性值到横的X轴会导致所有的属性值都无法显示。在这里我把属性添加到直立的X轴。

> plot(boruta.train, xlab = "", xaxt = "n")

> lz<-lapply(1:ncol(boruta.train$ImpHistory),function(i)

boruta.train$ImpHistory[is.finite(boruta.train$ImpHistory[,i]),i])

> names(lz) <- colnames(boruta.train$ImpHistory)

> Labels <- sort(sapply(lz,median))

> axis(side = 1,las=2,labels = names(Labels),

at = 1:ncol(boruta.train$ImpHistory), cex.axis = 0.7)

蓝色的盒状图对应一个阴影属性的最小、平均和最大Z分数。红色、黄色和绿色的盒状图分别代表拒绝、暂定和确认属性的Z分数。

现在我们对实验性属性进行判定。实验性属性将通过比较属性的Z分数中位数和最佳阴影属性的Z分数中位数被归类为确认或拒绝。让我们开始吧。

> final.boruta <- TentativeRoughFix(boruta.train)

> print(final.boruta)

Boruta performed 99 iterations in 18.399 secs.

Tentatives roughfixed over the last 99 iterations.

6 attributes confirmed important: ApplicantIncome, CoapplicantIncome,

CreditHistory, LoanAmount, LoanAmountTerm and 1 more.

5 attributes confirmed unimportant: Dependents, Education, Gender, PropertyArea,

SelfEmployed.

对属性进行初步分类后的Boruta结果图

现在我们要得出结果了。让我们获取确认属性的列表。

> getSelectedAttributes(final.boruta, withTentative = F)

[1] "Married" "ApplicantIncome" "CoapplicantIncome" "LoanAmount"

[5] "LoanAmountTerm" "CreditHistory"

我们将创建一个来自Boruta最终结果的数据框架。

> boruta.df <- attStats(final.boruta)

> class(boruta.df)

[1] "data.frame"

> print(boruta.df)

meanImp medianImp minImp maxImp normHits decision

Gender 1.04104738 0.9181620 -1.9472672 3.767040 0.01010101 Rejected

Married 2.76873080 2.7843600 -1.5971215 6.685000 0.56565657 Confirmed

Dependents 1.15900910 1.0383850 -0.7643617 3.399701 0.01010101 Rejected

Education 0.64114702 0.4747312 -1.0773928 3.745441 0.03030303 Rejected

SelfEmployed -0.02442418 -0.1511711 -0.9536783 1.495992 0.00000000 Rejected

ApplicantIncome 6.05487791 6.0311639 2.9801751 9.197305 0.94949495 Confirmed

CoapplicantIncome 5.76704389 5.7920332 1.9322989 10.184245 0.97979798 Confirmed

LoanAmount 5.19167613 5.3606935 1.7489061 8.855464 0.88888889 Confirmed

LoanAmountTerm 5.50553498 5.3938036 2.0361781 9.025020 0.90909091 Confirmed

CreditHistory 59.57931404 60.2352549 51.7297906 69.721650 1.00000000 Confirmed

PropertyArea 2.77155525 2.4715892 -1.2486696 8.719109 0.54545455 Rejected

让我们了解用于Boruta 的参数:

maxRuns:随机森林运行的最大次数。如果暂时属性被保留,你可以考虑增加这个参数。默认为100。

doTrace:它指的是详细程度。0指不跟踪。1指一旦属性被清除就作出报告决定。2意味着所有的1另加上报告每一次迭代。默认为0。

holdHistory:存储重要性运行的全部历史,当其设置为TRUE(默认)时。当plotImpHistory 功能被唤醒时生成一个分类器运行vs.重要性的表格。

更复杂的参数请参阅Boruta包文件。


Boruta VS传统特征选择算法

到这里,我们已经学习了在R里实现Boruta包的有关概念和步骤。

如果我们使用一个传统的特征选择算法,如对相同的数据集进行递归特征消除,我们是否最终获得相同的重要性特征?让我们来看看。

现在,我们将学习用于实现递归特征消除(RFE)的步骤。在R中,RFE算法可以通过使用插入包的方法实现。

让我们从定义一个可用于RFE算法的控制功能开始。我们加载所需的库:

> library(caret)

> library(randomForest)

> set.seed(123)

> control <- rfeControl(functions=rfFuncs, method="cv", number=10)

在这里,我们通过rfFuncs选项指定了一个随机森林选择功能(也是Boruta中的底层算法)。

现在让我们实现RFE算法。

> rfe.train <- rfe(traindata[,2:12], traindata[,13], sizes=1:12, rfeControl=control)

我确定这是一目了然的。traindata[,2:12],指选择ID变量和自变量以外的所有列。traindata[,13],只选择因变量。它可能需要花费一些时间来运行。

我们还可以检查该算法的结果。

> rfe.train

Recursive feature selection

Outer resampling method: Cross-Validated (10 fold)

Resampling performance over subset size:

Variables Accuracy Kappa AccuracySD KappaSD Selected

1 0.8083 0.4702 0.03810 0.1157 *

2 0.8041 0.4612 0.03575 0.1099

3 0.8021 0.4569 0.04201 0.1240

4 0.7896 0.4378 0.03991 0.1249

5 0.7978 0.4577 0.04557 0.1348

6 0.7957 0.4471 0.04422 0.1315

7 0.8061 0.4754 0.04230 0.1297

8 0.8083 0.4767 0.04055 0.1203

9 0.7897 0.4362 0.05044 0.1464

10 0.7918 0.4453 0.05549 0.1564

11 0.8041 0.4751 0.04419 0.1336

The top 1 variables (out of 1):

CreditHistory

这个算法对Credit History给出了最高权重。现在我们将图表化RFE算法的结果,得到一个变量重要性的图表。

> plot(rfe.train, type=c("g", "o"), cex = 1.0, col = 1:11)

让我们来提取所选择的功能。我相信这会反映在Credit History中。

> predictors(rfe.train)

[1] "CreditHistory"

因此,我们看到递归特征消除算法在数据集的11个特征中选取了“信用记录”作为唯一重要特征。

相比传统的特征选择算法,Boruta能够返回变量重要性的更好结果,也很容易解释!我觉得一个人能接触到许多神奇的R语言包是极好的。我相信肯定会有许多其他的特征选择包。我特别想了解它们。

结束语

Boruta是一个易用的软件包,它没有许多需要调整/记忆的参数。在使用Boruta的时候不要使用有缺失值的数据集或极端值检查重要变量。它会直接报错。您可以使用此算法来处理手上的任何分类/回归问题以得出有意义的特征。

在这篇文章中,我使用了一种快速的方法来填补缺失值。毕竟这篇文章的范围是了解boruta(理论与实践)。我建议你使用一种先进的方法,缺失值估算。毕竟,数据信息可知性是我们所期待的!继续努力。

你喜欢这篇文章吗?你使用的其他选择变量方法是什么?在下面的评论中,请分享你的建议/意见。

相关推荐

再见Swagger UI 国人开源了一款超好用的 API 文档生成框架,真香

背景最近,栈长发现某些国内的开源项目都使用到了Knife4j技术,看名字就觉得很锋利啊!...

Spring Boot自动装配黑魔法:手把手教你打造高逼格自定义Starter

如果你是SpringBoot深度用户,是否经历过这样的痛苦:每个新项目都要重复配置Redis连接池,反复粘贴Swagger配置参数,在微服务架构中为统一日志格式疲于奔命?本文将为你揭开Spring...

Spring Boot(十五):集成Knife4j(spring boot 集成)

Knife4j的简介Knife4j是一个集Swagger2和OpenAPI3为一体的增强解决方案,它的前身是上一篇文章中介绍的swagger-bootstrap-ui。swagger-bootstra...

swagger-bootstrap-ui:swagger改进版本,界面更美观易于阅读

swagger作为一款在线文档生成工具,用于自动生成接口API,避免接口文档和代码不同步,但原生的界面不是很友好,下面介绍一款改进版本swagger-bootstrap-ui,界面左右侧布局,可以打开...

界面美观功能强大,终于可以告别单调的swagger ui了——knife4j

介绍knife4j是为JavaMVC框架集成Swagger生成Api文档的增强解决方案(在非Java项目中也提供了前端UI的增强解决方案),前身是swagger-bootstrap-ui,取名kni...

从 0 到 1 实战 Spring Boot 3:手把手教你构建高效 RESTful 接口

从0到1实战SpringBoot3:手把手教你构建高效RESTful接口在微服务架构盛行的今天,构建高效稳定的RESTful接口是后端开发者的核心技能。SpringBoot凭...

SpringBoot动态权限校验终极指南:3种高赞方案让老板主动加薪!

“上周用这套方案重构权限系统,CTO当着全组的面摔了祖传代码!”一位脉脉匿名网友的血泪经验:还在用硬编码写Shiro过滤器?RBAC模型搞出200张表?是时候用SpringSecurity+动态路...

一个基于 Spring Boot 的在线考试系统

今天推荐一款超级美观的在线考试系统,感兴趣可以先去预览地址看看该项目。在线Demo预览,http://129.211.88.191,账户分别是admin、teacher、student,密码是ad...

SpringBoot API开发的十大专业实践指南

在SpringBoot应用开发领域,构建高效、可靠的API需遵循系统化的开发规范。本文结合实战编码示例,详细解析10项关键开发实践,助您打造具备工业级标准的后端接口。一、RESTful...

震碎认知!将原理融会贯通到顶点的SpringBoot实战项目

SpringBoot是什么?我们知道,从2002年开始,Spring一直在飞速的发展,如今已经成为了在JavaEE(JavaEnterpriseEdition)开发中真正意义上的标准,但...

Spring Boot 整合 Knife4j 实现接口文档编写?

Knife4j增强版的SwaggerUI实现,在Knife4j中提供了很多功能并且用户体验也随之有了很大的提升。Knife4j主要基于Swagger2.0构建的,主要的用途就是在SpringBo...

前端同事老是说swagger不好用,我用了knife4j后,同事爽得不行

日常开发当中,少不了前端联调,随着协同开发的发展,前端对接口要求也变得越来越高了。所以我使用了knife4j,同事用完觉得太舒服了。knife4j简介:Knife4j...

一个基于spring boot的Java开源商城系统

前言一个基于springboot的JAVA开源商城系统,是前后端分离、为生产环境多实例完全准备、数据库为b2b2c商城系统设计、拥有完整下单流程和精美设计的java开源商城系统https://www...

再见 Swagger!国人开源了一款超好用的 API 文档生成框架真香

Knife4j是为JavaMVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍!...

Spring Boot整合MybatisPlus和Druid

在Java中,我比较ORM熟悉的只有...

取消回复欢迎 发表评论: