[譯] 用 Scikit-Learn 實現 SVM 和 Kernel SVM

支持向量機(SVM)是一種監督學習分類算法。支持向量機提出於 20 世紀 60 年代在 90 年代獲得了進一步的發展。然而,因爲能取得很好的效果,最近纔開始變得特別受歡迎。與其餘機器學習算法相比,SVM 有其獨特之處。前端

本文先簡明地介紹支持向量機背後的理論和如何使用 Python 中的 Scikit-Learn 庫來實現。而後咱們將學習高級 SVM 理論如 Kernel SVM,一樣會使用 Scikit-Learn 來實踐。python

簡單 SVM

考慮二維線性可分數據,如圖 1,典型的機器學習算法但願找到使得分類錯誤最小的分類邊界。若是你仔細看圖 1,會發現能把數據點正確分類的邊界不惟一。兩條虛線和一條實線都能正確分類全部點。android

Multiple Decision Boundaries

圖 1:多決策邊界ios

SVM 經過最大化全部類中的數據點到決策邊界的最小距離的方法來肯定邊界,這是 SVM 和其餘算法的主要區別。SVM 不僅是找一個決策邊界;它能找到最優決策邊界。git

能使全部類到決策邊界的最小距離最大的邊界是最優決策邊界。如圖 2 所示,那些離決策邊界最近的點被稱做支持向量。在支持向量機中決策邊界被稱做最大間隔分類器,或者最大間隔超平面。github

Decision Boundary with Support Vectors

圖 2:決策邊界的支持向量算法

尋找支持向量、計算決策邊界和支持向量之間的距離和最大化該距離涉及到很複雜的數學知識。本教程不打算深刻到數學的細節,咱們只會看到如何使用 Python 的 Scikit-Learn 庫來實現 SVM 和 Kernel-SVM。後端

經過 Scikit-Learn 實現 SVM

咱們將使用和決策樹教程同樣的數據。bash

咱們的任務是經過四個屬性來判斷紙幣是否是真的,四個屬性是小波變換圖像的偏度、圖像的方差、圖像的熵和圖像的曲率。咱們將使用 SVM 解決這個二分類問題。剩下部分是標準的機器學習流程。機器學習

導入庫

下面的代碼導入全部須要的庫:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
複製代碼

導入數據

數據能夠從下面的連接下載:

drive.google.com/file/d/13nw…

數據的詳細信息能夠參考下面的連接:

archive.ics.uci.edu/ml/datasets…

從 Google drive 連接下載數據並保存在你本地。這個例子中數據集保存在我 Windows 電腦的 D 盤 「Datasets」 文件夾下的 CSV 文件裏。下面的代碼從文件路徑中讀取數據。你能夠根據文件在你本身電腦上的路徑修改。

讀取 CSV 文件的最簡單方法是使用 pandas 庫中的 read_csv 方法。下面的代碼讀取銀行紙幣數據記錄到 pandas 的 dataframe:

bankdata = pd.read_csv("D:/Datasets/bill_authentication.csv")
複製代碼

探索性數據分析

使用 Python 中各類各樣的庫幾乎能夠完成全部的數據分析。爲了簡單起見,咱們只檢查數據的維數並查看最前面的幾條記錄。查看數據的行數和列數,執行下面的語句:

bankdata.shape
複製代碼

你將看到輸出爲(1372, 5)。這意味着數據集有 1372 行和 5 列。

爲了對數據長什麼樣有個直觀感覺,能夠執行下面的命令:

bankdata.head()
複製代碼

輸出下面以下:

你能夠發現全部的屬性都是數值型。類別標籤也是數值型即 0 和 1。

數據預處理

數據預處理包括(1)把屬性和類表標籤分開和(2)劃分訓練數據集和測試數據集。

把屬性和類別標籤分開,執行下面的代碼:

X = bankdata.drop('Class', axis=1)
y = bankdata['Class']
複製代碼

上面代碼第一行從 bankdata dataframe 中移除了類別標籤列 「Class」 並把結果賦值給變量 X。函數 drop() 刪除指定列。

第二行,只將類別列存儲在變量 y 裏。如今變量 X 包含全部的屬性變量 y 包含對應的類別標籤。

