【機器學習與R語言】9- 支援向量機
阿新 • • 發佈:2020-09-09
目錄
1.理解支援向量機(SVM)
1)SVM特點
- 支援向量機和神經網路都是“黑箱模型”的代表:潛在的模型基於複雜的數學系統,而且結果難以解釋。
- SVM的目標是建立一個平面邊界(“超平面”),使得任何一邊的資料劃分都是均勻的。結合了kNN和線性迴歸。
- 幾乎適用於所有的學習任務,包括分類和數值預測。
2)用超平面分類
- 線性可分:可以由一條直線或一個平面進行劃分
- 最大間隔超平面(MMH):很多線都能對資料點進行分類,但要尋找能使類形成最大間隔的那條線(因為在邊界附近點位置的微小變化可能導致某些點落線上之外),支援向量就是每個類中最接近最大間隔超平面的點。所以單獨使用支援向量,就能定義最大間隔超平面。
- 線性可分條件下,最大間隔超平面要儘可能遠離兩組資料點的外邊界(“凸包”),最大間隔超平面就是兩個凸包之間的最短距離直線的垂直平分線,可通過“二次優化”演算法實現。
- 非線性可分:資料不是線性可分的條件下,使用一個“鬆弛變數”來建立一個軟間隔,允許一些點落線上不正確的一邊。
- 非線性可分中的成本引數C:即所有違反約束的點,試圖使總成本最小,而非尋找最大間隔。修改C將調整對於落在超平面錯誤一邊的案例的懲罰。C越大,實現100%分離的優化就越困難。較小的C將把重點放在更寬的整體邊緣。
3)對非線性空間使用核函式
- 另一種處理非線性問題的方法,就是使用“核技巧”的處理將問題對映到一個更高維的空間,這樣非線性關係可能會變為完全線性。
- 從本質上講,核技巧涉及一個新增能夠表述度量特徵之間數學關係新特徵的過程。
- 非線性核SVM的特點:
- 核函式:線性核函式(特徵的點積),多項式核函式(加一個非線性資料變換),S形核函式(類似神經網路的S形啟用函式),高斯RBF核函式(類似RBF神經網路)。多數情況下,核函式的選擇是任意的,因為效能可能只有輕微的變化。
2. 支援向量機應用示例
使用SVM進行光學字元識別(OCR影象處理):通過將印刷或手寫文字轉換為電子形式,儲存在資料庫種來處理紙質檔案。
難點:
- 影象的規則模式很難嚴格定義
- 影象資料往往是噪聲資料
1)收集資料
資料集包含26個大寫英文字母的2000個案例,使用20種不同的隨機重塑和扭曲的黑斯和白色字型印刷。
假設當影象字元被掃描到計算機,轉換為畫素,有16個統計屬性(如水平垂直尺寸,黑色畫素比例等)。
資料下載:
連結: https://pan.baidu.com/s/1q8zHWkMZcapwnX90PA4hOg 提取碼: eaqt
2)探索和準備資料
SVM需要所有特徵都是數值型的,而且每一個特徵需要縮小到一個相當小的區間內。所以不要有因子,而且要做標準化。這裡略過沒做。
## Example: Optical Character Recognition ----
## Step 2: Exploring and preparing the data ----
# read in data and examine structure
letters <- read.csv("letterdata.csv")
str(letters)
# divide into training and test data
letters_train <- letters[1:16000, ] #80%
letters_test <- letters[16001:20000, ] #20%
3)訓練資料
SVM的R包有e1071,klaR和kernlab
等,這裡用kernlab(與caret連用,允許SVM使用各種自動化方法進行訓練和評估)。
kernlab::ksvm(target~predictors,
data=mydata,
kernel="rbfdot", #隱非線性對映,rbfdot/polydot/tanhdot/vanilladot
c=1) #違法約束條件的懲罰,較大的c值導致較窄的邊界
訓練:
## Step 3: Training a model on the data ----
# begin by training a simple linear SVM
library(kernlab)
letter_classifier <- ksvm(letter ~ ., data = letters_train,
kernel = "vanilladot") #預設使用高斯RBF核函式,這裡用線性函式
# look at basic information about the model
letter_classifier
4)評估模型
letter_predictions <- predict(letter_classifier, letters_test)
head(letter_predictions)
table(letter_predictions, letters_test$letter)
# look only at agreement vs. non-agreement
# construct a vector of TRUE/FALSE indicating correct/incorrect predictions
agreement <- letter_predictions == letters_test$letter
table(agreement)
prop.table(table(agreement))
識別的準確度大概為84%。
5)提高效能
可以使用一個更復雜的核函式,將資料對映到更高維的空間,獲得一個較好的模型擬合度。如試試高斯RF核函式,或者修改成本約束引數C值來修正決策邊界的寬度。
## Step 5: Improving model performance ----
set.seed(12345)
letter_classifier_rbf <- ksvm(letter ~ ., data = letters_train, kernel = "rbfdot") #高斯RBF核函式
letter_predictions_rbf <- predict(letter_classifier_rbf, letters_test)
agreement_rbf <- letter_predictions_rbf == letters_test$letter
table(agreement_rbf)
prop.table(table(agreement_rbf))
訓練時間更長,將準確度提高到了93%。