支持向量機是一個相對較新和較先進的機器學習技術,最初提出是爲了解決二類分類問題,如今被普遍用於解決多類非線性分類問題和迴歸問題。繼續閱讀本文,你將學習到支持向量機如何工做,以及如何利用R語言實現支持向量機。git
支持向量機如何工做?
簡單介紹下支持向量機是作什麼的:github
假設你的數據點分爲兩類,支持向量機試圖尋找最優的一條線(超平面),使得離這條線最近的點與其餘類中的點的距離最大。有些時候,一個類的邊界上的點可能越過超平面落在了錯誤的一邊,或者和超平面重合,這種狀況下,須要將這些點的權重下降,以減少它們的重要性。dom
這種狀況下,「支持向量」就是那些落在分離超平面邊緣的數據點造成的線。機器學習
沒法肯定分類線(線性超平面)時該怎麼辦?
此時能夠將數據點投影到一個高維空間,在高維空間中它們可能就變得線性可分了。它會將問題做爲一個帶約束的最優化問題來定義和解決,其目的是爲了最大化兩個類的邊界之間的距離。函數
個人數據點多於兩個類時該怎麼辦?
此時支持向量機仍將問題看作一個二元分類問題,但此次會有多個支持向量機用來兩兩區分每個類,直到全部的類之間都有區別。學習
工程實例
讓咱們看一下如何使用支持向量機實現二元分類器,使用的數據是來自MASS包的cats數據集。在本例中你將嘗試使用體重和心臟重量來預測一隻貓的性別。咱們拿數據集中20%的數據點,用於測試模型的準確性(在其他的80%的數據上創建模型)。測試
1
2
3
4
|
# Setup
library(e1071)
data(cats, package="MASS")
inputData <- data.frame(cats[, c (2,3)], response = as.factor(cats$Sex)) # response as factor
|
線性支持向量機
傳遞給函數svm()的關鍵參數是kernel、cost和gamma。Kernel指的是支持向量機的類型,它多是線性SVM、多項式SVM、徑向SVM或Sigmoid SVM。Cost是違反約束時的成本函數,gamma是除線性SVM外其他全部SVM都使用的一個參數。還有一個類型參數,用於指定該模型是用於迴歸、分類仍是異常檢測。可是這個參數不須要顯式地設置,由於支持向量機會基於響應變量的類別自動檢測這個參數,響應變量的類別多是一個因子或一個連續變量。因此對於分類問題,必定要把你的響應變量做爲一個因子。優化
1
2
3
4
5
6
|
# linear SVM
svmfit <- svm(response ~ ., data = inputData, kernel = "linear", cost = 10, scale = FALSE) # linear svm, scaling turned OFF
print(svmfit)
plot(svmfit, inputData)
compareTable <- table (inputData$response, predict(svmfit)) # tabulate
mean(inputData$response != predict(svmfit)) # 19.44% misclassification error
|
徑向支持向量機
徑向基函數做爲一個受歡迎的內核函數,能夠經過設置內核參數做爲「radial」來使用。當使用一個帶有「radial」的內核時,結果中的超平面就不須要是一個線性的了。一般定義一個彎曲的區域來界定類別之間的分隔,這也每每致使相同的訓練數據,更高的準確度。spa
1
2
3
4
5
6
|
# radial SVM
svmfit <- svm(response ~ ., data = inputData, kernel = "radial", cost = 10, scale = FALSE) # radial svm, scaling turned OFF
print(svmfit)
plot(svmfit, inputData)
compareTable <- table (inputData$response, predict(svmfit)) # tabulate
mean(inputData$response != predict(svmfit)) # 18.75% misclassification error
|
尋找最優參數
你可使用tune.svm()函數,來尋找svm()函數的最優參數。code
1
2
3
4
5
6
7
8
9
10
|
### Tuning
# Prepare training and test data
set.seed(100) # for reproducing results
rowIndices <- 1 : nrow(inputData) # prepare row indices
sampleSize <- 0.8 * length(rowIndices) # training sample size
trainingRows <- sample (rowIndices, sampleSize) # random sampling
trainingData <- inputData[trainingRows, ] # training data
testData <- inputData[-trainingRows, ] # test data
tuned <- tune.svm(response ~., data = trainingData, gamma = 10^(-6:-1), cost = 10^(1:2)) # tune
summary (tuned) # to select best gamma and cost
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# Parameter tuning of 'svm':
# - sampling method: 10-fold cross validation
#
# - best parameters:
# gamma cost
# 0.001 100
#
# - best performance: 0.26
#
# - Detailed performance results:
# gamma cost error dispersion
# 1 1e-06 10 0.36 0.09660918
# 2 1e-05 10 0.36 0.09660918
# 3 1e-04 10 0.36 0.09660918
# 4 1e-03 10 0.36 0.09660918
# 5 1e-02 10 0.27 0.20027759
# 6 1e-01 10 0.27 0.14944341
# 7 1e-06 100 0.36 0.09660918
# 8 1e-05 100 0.36 0.09660918
# 9 1e-04 100 0.36 0.09660918
# 10 1e-03 100 0.26 0.18378732
# 11 1e-02 100 0.26 0.17763883
# 12 1e-01 100 0.26 0.15055453
|
結果證實,當cost爲100,gamma爲0.001時產生最小的錯誤率。利用這些參數訓練徑向支持向量機。
1
2
3
4
5
|
svmfit <- svm (response ~ ., data = trainingData, kernel = "radial", cost = 100, gamma=0.001, scale = FALSE) # radial svm, scaling turned OFF
print(svmfit)
plot(svmfit, trainingData)
compareTable <- table (testData$response, predict(svmfit, testData)) # comparison table
mean(testData$response != predict(svmfit, testData)) # 13.79% misclassification error
|
1
2
3
|
F M
F 6 3
M 1 19
|
網格圖
一個2-色的網格圖,能讓結果看起來更清楚,它將圖的區域指定爲利用SVM分類器獲得的結果的類別。在下邊的例子中,這樣的網格圖中有不少數據點,而且經過數據點上的傾斜的方格來標記支持向量上的點。很明顯,在這種狀況下,有不少越過邊界違反約束的點,但在SVM內部它們的權重都被下降了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# Grid Plot
n_points_in_grid = 60 # num grid points in a line
x_axis_range <- range (inputData[, 2]) # range of X axis
y_axis_range <- range (inputData[, 1]) # range of Y axis
X_grid_points <- seq (from=x_axis_range[1], to=x_axis_range[2], length=n_points_in_grid) # grid points along x-axis
Y_grid_points <- seq (from=y_axis_range[1], to=y_axis_range[2], length=n_points_in_grid) # grid points along y-axis
all_grid_points <- expand.grid (X_grid_points, Y_grid_points) # generate all grid points
names (all_grid_points) <- c("Hwt", "Bwt") # rename
all_points_predited <- predict(svmfit, all_grid_points) # predict for all points in grid
color_array <- c("red", "blue")[as.numeric(all_points_predited)] # colors for all points based on predictions
plot (all_grid_points, col=color_array, pch=20, cex=0.25) # plot all grid points
points (x=trainingData$Hwt, y=trainingData$Bwt, col=c("red", "blue")[as.numeric(trainingData$response)], pch=19) # plot data points
points (trainingData[svmfit$index, c (2, 1)], pch=5, cex=2) # plot support vectors
|