如今數據集已經將屬性和類別標籤分開,最後一步預處理是劃分出訓練集和測試集。幸運的是 Scikit-Learn 中 model_selection 模塊提供了函數 train_test_split 容許咱們優雅地把數據分紅訓練和測試兩部分。

執行下面的代碼完成劃分:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)
複製代碼

算法訓練

咱們已經把數據分紅了訓練集和測試集。如今咱們使用訓練集來訓練。Scikit-Learn 庫中的 svm 模塊實現了各類不一樣的 SVM 算法。因爲咱們要完成一個分類任務,咱們將使用由 Scikit-Learn 中 svm 模塊下的 SVC 類實現的支持向量分類器。這個類須要一個參數指定核函數的類型。這參數很重要。這裏考慮最簡單的 SVM 把類型參數設爲 linear 線性支持向量機只適用於線性可分數據。咱們在下一部分介紹非線性核。

把訓練數據傳給 SVC 類 fit 方法來訓練算法。執行下面的代碼完成算法訓練:

from sklearn.svm import SVC
svclassifier = SVC(kernel='linear')
svclassifier.fit(X_train, y_train)
複製代碼

作預測

SVC 類的 predict 方法能夠用來預測新的數據的類別。代碼以下:

y_pred = svclassifier.predict(X_test)
複製代碼

算法評價

混淆矩陣、精度、召回率和 F1 是分類任務最經常使用的一些評價指標。Scikit-Learn 的 metrics 模塊中提供了 classification_reportconfusion_matrix 等方法,這些方法能夠快速的計算這些評價指標。

下面是計算評價指標的代碼:

from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test,y_pred))
print(classification_report(y_test,y_pred))
複製代碼

結果

下面是評價結果:

[[152    0]
 [  1  122]]
              precision   recall   f1-score   support

           0       0.99     1.00       1.00       152
           1       1.00     0.99       1.00       123

avg / total        1.00     1.00       1.00       275
複製代碼

從上面的評價結果中咱們能夠發現 SVM 比決策樹稍微的要好。SVM 只有 1% 的錯分類而決策樹有 4%。

Kernel SVM

在上面的章節咱們看到了如何使用簡單 SVM 算法在線性可分數據上找到決策邊界。然而,當數據不是線性可分的時候如圖 3,直線就不能再做爲決策邊界了。

Non-linearly Separable Data

Fig 3: 非線性可分數據

對非線性可分的數據集,簡單的 SVM 算法就再也不適用。一種改進的 SVM 叫作 Kernel SVM 能夠用來解決非線性可分數據的分類問題。

從根本上說,kernel SVM 把在低維空間中線性不可分數據映射成在高維空間中線性可分的數據, 這樣不一樣類別的數據點就分佈在了不一樣的維度上。一樣,這裏涉及到複雜的數學,可是若是你只是使用 SVM 徹底不用擔憂。咱們能夠很簡單的使用 Python 的 Scikit-Learn 庫來實現和使用 kernel SVM。

使用 Scikit-Learn 實現 Kernel SVM

和實現簡單的 SVM 同樣。在這部分咱們使用有名的鳶尾花數據集,依照植物下面的四個屬性去預測它屬於哪一個分類:萼片寬度,萼片長度,花瓣寬度和花瓣長度。

數據能夠從下面的連接下:

archive.ics.uci.edu/ml/datasets…

剩下的步驟就是典型的機器學習步驟在訓練 Kernel SVM 以前咱們須要一些簡單說明。

導入庫

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
複製代碼

導入數據

url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"

# Assign colum names to the dataset
colnames = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'Class']

# Read dataset to pandas dataframe
irisdata = pd.read_csv(url, names=colnames)
複製代碼

預處理

X = irisdata.drop('Class', axis=1)
y = irisdata['Class']
複製代碼

訓練和測試集劃分

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)
複製代碼

算法訓練

一樣使用 Scikit-Learn 的 svm 模塊中的 SVC 類。區別在於類 SVC 的核函數類型參數的值不同。在簡單 SVM 中咱們使用的核函數類型是 「linear」。然而,kernel SVM 你可使用 高斯、多項式、sigmoid或者其餘可計算的核。咱們將實現多項式、高斯和 sigmoid 核並檢驗哪個表現更好。

