【技術翻譯】支持向量機簡明教程及其在python和R下的調參
原文: Simple Tutorial on SVM and Parameter Tuning in Python and R
介紹
數據在機器學習中是重要的一種任務,支持向量機(SVM)在模式分類和非線性回歸問題中有著廣泛的應用. SVM最開始是由N. Vapnik and Alexey Ya. Chervonenkis
在1963年提出。從那時候開始,各種支持向量機被成功用於解決各種現實問題,比如文本聚類,圖像分類,生物信息學(蛋白質分類,癌癥分類),手寫字符識別等等.
內容
1. 什麽是支持向量機(support vector machine)?
2. 支持向量機如何工作?
3. 支持向量機的推導
4. 支持向量機的優點和缺點
5. Python和R下的支持向量機實現
什麽是支持向量機?
支持向量機是一種可以用來解決分類問題和回歸問題的監督式機器學習算法. 它使用一種叫做核方法(kernel trick)的技術來對數據進行轉換,
基於這些轉換,它在各種可能的解中找到最優的邊界.
簡而言之, 為了根據數據標簽將數據分開來,SVM對數據進行一些很復雜的轉換. 這篇文章,我們只會討論SVM的分類算法.
支持向量機如何工作?
要了解SVM如何工作最主要的是了解最大化訓練數據間隔的最優分隔超平面(optimal separating hyperplane)
什麽是分類超平面?
對於上面那幅圖,我們是能夠分開那些數據的. 比如我們可以在數據中間畫一條線, 線下面全是綠色數據點,線上面全是紅色數據點.
那麽問題來了,它明明是條線,你為什麽叫它超平面呢?
在上面的圖中, 我們僅僅考慮了最簡單的情形,數據分布於2-維平面. 然而SVM在一般的n-維空間也能工作. 而在更高維空間, 超平面是平面的一般情況.
比如:
1 維數據,一個點代表著超平面
2 維數據,一條線代表著超平面
3 維數據,一個平面代表著超平面
對於更高維數據,就叫做超平面
前面我們提到,SVM的目標是找到最優分隔超平面. 那麽什麽樣的超平面才是最優的呢?事實是存在分隔超平面並不一定代表它就是最優的.
下面我們通過幾張圖來理解這個問題.
1. 很多超平面
下圖中有很多超平面,那個才是分隔超平面呢?很容易看出線B 是能夠很好區分兩個類的超平面.
2. 很多分隔超平面
也可能出現有多個分隔超平面的情況. 我們如何找到最優分隔超平面呢, 直觀上來說,如果我們選擇了一個距離一類點很近的超平面,那麽它的泛化能力肯定不是很好. 所以要找到距離各個類中的點都盡可能元的超平面.
在上圖中,最優超平面就是超平面B.
因此, 最大化每一類中距離超平面最近的點和超平面之間的距離,就能得到最優分隔超平面. 這個距離被稱作: 邊界(margin).
SVM的目標就是找到最優超平面, 因為它不僅僅可以對現有的數據分類,也能夠對未知的數據進行預測. 最優超平面也就是有著最大邊界(margin)的超平面.
數學推導
現在我們已經大概了解了算法背後的基本概念,接下來我們看看SVM的數學推導
我假設你已經對基本的向量,向量代數,數學,正交投影有了基本的了解. 這些概念都可以在這篇文章中有介紹: 機器學習中的線性代數
超平面方程
你肯定知道直線方程可以是: $y = mx + c$, m是直線的斜率, c是直線的y軸截距.
更一般的超平面的方程如下:
$$W^Tx = 0$$
式中, $x$和$w$是向量, $W^Tx$,代表向量的點積, $W$通常被稱為權向量.
對於上面的直線$y - mx -c = 0$. 在這種情況下:
$w = \begin{pmatrix}
-c\\
-m\\
1
\end{pmatrix}$
$x = \begin{pmatrix}
1\\
x\\
y
\end{matrix}$
$W^Tx = 0$
僅僅是同一樣東西的兩種不同表達. 那麽我們為什麽使用$W^Tx = 0$. 僅僅是因為在面對高維數據的時候,這種表達更好處理. $W$代表垂直平面的向量, 這種特性在我們計算點到超平面距離的時候很有用.
理解限制條件
在我們分類問題中的訓練數據是$\{(x_1,y_1), (x_2, y_2),...,(x_n,y_n)\}\in R^n * \{-1, 1\}.$ 這意味著訓練數據是一些$x_i$, n 維向量, $y_i$是$x_i$的標簽,$y_i$ = 1 意味著特征向量$x_i$屬於類別1,反之屬於類別 -1.
在一個分類問題中,我們試著找出一個函數 $y = f(x):R^n\rightarrow \{-1,1\}$,這個函數是從訓練數據學習得到. 然後我們用這個函數來預測未知數據的類別.
f(x)有無數種可能性,我們必須給他加一個限制條件,縮小f(x)的範圍. 在SVM的例子中, f(x) 必須滿足$W^Tx = 0$
也可以被表示為 $\vec{w}\cdot\vec{x} + b = 0; \vec{w} \in R^n and b \in R$
這將輸入空間分為兩個部分,一部分是-1類別,一部分是1類別
接下來的文章,我們會考慮2維向量,假設$H_0$是數據的分隔超平面,滿足以下條件:
$\vec{w}\cdot\vec{x} + b = 0 $
在有$H_0$情況下,我們可以選擇兩個其他的超平面$H_1$和$H_2$,他們也可以分隔數據且滿足以下方程:
$\vec{w}\cdot\vec{x} + b = -\ sigma $ $\vec{w}\cdot\vec{x} + b = \sigma $
這使得$H_0$到$H_1$和$H_2$的距離相等
變量$\sigma$的不確定的,因此我們可以令\sigma = 1來簡化問題.
$\vec{w}\cdot\vec{x} + b =-1 $ $\vec{w}\cdot\vec{x} + b = 1 $
接下來我們要確定這二者之間沒有其他點. 因此我們會選擇滿足以下限制條件的超平面, 對於每個向量$x_i$:
要麽:$對於屬於-1 類的x_i 來說 \vec{w} \cdot \vec{x} \leq -1$
要麽:$對於屬於 1類的x_i 來說 \vec{w} \cdot \vec{x} \geq 1$
上述限制條件可以整合到一個式子中:$y_i(\vec{w}\cdot\vec{x_i}) \geq 1 i \in [1,n]$
為了簡潔我們略去計算margin的推導: margin用m來表示:
$m = \frac{2}{||\vec{w}||}$
式子中的唯一變量就是$w$,因此最大化margin我們可以轉化為最小化$||\vec{w}||$, 優化目標可以轉化為以下:
$$Min \frac{||\vec{w}||}{2}$$
$$S.t. y_i(\vec{w} \cdot \vec{x_i}+b) \geq 1, 對於\forall i = 1,...,n$$
上面的式子在我們的數據是完全線性可分的時候是有效的,但是有些時候我們的數據並不是完全線性可分的,或者說數據由於受到噪聲的幹擾,即使線性可分,但是噪聲會使得找到的超平面並不是最優的.
對於這個問題我們引入松弛變量(slack variable), 允許一些點落到分類間隔之內,但是對於這些點我們進行一些懲罰:
在這種情況下,算法盡量使得松弛變量為0. 算法最小化的不是錯分類的綜述,而是最小化總的錯分距離.
限制條件現在變為:$y_i(\vec{w}\cdot\vec{x_i} + b) \geq 1- \varsigma_i, \forall 1 \geq i \leq n_i, \varsigma_i \geq 0$
優化目標變為:
參數$C$是正則化參數控制松弛變量大小和分類間隔大小的平衡.
小$C$會使得越過邊界的點更容易被忽視,從而使得邊界增大.
大$C$會使得越過邊界的點更難被忽視,從而使得邊界減小.
對於$C = \inf$, 所有的限制條件都是強制的.
對於2-維平面來說,最好的分類方式就是一條直線,對於3-維空間來說,最好的分類方式就會一個平面。但是並不是每次都能使用直線或者平面達到完美的分類,有時候我們需要用非線性區域來將類別分開.SVM使用核函數來解決這種非線性分類問題,核函數能夠將數據映射到一個不同的空間,在這個空間中,我們可以使用線性超平面將數據分開. 這種方法被稱為核方法.
假設 $\phi$是將$x_i$映射到$\phi(x)$的核函數,限制條件變為:
$$y_i(\vec{w}\cdot\vec{x_I} +b) \geq 1- \varsigma_i, \forall 1 \leq i \geq n, \varsigma_i \geq 0$$
優化目標變為:
這裏我們不深入如何去解這個優化問題,最常見解決這類問題的方法是凸優化(convex optimization)
SVM的優點和缺點
針對特定的數據集,每個分類算法都有自己的優點和缺點. SVM的優點如下:
- 優化目標的凸優化本質保證了找到最優解的可行性. 而且這個最優解是全局最優解而不是局部最優解
- SVM既適用於線性可分數據也適用於非線性可分數據(使用核方法就可以), 只要找到對應的懲罰參數C就可以.
- 對於高維數據和低維數據,SVM都有效, 即使在高維數據下SVM也能很高效工作,因為SVM的特性只由支持向量數目確定,而不是整個數據的維度, 非支持向量之外的數據點對於SVM無關緊要,甚至可以去除.
SVM缺點如下:
- 他們不適合大數據集訓練,因為訓練時間很長,而且對計算性能要求較高
- 對於有重疊類別的噪聲數據,SVM不是很有效
Python和R下的SVM
python下最常用的實現機器學習算法的庫是scikit-learn, SVM在scikit-learn下的分類函數是svm.SVC()
sklearn.svm.SVC(c = 1.0, kernel = ‘rbf‘,degree=3, gamma=‘auto‘)
參數如下:
C:正則化參數
kernel: 算法中使用的核函數, 可以是 ‘linear‘,‘poly‘,‘rbf‘,‘sigmoid‘,‘precomputed‘, 或者是用戶函數. 默認值是‘rbf‘
degree: ‘poly‘ 多項式核函數中的維度,默認是3,其他核函數忽略這個參數
gamma: ‘rbf‘,‘poly‘,‘sigmoid‘ 中的系數, 如果gamma是‘auto‘ 那麽會默認使用1/n 個特征
這裏很多參數我在這篇文章中都沒有提到過,進一步了解你可以查看這裏.
我們可以通過改變參數 C, \gamma 和核函數來優化SVM, scikit-learn中參數參數優化函數是gridSearch().
sklearn.model_selection.GridSearchCV(estimator, param_grid)
參數如下:
estimator:是我們我估計的對象,比如這裏就是svm.SVC()
param_grid:包含要優化的參數名字和要優化的值的字典或者列表
在上述代碼中,我們要考慮優化的參數是C和gamma, 這些參數的最優值在我們給定的參數中,這裏我們僅僅給出了一些值,我們也可以給出一系列取值範圍,但是這樣程序執行的時間會變長.
【技術翻譯】支持向量機簡明教程及其在python和R下的調參