55-caret包学习:预处理函数

1、创建虚拟变量

caret包通过model.matrix()、dummyVars()或其他方式将因子转换为虚拟变量。
dummyVars()可用于从一个或多个因子变量生成一个完整的虚拟变量集。该函数获取一个公式和一个数据集,并输出一个对象,该对象创建虚拟变量可用于预测。

> library(pacman)
> p_load(earth, caret)
> data(etitanic)
> str(etitanic)
## 'data.frame':    1046 obs. of  6 variables:
##  $ pclass  : Factor w/ 3 levels "1st","2nd","3rd": 1 1 1 1 1 1 1 1 1 1 ...
##  $ survived: int  1 1 0 0 0 1 1 0 1 0 ...
##  $ sex     : Factor w/ 2 levels "female","male": 1 2 1 2 1 2 1 2 1 2 ...
##  $ age     : num  29 0.917 2 30 25 ...
##  $ sibsp   : int  0 1 1 1 1 0 1 0 2 0 ...
##  $ parch   : int  0 2 2 2 2 0 0 0 0 0 ...

该数据集包括两个因子变量,pclass表示乘客等级,sex表示性别。
看看R基本函数model.matrix()生成的结果:

> lm.mat <- model.matrix(survived ~ ., data = etitanic)
> head(lm.mat, 3)
##   (Intercept) pclass2nd pclass3rd sexmale     age sibsp parch
## 1           1         0         0       0 29.0000     0     0
## 2           1         0         0       1  0.9167     1     2
## 3           1         0         0       0  2.0000     1     2

再看看dummyVars()函数的结果:

> dummies <- dummyVars(survived ~ ., data = etitanic)
> pred.dummies <- predict(dummies, newdata = etitanic)
> head(pred.dummies, 3)
##   pclass.1st pclass.2nd pclass.3rd sex.female sex.male     age sibsp parch
## 1          1          0          0          1        0 29.0000     0     0
## 2          1          0          0          0        1  0.9167     1     2
## 3          1          0          0          1        0  2.0000     1     2

注意没有截距项,每个级别的因子都有一个虚拟变量,所以这个参量化的函数对于某些模型可能没有用处,比如lm()。

2、零方差和接近零方差变量的预测

在某些情况下,数据生成机制可以创建只有一个唯一值的预测因子(即“零方差预测器”)。 对于许多模型(不包括基于树的模型) ,这可能会导致模型崩溃或拟合得不健壮。

> data(mdrr)
> table(mdrrDescr$nR11)
## 
##   0   1   2 
## 501   4  23

数据集中可能只有少数值出现的频率很低,非常的不平衡。当使用交叉验证建模时,这些样本可能对模型的影响很小而成为零方差预测因子。
nearZeroVar()函数用来识别常数自变量,或者是方差极小的自变量:

> # saveMetrics默认为F,用来显示细节
> nzv <- nearZeroVar(mdrrDescr,
+                    # 第一众数与第二众数的比率的cutoff(临界值)
+                    freqCut = 95/5,
+                    # 剔重后的唯一值 与 样本总数量的百分比,大于这个值不会被剔除
+                    uniqueCut = 10,
+                    saveMetrics = T)
> str(nzv)
## 'data.frame':    342 obs. of  4 variables:
##  $ freqRatio    : num  1.25 1.12 1 1.25 1.25 ...
##  $ percentUnique: num  90 42.6 83 84.3 82.8 ...
##  $ zeroVar      : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ nzv          : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
> # 显示前10个接近零方差的变量
> nzv[nzv$nzv,][1:10,]
##        freqRatio percentUnique zeroVar  nzv
## nTB     23.00000     0.3787879   FALSE TRUE
## nBR    131.00000     0.3787879   FALSE TRUE
## nI     527.00000     0.3787879   FALSE TRUE
## nR03   527.00000     0.3787879   FALSE TRUE
## nR08   527.00000     0.3787879   FALSE TRUE
## nR11    21.78261     0.5681818   FALSE TRUE
## nR12    57.66667     0.3787879   FALSE TRUE
## D.Dr03 527.00000     0.3787879   FALSE TRUE
## D.Dr07 123.50000     5.8712121   FALSE TRUE
## D.Dr08 527.00000     0.3787879   FALSE TRUE
> dim(mdrrDescr)
## [1] 528 342
> index <- nearZeroVar(mdrrDescr)
> filter.Descr <- mdrrDescr[, -index]
> dim(filter.Descr)
## [1] 528 297

可以看到,数据由342个变量删减为297个变量了。

3、识别与其他变量有强相关性的变量

> # 建立相关性矩阵
> descr.cor <- cor(filter.Descr)
> summary(descr.cor[upper.tri(descr.cor)])

