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"
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容