借助caret包实现特征选择的工作
我们有一期的文章讲述了如何使用caret包进行数据的预处理,其中内容包括哑变量的创建、近零方差变了的筛选、数据标准化、缺失值处理、数据分割等。可以在教你使用caret包(一)--数据预处理获取更详细的内容介绍。下面我们接着讲讲如何使用caret包实现特征选择的任务。
特征选择的实质就是在已有的变量基础上,选择部分子集,在一定程度上避免维度灾难造成的模型过拟合,从而提升模型的精确度、降低模型的运行时间等。在卢辉的《数据挖掘与数据化运营实战》一书中一直强调一个观点:少而精的变量可以充分发挥模型的效率。
目前关于特征选择的方法主要有两大类,即封装法和过滤法:
封装法,将特征选择过程与训练过程融合在一起,以模型的预测能力作为特征选择的衡量标准。例如在多元线性模型中,我们常常会使用逐步回归的方法进行变量的筛选,这里的逐步回归就是属于封装法的一种。封装法可以选出高质量的变量子集,但运行速度上会大打折扣。
过滤法,与封装法不同的是特征选择过程与训练过程相互独立,通过分析变量内部的关系进行筛选操作,与训练模型的选择并没有关系。例如通过变量间的相关性、近零方差检验、聚类分析等方法选择出来的变量,再用于不同的训练模型构建、评估等。过滤法虽然在速度上比封装法更占优势,但可能会删除非常有实质意义的变量。
我们使用R中的caret包进行特征选择,该包也为我们提供了封装和过滤两种方法进行特征选择,首先来看看相对简单的过滤法,过滤法的实现可以使用caret包中的sbf(select by filter)函数实现,该函数需要与sbfControl函数搭配使用。我们来看看sbfControl和sbf函数的语法和参数含义:
过滤法
sbfControl(functions = NULL,
method = "boot",
saveDetails = FALSE,
number = ifelse(method %in% c("cv", "repeatedcv"), 10, 25),
repeats = ifelse(method %in% c("cv", "repeatedcv"), 1, number),
verbose = FALSE,
returnResamp = "final",
p = 0.75,
index = NULL,
indexOut = NULL,
timingSamps = 0,
seeds = NA,
allowParallel = TRUE,
multivariate = FALSE)
sbfControl函数用来设置sbf函数的控制参数,几个重要的参数如下:
functions:用于设置模型拟合、预测和特征选择的一系列函数,可以是lmSBF(线性回归),rfSBF(随机森林),treebagSBF(袋装决策树),ldaSBF(线性判别分析法),nbSBF(朴素贝叶斯)和caretSBF(自定义函数)。
method:指定抽样方法,可以是boot(BootStrap抽样),cv(交叉验证抽样),LOOCV(留一交叉验证法)和LGOCV(留组交叉验证法)。
saveDetails:是否保存特征选择过程中的预测值和变量重要性,默认为FALSE。
number:指定折数或者重抽样迭代次数,当method为cv或repeatedcv时,则默认从总体中抽取10份样本并迭代10次,否则抽取25份并迭代25次。
repeats:指定抽样组数,默认抽取一组样本。
verbose:是否返回每次重抽样的详细信息,默认为FALSE。
returnResamp:返回重抽样的汇总信息。
p:如果指定method为LGOCV时,该参数起作用,指定训练集的比重。
seeds:为抽样设置随机种子。
allowParallel:在并行后台已加载和允许的情况下,是否允许并行运算。
sbf(x, y, sbfControl = sbfControl(), ...)
x:指定输入变量。
y:指定输出变量。
sbfControl:指定sbf函数的控制参数。
过滤法的案例实战
我们使用C50包中的用户流失数据作为案例,通过过滤法进行特征选择:
#加载所需的R包
if(!suppressWarnings(require(C50))){
install.packages('C50')
require(C50)
}
if(!suppressWarnings(require(caret))){
install.packages('caret')
require(caret)
}
#加载C50包中的数据集
data(churn)
#构建sbf函数的控制参数(使用朴素贝叶斯函数和BootStrap抽样方法)
sbfControls_nb <- sbfControl(
functions = nbSBF,
method = 'boot')
#使用sbf函数进行特征选择
fs_nb <- sbf(x = churnTrain[,-20],
y = churnTrain[,20],
sbfControl = sbfControls_nb)
基于随机森林函数和BootStrap抽样方法,从19个自变量中筛选出11个优秀的变量.
其中的11个变量为:
#构建sbf函数的控制参数(使用随机森林函数和10重交叉验证抽样方法,并抽取5组样本)
sbfControls_rf <- sbfControl(
functions = rfSBF,
method = 'cv',
repeats = 5)
#使用sbf函数进行特征选择
fs_rf <- sbf(x = churnTrain[,-20],
y = churnTrain[,20],
sbfControl = sbfControls_rf)
基于随机森林函数和10重交叉验证的抽样方法,从19个自变量中筛选出11个优秀的变量.
选出的变量是:
封装法
caret包中提供的封装法主要有3种,即递归特征删减法、遗传算法和蚁群算法。三种方法实现的函数分别是rfe(),gafs()和safs()。同样,我们来看看这三个函数的语法特征和参数含义:
rfeControl(functions = NULL,
rerank = FALSE,
method = "boot",
saveDetails = FALSE,
number = ifelse(method %in% c("cv", "repeatedcv"), 10, 25),
repeats = ifelse(method %in% c("cv", "repeatedcv"), 1, number),
verbose = FALSE,
returnResamp = "final",
p = .75,
index = NULL,
indexOut = NULL,
timingSamps = 0,
seeds = NA,
allowParallel = TRUE)
rerank:布尔类型参数,在每次特征删除的过程中是否重新计算特征的重要性,默认为False。
其他参数与sbfControl函数的参数一致,这里不再赘述。
rfe(x, y,
sizes = 2^(2:4),
metric = ifelse(is.factor(y), "Accuracy", "RMSE"),
maximize = ifelse(metric == "RMSE", FALSE, TRUE),
rfeControl = rfeControl(),
...)
x:指定输入变量。
y:指定输出变量。
sizes:通过一个整数向量,指定需要保留的特征数量。
metric:指定衡量最优模型的判断指标,默认使用RMSE(均方根误差)和Rsquared(判决系数)衡量回归模型,使用Accuracy(精确度)和Kappa系数衡量分类模型。
maximize:布尔类型参数,如果metric为RMSE,则不要求metric最小化,否则要求Kappa系数、判决系数最大化和精确度达到最大化。
rfeControl:指定rfe函数的控制参数。
递归特征删减法的案例实战
我们仍然使用C50包中的用户流失数据作为案例,用来比较过滤法和封装法。
#构建rfe函数的控制参数(使用随机森林函数和BootStrap抽样方法)
rfeControls_nb <- rfeControl(
functions = nbFuncs,
method = 'boot')
#使用rfe函数进行特征选择
fs_nb <- rfe(x = churnTrain[,-20],
y = churnTrain[,20],
sizes = seq(4,19,2),
rfeControl = rfeControls_nb)
从返回的结果可知,可以选择的最优变量个数为11或12个,同样通过图形也能够看出来。似乎跟过滤法没有太大的差异,而且运行时间非常长!
plot(fs_nb, type = c('g','o'))
#构建rfe函数的控制参数(使用随机森林函数和10重交叉验证抽样方法,并抽取5组样本)
rfeControls_rf <- rfeControl(
functions = rfFuncs,
method = 'cv',
repeats = 5)
#使用rfe函数进行特征选择
fs_nb <- rfe(x = churnTrain[,-20],
y = churnTrain[,20],
sizes = seq(4,19,2),
rfeControl = rfeControls_rf)
使用随机森林函数,当选择10个变量时,精确度就超过95%了,而过滤法选择11个变量时,精确度还不足93%,故在93%的精确度下,完全可以使用随机森林函数,而且只需要8个变量就可以达到功效,速度还是非常快的!。
如下是变量选择的可视化结果:
plot(fs_rf, type = c('g','o'))
通过比较发现,随机森林函数在特征选择时还是非常优秀的,既能保证精确度的提升,又能够快速的返回运行结果。
本期的内容就到这里,基于遗传算法和蚁群算法的特征选择将在后期补上,这里面的理论内容消化起来非常费力,请各位朋友谅解。同时也欢迎热爱数据分析与挖掘的朋友们多多分享与交流!
每天进步一点点2015
学习与分享,取长补短,关注小号!
长按识别二维码 马上关注