查看相关性统计信息:

##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -0.99607 -0.05373  0.25006  0.26078  0.65527  1.00000
> # 找出相关性高于0.75的变量
> high.cor <- findCorrelation(descr.cor, cutoff = 0.75)
> length(high.cor)
## [1] 247

一共247个变量,与其他变量的相关性高于0.75。

> low.cor <- filter.Descr[, -high.cor]
> descr.cor.2 <- cor(low.cor)
> summary(descr.cor.2[upper.tri(descr.cor.2)])
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -0.70728 -0.05378  0.04418  0.06692  0.18858  0.74458

剔除后再看看相关性统计信息,全部在0.75以下了。

4、识别变量共线性

> mat <- matrix(0, nrow = 6, ncol = 6)
> mat[, 1] <- c(1, 1, 1, 1, 1, 1)
> mat[, 2] <- c(1, 1, 1, 0, 0, 0)
> mat[, 3] <- c(0, 0, 0, 1, 1, 1)
> mat[, 4] <- c(1, 0, 0, 1, 0, 0)
> mat[, 5] <- c(0, 1, 0, 0, 1, 0)
> mat[, 6] <- c(0, 0, 1, 0, 0, 1)

请注意,第二列和第三列相加就等于第一列。同样,第四、五和六列加起来就是第一列。Findlinearcombos()函数将返回一个列表,列举这些依赖项。对于每个线性组合,它都会递增地从矩阵中删除列,并测试依赖关系是否已被解析。还将返回一个列位置的向量,以消除线性依赖:

> combo.info <- findLinearCombos(mat)
> combo.info
## $linearCombos
## $linearCombos[[1]]
## [1] 3 1 2
## 
## $linearCombos[[2]]
## [1] 6 1 4 5
## 
## 
## $remove
## [1] 3 6
> mat <- mat[, -combo.info$remove]
> mat
##      [,1] [,2] [,3] [,4]
## [1,]    1    1    1    0
## [2,]    1    1    0    1
## [3,]    1    1    0    0
## [4,]    1    0    1    0
## [5,]    1    0    0    1
## [6,]    1    0    0    0

5、preProcess函数

缺省参数是标准化数据,其高级功能还包括用K近邻和装袋决策树两种方法来预测缺失值。此外它还可以进行cox幂变换和主成分提取。
method为处理方法,可能的值为"BoxCox", "YeoJohnson", "expoTrans", "center", "scale", "range", "knnImpute", "bagImpute", "medianImpute", "pca", "ica", "spatialSign", "corr", "zv", "nzv", "conditionalX"。

BoxCox 变换用于响应变量的转换,对于估计幂变换也同样有效
YeoJohnson 转换类似于 Box-Cox 模型,但是可以容纳零和 / 或负值的预测器(BoxCox 转换的预测器值必须严格为正)

center 预测值减去预测值数据的平均值
scale 预测值除以预测值数据的标准差

range 转换扩展了范围内的数据。 如果新样本的值大于或小于训练集中的值,则值将超出此范围。在计算中将忽略非数值型预测值。

zv 用单个值(即方差为零)标识数值型预测列,并将其排除在进一步计算之外
nzv 通过应用nearZeroVar函数标识方差接近0的变量,并将其排除在进一步计算之外
除非使用zv或者nzv方法,否则任何数值型变量少于2个唯一值时函数将报错

corr 通过findCorrelation函数过滤掉高度相关的预测因子

conditionalX 对于分类,根据结果检查每个预测因子的分布情况。如果某类中只有一个唯一值,则预测器将被排除在进一步计算之外。如果预测的不是因子变量,则不执行此计算。 这个操作在通过train函数进行重采样时会很耗时。

运算按如下顺序进行: zero-variance filter, near-zero variance filter, correlation filter, Box-Cox/Yeo-Johnson/exponential transformation, centering, scaling, range, imputation, PCA, ICA then spatial sign.

使用PCA和ICA方法时,数据将被自动中心化和标准化。如果同时使用PCA和ICA方法,则会抛出警告。Ica由fastICA包实现,在查找ICA得分之前自动进行PCA分解
注意,当使用PCA或ICA时,非数值型变量在预测时可能位于不同的位置。非数值型数据不会被预处理,但是他们的值会保留在预测值中。

knnImpute 通过训练集的K最近邻(欧式距离)填充缺失值
bagImpute 通过装袋法填充缺失值,该方法简单、准确、可接受缺失值,但是计算量大
medianImpute 通过训练集中预测值的中位数填充缺失值,该方法简单、快速、可接受缺失值,但可能不准确

5.1 中心化和标准化

