Support Vector Regression (SVR)
林朕陞
2021-5-24
概要:SVR是由SVM的擴充版本,能夠處理依變數(dependent variable)是連續的預測問題。在e1071套件中,我們須注意並沒有一個函數為svr(),而是同樣使用svm()。差別只在於:
- 若依變數的類型是factor時,svm()會建立SVM的超平面(hyperplane),來處理分類的問題。
- 若依變數的類型是numeric時,svm()會自動轉為SVR,進行連續值的預測。
我會一步步教導同學操作SVR演算法。
內容:
- 進行SVR之前,我們先建立一筆資料:
data = data.frame(x=1:30,
y=c(3,4,8,2,6,10,12,13,15,14,17,18,20,17,21,22,25,30,29,31,30,32,30,33,34,32,35,36,34,40))
# 資料的原始值
plot(data$x, data$y, pch=16, xlab="X", ylab="Y",col="blue")
- 先畫一條簡單的線性迴歸:
model <- lm(y ~ x , data)
# lm預測
lm.pred = predict(model, data)
# 資料的原始值(黑點)
plot(data$x, data$y, pch=16, xlab="X", ylab="Y",col="blue")
# lm的預測值(紅三角形)
points(lm.pred, pch=2, col="red")
abline(model, col="red")
- 我們直接用SVR來建模及預測:
#安裝e1071套件 install.packages("e1071")
library(e1071)
#執行SVR模型
model <- svm(y ~ x , data, kernel ="radial", cost=20, scale=FALSE) # 依變數的類型必須是numeric
# 預測
svr.pred = predict(model, data)
# 資料的原始值(藍點)
plot(data$x, data$y, pch=16, xlab="X", ylab="Y",col="blue")
# SVR的預測值(黑叉)
points(svr.pred, pch=4, col="black")
- 最後,比較一下線性迴歸(lm)和支持向量迴歸(SVR)的預測表現。
# 資料的原始值(藍點)
plot(data$x, data$y, pch=16, xlab="X", ylab="Y",col="blue")
# lm的預測值(紅三角形)
points(lm.pred, pch=2, col="red")
# SVR的預測值(黑叉)
points(svr.pred, pch=4, col="black")
# (lm, SVR) models in RMSE
c(sqrt(mean((data$y - lm.pred)^2)), sqrt(mean((data$y - svr.pred)^2)))
## [1] 2.2084589 0.1000378
- 可以發現到,在這個例子中,SVR比lm的預測評比還要好很多(0.100 < 2.208)。
參數討論:
前面的SVR,我們都是用預設的參數來建模,並且都得到還不錯的結果,主要是我們的資料並不複雜。 但是在實際資料中,幾乎不可能發生。所以我們必須了解SVR裡面的參數,了解它們的意義,了解如何有效率地調校(tune)它們,讓模型既不會發生overfitting,同時表現合乎預期。在SVR,同時也是e1071套件裡的svm()裡面,有兩個最重要的參數值得關注:(cost, epsilon)。
svm(...
type = 決定svR是要用來classification(類別)、還是regression(連續)。
scale = 將資料正規化成(平均值, 標準差) = (0,1) 的分佈。
kernel = 將資料由低維度映射到高維度特徵空間的kernel-function,用來處理「非線性可分」的問題。
cost = 懲罰參數,在Lagrange formulation中的大C,決定給被分錯的資料「多少」懲罰值。
epsilon = margin of tolerance。越大,表示在容忍範圍內被分錯的資料,不會被懲罰;反之,越接近0,每一個被分錯的資料都會被懲罰,此參數扮演極重要的角色。
gamma = 在kernel-function裡面的參數(linear-function除外)。
...
)
更多設定請參考R的官方e1071套件手冊PP.52~60 https://cran.r-project.org/web/packages/e1071/e1071.pdf
# tune cost and epsilon in SVR
tune.model = tune(svm, y~x, data=data, kernel ="radial", scale=FALSE, range=list(cost=2^(1:10), epsilon = seq(0,1,0.1)) )
# 調校參數的最主要一行
tune.model
##
## Parameter tuning of 'svm':
##
## - sampling method: 10-fold cross validation
##
## - best parameters:
## cost epsilon
## 32 0
##
## - best performance: 46.82352
這裡有兩個重點:
- 在訓練的過程中,我們訓練的是一堆模型,包含cost=2^1, 2^2, … 2^10,epsilon=0, 0.1, 0.2, 0.3,……,1,這兩種參數的排列組合,換句話說,會有10x11=110個SVR模型。
- 裡面的值是mean squared error。
plot(tune.model)
同學可注意這張圖的分層很有意思,隨著epsilon越高,模型的表現越糟(顏色越淺)。同時它也希望cost愈低愈好(顏色越深),所以最後得出的最佳參數組合: cost=32, epsilon=0。
最後,要挑出表現最佳的模型,可以直接從tune()回傳的結果中取出($best.model)。
# Best model in set of tuning models
tune.model$best.model
##
## Call:
## best.tune(method = svm, train.x = y ~ x, data = data, ranges = list(cost = 2^(1:10),
## epsilon = seq(0, 1, 0.1)), kernel = "radial", scale = FALSE)
##
##
## Parameters:
## SVM-Type: eps-regression
## SVM-Kernel: radial
## cost: 32
## gamma: 1
## epsilon: 0
##
##
## Number of Support Vectors: 30
- 我們使用剛才的最佳參數組合,進行SVR的建模及預測:
#執行SVR模型
model <- svm(y ~ x , data, kernel ="radial", cost=32, epsilon=0, scale=FALSE)
# 預測
svr.pred = predict(model, data)
# (lm, SVR) models in RMSE
c(sqrt(mean((data$y - lm.pred)^2)), sqrt(mean((data$y - svr.pred)^2)))
## [1] 2.2084589235 0.0002449839
- 可以發現到,在本次的參數調校中,SVR比lm的預測評比好非常的多(0.0002 < 2.208)。
總結:
SVR是資料科學中最重要的演算法之一,它同時具有機器學習和統計理論的優點,在分類及預測的問題上都表現的很不錯。但要充分發揮SVR的長處,需要將其中的許多細節(參數)知道得十分清楚,同時具有對資料的敏銳度才行,包括kernel-function的選擇,都需要經驗累積,但非常值得同學花時間好好靜下來學習。