這個單元,我們要介紹如何在R使用SVM(SpportVectorMachine)。
在世界上,SVM(SupportVectorMachine)最有名的實作之一,就是出自台灣大學資工系林智仁老師實驗室的libsvm套件。R的e1071套件則是libsvm的wrapper,讓我們可以直接透過e1071讓libsvm的核心幫我們解出SVM的模型。請同學安裝這個套件。
check_then_install("e1071", "1.6.7")
請同學載入e1071套件
library(e1071)
請同學輸入:vignette(package="e1071")檢查e1071上的vignette清單。
vignette(package = "e1071")
請同學輸入:vignette("svmdoc",package="e1071")打開名稱為svmdoc的vignette。這份文件很清楚的介紹了SVM演算法、和e1071相關的各種變形、原理,以及對應的參數。
vignette("svmdoc", package = "e1071")
再來請同學輸入?svm打開svm的說明文件。
?svm
由於svm有formulainterface,所以我們可以簡單利用g<-svm(Species~.,iris)馬上學出一個svm的模型。
g <- svm(Species ~ ., iris)
svm在學習時,可以依據應用解決不同的問題。這取決於目標的型態。舉例來說,如果我們使用svm(Species~.,iris),這裡的預測目標就是iris$Species這個變數了。請問同學,這個變數的型態(class)是什麼?
class(iris$Species)
由於預測的目標是一個類別變數,所以R會自動使用classification的模式來解決問題。svm中支援的模式列在說明文件的Arguments項目下的type參數之中。
至於kernel參數則可以讓svm學習出資料中非線性的模式。不同的kernel也可以透過不同的額外參數來調整。所有的細節,都可以在?svm打開的說明文件中找到。
依照說明文件,degree參數是用於哪一種kernel?
polynomial
預測也是很直接的使用predict(g,iris)就可以了,請同學試試看。
predict(g, iris)
由於e1071套件是使用S3物件導向的系統,所以我們可以利用?predict.svm打開說明文件,查閱如何調整predict的輸出。請同學試試看。
?predict.svm
根據說明文件,如果我們想要的不只是預測的類別結果,而是決定類別的分數,可以透過decision.values這個參數。請同學試試看:predict(g,iris,decision.values=TRUE)
predict(g, iris, decision.values = TRUE)
最後我們請同學再拿mlbench套件的Ionosphere資料集做練習,挑戰更低的logloss。
check_then_install("mlbench", "2.1.1")
library(mlbench)
# 方便起見,同學可以使用這個函數計算 Logarithmic Loss
logloss <- function(y, p, tol = 1e-4) {
# tol 的用途是避免對0取log所導致的數值問題
p[p < tol] <- tol
p[p > 1 - tol] <- 1 - tol
-sum(y * log(p) + (1 - y) * log(1-p))
}
data(Ionosphere)
test.i <- c(4L, 6L, 9L, 13L, 14L, 22L, 31L, 33L, 50L, 52L, 61L, 63L, 68L,
79L, 91L, 99L, 119L, 135L, 154L, 155L, 160L, 162L, 166L, 194L,
200L, 219L, 233L, 236L, 237L, 242L, 244L, 248L, 250L, 257L, 261L,
276L, 278L, 283L, 292L, 310L, 312L, 315L, 319L, 323L, 325L, 327L,
335L, 337L, 338L, 344L)
df.test <- Ionosphere[test.i,-2] # remove V2
train.i <- setdiff(seq_len(nrow(Ionosphere)), test.i)
df.train <- Ionosphere[train.i,-2]
logloss2 <- function(answer_04) {
p <- predict(answer_04, df.test, probability = TRUE)
logloss(df.test$Class == "good", attr(p, "probabilities")[,"good"])
}
# 請利用e1071的svm函數,透過調整參數,建立一個logloss小於4的模型
answer_04 <- local({
# NULL
# 你的程式碼應該很類似以下的程式碼:
svm(Class ~ ., df.train, probability = TRUE)
})
stopifnot("svm" %in% class(answer_04))
if (interactive()) {
stopifnot(local({
p <- predict(answer_04, df.test, probability = TRUE)
logloss(df.test$Class == "good", attr(p, "probabilities")[,"good"]) < 4
}))
}