> set.seed(120)
> ind <- sample(2, nrow(low.cor), replace = T, prob = c(0.7, 0.3))
> 
> train <- low.cor[ind == 1, ]
> test <- low.cor[ind == 2, ]
> 
> dim(train)
## [1] 367  50
> dim(test)
## [1] 161  50
> # 同时使用多种预处理方法
> preprocess.values <- preProcess(train, 
+     method = c("center", "scale", "YeoJohnson", "nzv"))
> preprocess.values
## Created from 367 samples and 50 variables
## 
## Pre-processing:
##   - centered (50)
##   - ignored (0)
##   - scaled (50)
##   - Yeo-Johnson transformation (31)
## 
## Lambda estimates for Yeo-Johnson transformation:
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -2.70101 -0.41917  0.04850 -0.07775  0.35785  1.88606
> train.transformed <- predict(preprocess.values, train)
> test.transformed <- predict(preprocess.values, test)
> 
> train[1:3, 1:3]
##                 AMW   Mp   Ms
## METHOPROMAZINE 7.15 0.67 1.92
## ACEPROMAZINE   7.26 0.68 2.06
## TRIMEPRAZINE   6.94 0.68 1.85
> train.transformed[1:3, 1:3]
##                        AMW        Mp         Ms
## METHOPROMAZINE 0.322580832 0.5994524 -0.9359891
## ACEPROMAZINE   0.480970227 0.9717011 -0.3131278
## TRIMEPRAZINE   0.007559779 0.9717011 -1.2474198

5.2 特征选择

在进行数据挖掘时,我们并不需要将所有的自变量用来建模,而是从中选择若干最重要的变量,这称为特征选择(feature selection)。一种算法是后向选择,即先将所有的变量都包括在模型中,然后计算其效能(如误差、预测精度)和变量重要排序,然后保留最重要的若干变量,再次计算效能,这样反复迭代,找出合适的自变量数目。这种算法的一个缺点在于可能会存在过度拟合,所以需要在此算法外再套上一个样本划分的循环。在caret包中的rfe()函数可以完成这项任务。

> # functions确定用什么样的模型进行自变量排序,本例选择的模型是随机森林即rfFuncs
> # 可以选择的还有lmFuncs(线性回归),nbFuncs(朴素贝叶斯),treebagFuncs(装袋决策树),caretFuncs(使用caret包的训练模型)
> # method确定用什么样的抽样方法,本例使用cv即交叉检验
> # 还有提升boot以及留一交叉检验LOOCV
> ctrl <- rfeControl(functions = rfFuncs, 
+                    # 确定抽样方法,默认为“boot”
+                    method = "repeatedcv",
+                    verbose = F,
+                    # 交叉验证折数或抽样迭代次数,默认10和25
+                    number = 20,
+                    returnResamp = "final")
> 
> # 使用随机森林算法,设置多线程(linux系统)
> if (require("multicore", quietly = TRUE, warn.conflicts = FALSE)) {
+   ctrl$workers <- multicore:::detectCores()
+   ctrl$computeFunction <- mclapply
+   ctrl$computeArgs <- list(mc.preschedule = FALSE, mc.set.seed = FALSE)
+ }
> 
> # 特征选择
> profile <- rfe(
+   # 训练集自变量矩阵或数据库,注意,列名必须唯一
+   train.transformed,
+   # 训练集的结果向量(数值型或因子型)
+   mdrrClass[ind==1],
+   # 指定选择最优模型的指标,默认分类用Acc,回归用RMSE
+   metric = "Accuracy",
+   # metric是否最大化,"Accuracy"为T,RMSE为F
+   maximize = T,
+   # 控制项列表,包括拟合预测的函数
+   rfeControl = ctrl,
+   rerank=F)
> profile
## 
## Recursive feature selection
## 
## Outer resampling method: Cross-Validated (20 fold, repeated 1 times) 
## 
## Resampling performance over subset size:
## 
##  Variables Accuracy  Kappa AccuracySD KappaSD Selected
##          4   0.7744 0.5374    0.07025  0.1434         
##          8   0.8234 0.6376    0.07440  0.1559         
##         16   0.8311 0.6544    0.06564  0.1292        *
##         50   0.8311 0.6539    0.05745  0.1134         
## 
## The top 5 variables (out of 16):
##    X5v, VRA1, H3D, G1, QXXm

最终选择了16个变量。画图看看重要性排序:

> plot(profile)
变量重要性

可以看到16个变量时效能最高。返回最终保留的自变量:

> profile$optVariables
##  [1] "X5v"   "VRA1"  "H3D"   "G1"    "QXXm"  "Xt"    "nBnz"  "Jhetm" "SPAM" 
## [10] "TIE"   "nAB"   "FDI"   "VEA1"  "BLI"   "SPI"   "SPH"
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容