查看原文
其他

借助caret包实现特征选择的工作

2016-12-17 刘顺祥 每天进步一点点2015

我们有一期的文章讲述了如何使用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

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


长按识别二维码 马上关注


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存