1. 多項式核

多項式核的狀況下,你開須要傳遞一個叫degree 的參數給SVC 類。這個參數是多項式的次數。看下面的代碼如何實現多項式覈實現 kernel SVM:

from sklearn.svm import SVC
svclassifier = SVC(kernel='poly', degree=8)
svclassifier.fit(X_train, y_train)
複製代碼

作預測

如今咱們已經訓練好了算法,下一步是在測試集上作預測。

運行下面的代碼來實現:

y_pred = svclassifier.predict(X_test)
複製代碼

算法評價

一般機器學習算法的最後一步是評價多項式核。運行下面的代碼。

from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
複製代碼

使用多項式核的 kernel SVM 的輸出以下:

[[11  0  0]
 [ 0 12  1]
 [ 0  0  6]]
                 precision   recall   f1-score   support

    Iris-setosa       1.00     1.00       1.00        11
Iris-versicolor       1.00     0.92       0.96        13  
 Iris-virginica       0.86     1.00       0.92         6

    avg / total       0.97     0.97       0.97        30
複製代碼

如今讓咱們使用高斯和 sigmoid 核來重複上面的步驟。

2. 高斯核

看一眼咱們是如何使用高斯覈實現 kernel SVM 的:

from sklearn.svm import SVC
svclassifier = SVC(kernel='rbf')
svclassifier.fit(X_train, y_train)
複製代碼

使用高斯核,你必須指定類 SVC 的核參數額值爲 「rbf」。

預測和評價

y_pred = svclassifier.predict(X_test)
複製代碼
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
複製代碼

使用高斯核的輸出:

[[11  0  0]
 [ 0 13  0]
 [ 0  0  6]]
                 precision   recall   f1-score   support

    Iris-setosa       1.00     1.00       1.00        11
Iris-versicolor       1.00     1.00       1.00        13  
 Iris-virginica       1.00     1.00       1.00         6

    avg / total       1.00     1.00       1.00        30
複製代碼

3. Sigmoid 核

最後,讓咱們使用 sigmoid 覈實現 Kernel SVM。看下面的代碼:

from sklearn.svm import SVC
svclassifier = SVC(kernel='sigmoid')
svclassifier.fit(X_train, y_train)
複製代碼

使用 sigmoid 核須要指定 SVC 類的參數 kernel 的值爲 「sigmoid」。

預測和評價

y_pred = svclassifier.predict(X_test)
複製代碼
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
複製代碼

使用 Sigmoid 核的輸出以下:

[[ 0  0 11]
 [ 0  0 13]
 [ 0  0  6]]
                 precision   recall   f1-score   support

    Iris-setosa       0.00     0.00       0.00        11
Iris-versicolor       0.00     0.00       0.00        13  
 Iris-virginica       0.20     1.00       0.33         6

    avg / total       0.04     0.20       0.07        30
複製代碼

對比核的表現

對比發現 sigmoid 核是最差的。由於 sigmoid 返回 0 和 1 兩個值,sigmoid 核更適合二分類問題。而咱們的例子中有三個類別。

高斯核與多項式核有差很少的表現。高斯核預測準確率 100% 多項式核也只有 1% 的偏差。高斯核表現稍好。然而沒有硬性的規則來評價哪一種核函數在任何場景下都更好。只能經過在測試集上的測試結果來選擇哪個核在你的數據集上表現更好。

資源

是否想學習更多的 Scikit-Learn 和的機器學習算法相關知識?我推薦你查看更多的資料,如在線課程:

總結

本文咱們學習了基本的 SVM 和 kernel SVMs。還了解了 SVM 算法背後的直覺以及如何使用 Python 庫 Scikit-Learn 來實現。咱們也學習了使用不一樣類型的核來實現 SVM。我猜你已經想把這些算法應用到真實的數據上了好比 kaggle.com

最後我仍是建議你去詳細瞭解下 SVM 背後的數學。雖然若是隻使用 SVM 算法並不須要瞭解那些數學,但要理解算法是如何找到決策邊界的數學會頗有幫助。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索