簡體   English   中英

使用線性內核調整SVM時,R插入符非常慢

[英]R caret unusually slow when tuning SVM with linear kernel

在使用caret調整SVM參數時,我觀察到了一種非常奇怪的行為。 在沒有調整的情況下訓練單個模型時,具有徑向基礎內核的SVM比具有線性內核的SVM花費更多時間,這是預期的。 然而,當在相同懲罰網格上調整具有兩個內核的SVM時,具有線性內核的SVM比具有徑向基礎內核的SVM花費更多的時間。 使用R 3.2和caret 6.0-47可以在Windows和Linux中輕松復制此行為。 有誰知道為什么調整線性SVM比徑向基核SVM需要更多的時間?

SVM linear
   user  system elapsed 
   0.51    0.00    0.52 

SVM radial
   user  system elapsed 
   0.85    0.00    0.84 

SVM linear tuning
   user  system elapsed 
 129.98    0.02  130.08 

SVM radial tuning
   user  system elapsed 
   2.44    0.05    2.48 

玩具示例代碼如下:

library(data.table)
library(kernlab)
library(caret)

n <- 1000
p <- 10

dat <- data.table(y = as.factor(sample(c('p', 'n'), n, replace = T)))
dat[, (paste0('x', 1:p)) := lapply(1:p, function(x) rnorm(n, 0, 1))]
dat <- as.data.frame(dat)

sigmas <- sigest(as.matrix(dat[, -1]), na.action = na.omit, scaled = TRUE)
sigma  <- mean(as.vector(sigmas[-2]))

cat('\nSVM linear\n')
print(system.time(fit1 <- train(y ~ ., data = dat, method = 'svmLinear', tuneLength = 1,
                                 trControl = trainControl(method = 'cv', number = 3))))

cat('\nSVM radial\n')
print(system.time(fit2 <- train(y ~ ., data = dat, method = 'svmRadial', tuneLength = 1,
                                 trControl = trainControl(method = 'cv', number = 3))))

cat('\nSVM linear tuning\n')
print(system.time(fit3 <- train(y ~ ., data = dat, method = 'svmLinear',
                                 tuneGrid = expand.grid(C = 2 ^ seq(-5, 15, 5)),
                                 trControl = trainControl(method = 'cv', number = 3))))

cat('\nSVM radial tuning\n')
print(system.time(fit4 <- train(y ~ ., data = dat, method = 'svmRadial',
                                 tuneGrid = expand.grid(C = 2 ^ seq(-5, 15, 5), sigma = sigma),
                                 trControl = trainControl(method = 'cv', number = 3))))

看了之后,我不相信這個問題是由caret ,而是與kernlab背后的事情(落后)。
正如其他地方所述,堆棧溢出SVM本身就是一種密集算法。 SVM的時間復雜度為O(n * n)。 現在這不能解釋SVM調用之間的區別。 似乎正在發生的事情是在通過一個以SVM > .Local > .call.結尾的非常深的堆棧調用編譯的C代碼之后SVM > .Local > .call. .call是對已編譯的c代碼的調用,並且在我的知識庫之外)。 大多數情況下,當你看到從RC意外緩慢時間時,因為事情是如何傳遞的。 由於你拉入矩陣,這進一步導致了命名或維度問題的假設,導致另一端的一些額外工作。
如果我們看看這個代碼是如何分析的,那么瓶頸就會變得非常明顯。

關於字體大小的道歉 - 它是一個深層疊加,我認為整體形狀比單個功能更能講述故事。 隨意垃圾郵件Ctrl +下面。

nSVM_linear看起來像一個健康的配置文件和許多友好的R函數。

nSVM_linear

nSVM radial相同的交易

在此輸入圖像描述

現在,一旦我們開始'徑向調整',我們開始看到更平坦的結構, try-call堆棧開始傾斜,但一切似乎都在快速執行。

在此輸入圖像描述

哇。 完全不同的線性調諧結構C調用在某些情況下超過100秒。

在此輸入圖像描述

所以說,看起來你的瓶頸在於kernlab編譯的C代碼。 由於軟件包連接到libsvm ,這似乎非常有效,我無法想象調用代碼存在實際問題。 實際上確定如何(基於安全的功能或來自R的輸入問題)以及當從一個移動到另一個時問題發生的原因是對於比我更好的人的工作。

我在Linux上遇到了令人難以置信的svmRadial性能。 事實證明,問題在於使用多核DoMC svmRadial在單核上運行良好。 kernlab函數是caret唯一表現出我所見過的行為的函數。 除了其他人提到的問題之外,還要為kernlab添加一個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM