R語言中的資料探勘演算法/分類/懲罰SVM
分類器是最常見的資料分析工具之一。有很多已實現的技術,但我們可以將SVM(支援向量機)作為最強大的技術之一,尤其是在高維資料中。最著名的SVM演算法是由弗拉基米爾·瓦普尼克建立的。[1]
標準的SVM實現SVM接收一個輸入資料集,並針對每個給定的輸入預測該輸入集屬於兩個可能類別中的哪一個。這是演算法最常見的用途,用於預測輸入是否屬於某個二分法,或者不屬於。由於此特性,SVM被稱為非機率二元線性分類器。
在基於機器學習的演算法(如SVM)中,輸入資料必須分成兩個集合:訓練集和測試集。訓練集和測試集之間的區別在於,在訓練集中,示例的類別事先已知。測試集包含應該預測其類別的示例。給定一組訓練示例,SVM演算法構建一個模型來預測測試集示例的類別。
在d維空間中表示示例,演算法構建的模型是一個超平面,它將屬於二分法的示例與不屬於二分法的示例分開。然後將新示例對映到該空間,以便我們可以根據其落入的間隙的哪一側來預測其所屬的類別。
此處描述的技術是使用懲罰函式的標準SVM的變體。該技術在稱為懲罰SVM的R包中實現,該包具有平滑截斷絕對偏差(SCAD)、“L1範數”、“彈性網路”(“L1範數”和“L2範數”)和“彈性SCAD”(SCAD和“L2範數”)作為可用的懲罰。
事實上,找到最佳模型來對新示例進行分類類似於找到最佳超平面的問題。演算法構建的模型的質量透過其超平面的邊距來衡量。邊距是超平面wx+b = 1和wx+b = -1之間的距離,因此每個超平面的一側最靠近wx+b = 0的點都被另外兩個超平面穿過。最佳超平面是具有最大邊距的超平面。
找到具有最大邊距的最佳超平面的問題透過凸最佳化來解決。最大化邊距可以透過求解以下問題來實現:
術語
在 SVM 實現中具有 L2 範數('嶺懲罰')的形式。這種懲罰會導致係數的減少,但並不總是減少到大於零的值。
模型的質量也可以透過計算訓練集預測誤差來衡量。需要較低的預測誤差,但將其降低到零可能會導致一個稱為過擬合的問題。這意味著構建的模型能夠很好地對訓練集中的樣本進行分類,但並不適合對測試集中的樣本進行分類。在這種情況下,對新樣本的預測通常會出錯。
不僅低預測誤差定義了模型的質量。可以透過識別在判別中起重要作用的協變數並評估其對分類器的貢獻來進一步改進模型。這可以透過應用特徵選擇方法來實現。
特徵選擇方法分為兩類:過濾方法和包裝方法[2]。過濾方法在演算法構建模型之前丟棄不相關的特徵。包裝方法透過在最佳化過程中進行選擇來提高預測能力。
R 包 'penalizedSVM' 提供了一些特徵選擇方法。其中之一是包裝特徵選擇 SCAD(平滑剪下絕對偏差)。SCAD 是一種非凸懲罰函式,最初由 Fan[3]提出,並在[4]中進行了討論。[5]將 SVM 與 SCAD 相結合用於特徵選擇。SCAD SVM 的懲罰項形式為
其中,每個係數 wj 的 SCAD 懲罰函式定義為
其中調整引數 a > 2(在包中,a = 3.7)和 λ > 0。pλ (w) 對應於在 λ 和 aλ 處有節點的二次樣條函式。
對於較小的係數,SCAD 與 L1 的行為相同。然而,對於較大的係數,SCAD 應用恆定懲罰,這與 L1 懲罰形成對比,後者隨著係數的增加而線性增加。SCAD 懲罰的這個絕對最大值獨立於輸入資料,減少了估計大系數的可能偏差。
本節描述的包為 penalizedSVM。此包使用懲罰函式提供特徵選擇 SVM。平滑剪下絕對偏差 (SCAD)、'L1 範數'、'彈性網路'('L1 範數' 和 'L2 範數')和 '彈性 SCAD'(SCAD 和 'L2 範數')懲罰可用。可以使用固定網格或區間搜尋找到調整引數。
此包有幾個依賴項。需要安裝的包及其描述如下所示
- e1071 用於潛在類別分析、短時傅立葉變換、模糊聚類、支援
向量機、最短路徑計算、袋裝聚類、樸素貝葉斯分類器等。
- MASS支援 Venables 和 Ripley 的函式和資料集,'現代應用統計與 S'(第 4
版)。
- corpcor此包實現了用於協方差矩陣的 James-Stein 型收縮估計器,
分別對方差和相關性進行收縮。該方法的詳細資訊在 Sch\"afer 和 Strimmer (2005) 以及 Opgen-Rhein 和 Strimmer (2007) 中有解釋。
- stadmod 各種統計建模函式,包括生長曲線比較、限制稀釋
分析、混合線性模型、異方差迴歸、Tweedie 族廣義線性模型、逆高斯分佈和高斯求積。
- tgp 基於樹的高斯過程的貝葉斯非平穩、半引數非線性迴歸和設計
帶有跳躍到限制線性模型 (LLM)。
- mlepg 用於單變數和多維輸出的最大似然高斯過程建模
帶有診斷圖。請聯絡維護者獲取實現靈敏度分析功能的包版本。
- lhs 此包提供了多種建立和增強拉丁超立方樣本的方法
penalizedSVM 中的主要函式是 svm.fs。其用法可以描述如下
## Default S3 method:
svm.fs(
x,
y,
fs.method = c("scad", "1norm", "scad+L2", "DrHSVM"),
### tuning parameter settings
# chose the search method for tuning lambda1,2: 'interval' or 'discrete'
grid.search=c("interval","discrete"),
#fixed grid for lambda1, lambda2
lambda1.set=NULL,
lambda2.set=NULL,
# define range for lambda1,2 for interval search
bounds=NULL,
# parms.coding="none" or "log2"
parms.coding= c("log2","none"),
# internal parameter for DIRECT
maxevals=500,
### valuidation settings
# fot nested validation, 'cross.outer'-fold cv
#cross.outer= 0,
# method for the inner validation: cross validation, gacv
inner.val.method = c("cv", "gacv"),
# 'cross.inner'-fold cv
cross.inner= 5,
# show plots in Direct?
show= c("none", "final"),
### other settings
# internal parameter for svm
calc.class.weights=FALSE,
class.weights=NULL,
#seed
seed=123,
# max iterations for the feature selection svm method
maxIter=700,
# verbose?
verbose=TRUE,
...)
其中引數為
- x: 輸入矩陣,列為基因,行為樣本!
- y: 類標籤的數值向量,-1,1
- fs.method: 特徵選擇方法。可用 'scad'、'1norm' 表示 1 範數、"DrHSVM" 表示彈性網路和 "scad+L2" 表示彈性 SCAD
- grid.search: 選擇 lambda1、2 的搜尋方法:'interval' 或 'discrete',預設:'interval'
- lambda1.set: 用於固定網格搜尋:lambda1 的固定網格,預設:NULL
- lambda2.set: 用於固定網格搜尋:lambda2 的固定網格,預設值:NULL
- bounds: 用於區間網格搜尋:lambda2 的固定網格,預設值:NULL
- parms.coding: 用於區間網格搜尋:parms.coding:none 或 log2,預設值:log2
- maxevals: DIRECT 函式評估的最大次數,預設值:500。
- cross.outer: 外層交叉驗證的摺疊數,預設值為 0,表示不進行交叉驗證。
- calc.class.weights: 為 SVM 計算 class.weights,預設值:FALSE
- class.weights: 用於非對稱類的不同類的權重新命名向量。
大小。並非所有因子水平都需要提供(預設權重:1)。所有元件都必須命名。
- inner.val.method: 內部驗證的方法:交叉驗證、gacv,預設 cv
- cross.inner: ‘cross.inner’ 摺疊交叉驗證,預設值:5
- show: 用於區間搜尋:顯示 DIRECT 演算法的繪圖:none、最終迭代、所有迭代。預設值:none
- seed: 隨機數種子
- maxIter: 最大迭代次數,預設值:700
- verbose: 是否詳細輸出?預設值:TRUE
- ... additional: 其他引數
要視覺化演算法的結果,可以使用 show 函式,如上例所示。
在本節中,我們將說明一個使用 penalizedSVM 的案例研究。
目標是判斷一張圖片是否屬於之前選擇的那張圖片的同一類別。為此,我們使用這些特徵值之間的差異。用作輸入的資料的屬性表示所選圖片中特徵值的差異以及我們想要分類的圖片。
訓練集和測試集是使用下面顯示的命令生成的。
> train<-sim.data(n = 200, ng = 100, nsg = 10, corr=FALSE, seed=seed ) > print(str(train)) List of 3 $ x : num [1:100, 1:200] -0.5605 2.1988 -0.0736 1.074 0.3563 ... ..- attr(*, "dimnames")=List of 2 .. ..$ : chr [1:100] "pos1" "pos2" "pos3" "pos4" ... .. ..$ : chr [1:200] "1" "2" "3" "4" ... $ y : Named num [1:200] 1 -1 1 1 1 -1 -1 -1 1 -1 ... ..- attr(*, "names")= chr [1:200] "1" "2" "3" "4" ... $ seed: num 123 NULL > test<-sim.data(n =20, ng = 100, nsg = 10, corr=FALSE, seed=seed+1 ) > print(str(test)) List of 3 $ x : num [1:100, 1:20] -1.3851 -1.1036 -0.2677 0.2836 -0.0951 ... ..- attr(*, "dimnames")=List of 2 .. ..$ : chr [1:100] "pos1" "pos2" "pos3" "pos4" ... .. ..$ : chr [1:20] "1" "2" "3" "4" ... $ y : Named num [1:20] -1 1 -1 1 1 1 1 1 1 -1 ... ..- attr(*, "names")= chr [1:20] "1" "2" "3" "4" ... $ seed: num 124 NULL
要構建模型,使用以下命令。
> bounds=t(data.frame(log2lambda1=c(-10, 10)))
>colnames(bounds)<-c("lower", "upper")
# computation intensive; for demostration reasons only for the first 100 features
# and only for 10 Iterations maxIter=10, default maxIter=700
>system.time( scad<- svm.fs(t(train$x)[,1:100], y=train$y, fs.method="scad", bounds=bounds,
+ cross.outer= 0, grid.search = "interval", maxIter = 10,
+ inner.val.method = "cv", cross.inner= 5, maxevals=500,
+ seed=seed, parms.coding = "log2", show="none", verbose=FALSE ) )
檢視建立的模型。
> print(str(scad$model)) List of 11 $ w : Named num [1:23] 0.625 0.616 0.353 0.258 0.959 ... ..- attr(*, "names")= chr [1:23] "pos1" "pos2" "pos3" "pos4" ... $ b : num -0.115 $ xind : int [1:23] 1 2 3 4 5 6 7 8 9 10 ... $ index : int [1:83] 3 4 9 14 17 18 22 35 37 40 ... $ fitted : num [1:200] 2.6 1.24 0.65 1 1.15 ... $ type : num 0 $ lambda1 : num 0.126 $ lambda2 : NULL $ iter : num 10 $ q.val : num 0.195 $ fit.info:List of 13 ..$ fmin : num 0.195 ..$ xmin : Named num -2.99 .. ..- attr(*, "names")= chr "log2lambda1" ..$ iter : num 26 ..$ neval : num 46 ..$ maxevals : num 500 ..$ seed : num 123 ..$ bounds : num [1, 1:2] -10 10 .. ..- attr(*, "dimnames")=List of 2 .. .. ..$ : chr "log2lambda1" .. .. ..$ : chr [1:2] "lower" "upper" ..$ Q.func : chr ".calc.scad" ..$ points.fmin:'data.frame': 1 obs. of 2 variables: .. ..$ log2lambda1: num -2.99 .. ..$ f : num 0.195 ..$ Xtrain : num [1:46, 1] -7.52 -2.26 -1.34 9.99 9.03 ... .. ..- attr(*, "dimnames")=List of 2 .. .. ..$ : NULL .. .. ..$ : chr "log2lambda1" ..$ Ytrain : num [1:46] 3.65e-01 3.20e-01 4.60e-01 1.00e+16 1.00e+16 ... ..$ gp.seed : num [1:25] 123 124 125 126 127 128 129 130 131 132 ... ..$ model.list :List of 1 .. ..$ model:List of 10 .. .. ..$ w : Named num [1:23] 0.625 0.616 0.353 0.258 0.959 ... .. .. .. ..- attr(*, "names")= chr [1:23] "pos1" "pos2" "pos3" "pos4" ... .. .. ..$ b : num -0.115 .. .. ..$ xind : int [1:23] 1 2 3 4 5 6 7 8 9 10 ... .. .. ..$ index : int [1:83] 3 4 9 14 17 18 22 35 37 40 ... .. .. ..$ fitted : num [1:200] 2.6 1.24 0.65 1 1.15 ... .. .. ..$ type : num 0 .. .. ..$ lambda1 : num 0.126 .. .. ..$ iter : num 10 .. .. ..$ q.val : num 0.195 .. .. ..$ inner.val.method: chr "cv" NULL
預測測試集上示例的類別。
>(scad.5cv.test<-predict.penSVM(scad, t(test$x)[,1:100], newdata.labels=test$y) )
$pred.class
[1] -1 1 -1 -1 -1 1 1 1 1 -1 -1 -1 1 1 1 -1 1 1 -1 -1
Levels: -1 1
$fitted
[,1]
1 -2.5344366
2 2.3440943
3 -1.3972349
4 -0.3613470
5 -2.1187284
6 1.1287477
7 2.5584662
8 1.9155333
9 1.5543941
10 -0.7128084
11 -1.6944994
12 -0.2943272
13 1.8497781
14 2.7800572
15 0.8927699
16 -0.1289518
17 2.4560094
18 0.8756835
19 -2.2114729
20 -1.7342811
$tab
newdata.labels
pred.class -1 1
-1 6 4
1 1 9
$error
[1] 0.25
$sensitivity
[1] 0.6923077
$specificity
[1] 0.8571429
> test<-sim.data(n = 20, ng = 100, nsg = 10, corr=FALSE, seed=seed+1 )
> print(str(test))
List of 3
$ x : num [1:100, 1:20] -1.3851 -1.1036 -0.2677 0.2836 -0.0951 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : chr [1:100] "pos1" "pos2" "pos3" "pos4" ...
.. ..$ : chr [1:20] "1" "2" "3" "4" ...
$ y : Named num [1:20] -1 1 -1 1 1 1 1 1 1 -1 ...
..- attr(*, "names")= chr [1:20] "1" "2" "3" "4" ...
$ seed: num 124
NULL
> (scad.5cv.test<-predict.penSVM(scad, t(test$x)[,1:100], newdata.labels=test$y))
$pred.class
[1] -1 1 -1 -1 -1 1 1 1 1 -1 -1 -1 1 1 1 -1 1 1 -1 -1
Levels: -1 1
$fitted
[,1]
1 -2.5344366
2 2.3440943
3 -1.3972349
4 -0.3613470
5 -2.1187284
6 1.1287477
7 2.5584662
8 1.9155333
9 1.5543941
10 -0.7128084
11 -1.6944994
12 -0.2943272
13 1.8497781
14 2.7800572
15 0.8927699
16 -0.1289518
17 2.4560094
18 0.8756835
19 -2.2114729
20 -1.7342811
$tab
newdata.labels
pred.class -1 1
-1 6 4
1 1 9
$error
[1] 0.25
$sensitivity
[1] 0.6923077
$specificity
[1] 0.8571429
要分析結果,可以使用以下命令。
> print(paste("minimal 5-fold cv error:", scad$model$fit.info$fmin,
+ "by log2(lambda1)=", scad$model$fit.info$xmin))
[1] "minimal 5-fold cv error: 0.195 by log2(lambda1)= -2.99093721912059"
> print(" all lambdas with the same minimum? ")
[1] " all lambdas with the same minimum? "
> print(scad$model$fit.info$ points.fmin)
log2lambda1 f
36 -2.990937 0.195
> print(paste(scad$model$fit.info$neval, "visited points"))
[1] "46 visited points"
#Plot the results
>.plot.EPSGO.parms (scad$model$fit.info$Xtrain, scad$model$fit.info$Ytrain,
+ bound=bounds, Ytrain.exclude=10^16, plot.name=NULL )
- ↑ Corinna Cortes 和 V. Vapnik,支援向量機,機器學習,20,1995。http://www.springerlink.com/content/k238jx04hm87j80g/
- ↑ Blum A 和 Langley P,機器學習中相關特徵和示例的選擇。Artif. Intell. 1997;97:245-271。
- ↑ Fan J.,關於 A. Antoniadis 的“統計中的小波:綜述”的評論。和 J. Italian Stat.Assoc. 1997;6:131-138。
- ↑ Fan J.,關於 A. Antoniadis 的“統計中的小波:綜述”的評論。和 J. Italian Stat.Assoc. 1997;6:131-138。
- ↑ Zhang HH 等,使用具有非凸懲罰的支援向量機的基因選擇。Bioinformatics 2006;22:88-95。
