關卡 1

這個單元,我們要介紹如何在R使用SVM(SpportVectorMachine)。

關卡 2

在世界上,SVM(SupportVectorMachine)最有名的實作之一,就是出自台灣大學資工系林智仁老師實驗室的libsvm套件。R的e1071套件則是libsvm的wrapper,讓我們可以直接透過e1071讓libsvm的核心幫我們解出SVM的模型。請同學安裝這個套件。

check_then_install("e1071", "1.6.7")

關卡 3

請同學載入e1071套件

library(e1071)

關卡 4

請同學輸入:vignette(package="e1071")檢查e1071上的vignette清單。

vignette(package = "e1071")

關卡 5

請同學輸入:vignette("svmdoc",package="e1071")打開名稱為svmdoc的vignette。這份文件很清楚的介紹了SVM演算法、和e1071相關的各種變形、原理,以及對應的參數。

vignette("svmdoc", package = "e1071")

關卡 6

再來請同學輸入?svm打開svm的說明文件。

?svm

關卡 7

由於svm有formulainterface,所以我們可以簡單利用g<-svm(Species~.,iris)馬上學出一個svm的模型。

g <- svm(Species ~ ., iris)

關卡 8

svm在學習時,可以依據應用解決不同的問題。這取決於目標的型態。舉例來說,如果我們使用svm(Species~.,iris),這裡的預測目標就是iris$Species這個變數了。請問同學,這個變數的型態(class)是什麼?

class(iris$Species)

關卡 9

由於預測的目標是一個類別變數,所以R會自動使用classification的模式來解決問題。svm中支援的模式列在說明文件的Arguments項目下的type參數之中。

關卡 10

至於kernel參數則可以讓svm學習出資料中非線性的模式。不同的kernel也可以透過不同的額外參數來調整。所有的細節,都可以在?svm打開的說明文件中找到。

關卡 11

依照說明文件,degree參數是用於哪一種kernel?

polynomial

關卡 12

預測也是很直接的使用predict(g,iris)就可以了,請同學試試看。

predict(g, iris)

關卡 13

由於e1071套件是使用S3物件導向的系統,所以我們可以利用?predict.svm打開說明文件,查閱如何調整predict的輸出。請同學試試看。

?predict.svm

關卡 14

根據說明文件,如果我們想要的不只是預測的類別結果,而是決定類別的分數,可以透過decision.values這個參數。請同學試試看:predict(g,iris,decision.values=TRUE)

predict(g, iris, decision.values = TRUE)

關卡 15

最後我們請同學再拿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
  }))
}