機器學習:支持向量機

本文來自同步博客

P.S. 不知道怎麼顯示數學公式以及更好的排版內容。所以如果覺得文章下面格式亂的話請自行跳轉到上述鏈接。後續我將不再對數學公式進行截圖,畢竟行內公式截圖的話排版會很亂。看原博客地址會有更好的體驗。

上一篇文章使用KNN算法解決機器學習的分類問題。本文將介紹另一種號稱解決分類問題的最佳算法,叫支持向量機SVM(Support Vector Machine)。

這篇文章將不立即從代碼開始介紹SVM,而是從理論知識開始瞭解其原理,最後用代碼實踐並驗證我們對知識的理解。

基本原理

SVM的目標是找到一個超平面,使得超平面到最近樣本點之間的間隙最大化,從而把樣本點切割成不同的子空間以得到分類的效果。

 
切割方法的比較

看上面圖片所列舉的三種針對同一空間中樣本數據的切割方法。最後一種纔是符合SVM要求的切割方法。

需要加深一下大家的印象:

  1. 在一維空間中,這個超平面是一個點;
  2. 在二維空間中,這個超平面是一條線;
  3. 在三維空間中,這個超平面是一個面;
  4. 更多維的空間,呵呵,我想象不了...

如果僅僅依靠點線面只能處理具有線性可分割特徵的數據,而當樣本數據無法進行線性切割時,是不是SVM就不適用了呢?不是的,對這種場景,可以通過一些轉換函數,把直線或者平面變成曲線或者曲面進行切割。

本文還是我們先從可以線性切割的簡單的場景出發進行推導SVM的基本原理。有關無法進行線性切割的內容,我們將在後面介紹。

數學推導

爲了找到符合SVM要求的超平面,我們需要先通過數學語言描述它。請看下圖:

 
超平面的數學表示

在這個空間中有四個樣本點分成了兩類,紅色的表示「+」類,黃色表示「-」類。圖中的實線L就是我們在這個空間中根據SVM定義找到的超平面。樣本點A、B、C、D等在空間中均用向量表示,特別地,落在虛線上的點A、B、C作爲間隙的邊界點而存在,將會爲計算超平面作出貢獻,因此成爲Support Vector。這應該就是Support Vector Machine名字的由來。

現在我們定義一個向量$-\vec{w}-$,它垂直於超平面L,是L的法向量。則使用法向量$-\vec{w}-$描述超平面L爲:

$$\vec{w}^{T}(\vec{x} - \vec{x_0}) = 0 $$

其中$-\vec{x_0}-$爲$-\vec{w}-$與超平面的交點。令$-b = -\vec{w}\vec{x_0}-$,L可以表示爲:

$$式子1: \vec{w}^{T}\vec{x} + b = 0$$

針對一個新的數據點$-\vec{u}-$,如果點落在超平面L的右上方,則判定這個數據點爲「+」類;若是落在L的左下方則判定爲「-」類。即決策規則爲:

$$
Rule: \begin{cases}
\vec{w}^{T}\vec{u} + b > 0, & \mbox{if }\vec{u}\mbox{ is class '+'} \\
\vec{w}^{T}\vec{u} + b < 0, & \mbox{if }\vec{u}\mbox{ is class '-'}
\end{cases}
$$

我們的目標是確定超平面L。但是由於$-\vec{w}-$的長度是不清楚的,$-b-$也受之影響而無法確定。它們可以有太多太多中組合了。所以接下來需要通過樣本數據來約束$-\vec{w}-$和$-b-$的取值範圍,爲我們求解提供依據。

原本對於對所有樣本點$-x_i-$,滿足:

$$
\begin{array}{lcl}
\vec{w}^{T}\vec{x_i} + b > 0,& \mbox{if }\vec{x_i}\mbox{ is class '+'} \\
\vec{w}^{T}\vec{x_i} + b < 0,& \mbox{if }\vec{x_i}\mbox{ is class '-'}
\end{array}
$$

爲了增加約束條件從而限制$-\vec{w}-$的取值範圍,我們把超平面分別向右上和左下平移,直至到達虛線位置。並且限定右上虛線和左下虛線的表達式爲:$-\vec{w}^{T}\vec{x_i} + b = 1-$和$-\vec{w}^{T}\vec{x_i} + b = -1-$。能夠同時滿足超平面以及兩個虛線位置的超平面表達式的$-\vec{w}-$和$-b-$組合一定是存在的。那麼所有的樣本點$-x_i-$都將滿足下面不等式:

$$
式子2: \begin{cases}
\vec{w}^{T}\vec{x_i} + b \ge 1,& \mbox{if }\vec{x_i}\mbox{ is class '+'} \\
\vec{w}^{T}\vec{x_i} + b \leq -1,& \mbox{if }\vec{x_i}\mbox{ is class '-'}
\end{cases}
$$

這個不等式組利用了樣本點已經確定了所屬類這個已知條件來約束$-\vec{w}-$的取值範圍。選擇「1」和「-1」則是一個數學技巧,讓後續計算中更加方便,它並不影響計算過程。

接下來,引入分類變量$-y_i-$:
$$
式子3: \begin{cases}
y_i = 1,& \mbox{if }\vec{x_i}\mbox{ is class '+'} \\
y_i = -1,& \mbox{if }\vec{x_i}\mbox{ is class '-'}
\end{cases}
$$

式子2和式子3兩個方程組分別相乘,並把右邊的1移到左邊,可以得到一個統一的不等式:

$$式子4:y_i(\vec{w}^{T}\vec{x_i} + b) - 1 \ge 0$$

這個不等式只有落在SVM分割間隙的邊緣(即圖中虛線)的樣本點(如:A、B、C)才能使等號成立。

到這裏,請重新回到SVM的原理:尋找讓間隙最大化的超平面作爲分類的決策邊界。我們需要確定分割間隙的寬度的計算函數。假設在間隙兩個邊緣(兩條虛線)處分別取樣本$-\vec{x_+}-$和$-\vec{x_-}-$,對應類型取值爲$-y_+ = 1-$、$-y_- = -1-$,可以得到:
$$
\begin{align}
width &= \frac{\vec{w}^{T}}{|\vec{w}|}(\vec{x_+} - \vec{x_-}) \\
&= \frac{1}{|\vec{w}|}(\vec{w}^{T}\vec{x_+} - \vec{w}^{T}\vec{x_-}) \\
&= \frac{1}{|\vec{w}|}(\frac{1-b}{y_+} - \frac{1-b}{y_-})\\
&= \frac{1}{|\vec{w}|}(\frac{1-b}{1} - \frac{1-b}{-1})\\
&= \frac{2}{|\vec{w}|}
\end{align}
$$

爲了讓間隙的寬度取得最大,可以推導出:

$$
式子5:\begin{align}
& Maximize(width) \\
&\Leftrightarrow Maximize(\frac{2}{|\vec{w}|}) \\
&\Leftrightarrow Minimize(|\vec{w}|)\\
&\Leftrightarrow Minimize(\frac{1}{2}|\vec{w}|^2)\\
&\Leftrightarrow Minimize(\frac{1}{2}\vec{w}^{T}\vec{w})
\end{align}
$$

有了這個依據,利用拉格朗日乘子法求不等式約束條件下的極值問題,可以構造這樣的函數:

$$
L(\vec{w}, b, \vec{\alpha}) = \frac{1}{2}\vec{w}^{T}\vec{w} - \sum_{i}{n}{\alpha_i[y_i(\vec{w}{T}\vec{x_i})-1]}, \alpha_i \ge 0, i = 1,2...n
$$

在這裏問題的目標是求讓$-L(\vec{w}, b, \vec{\alpha})-$最小時的$-\vec{w}-$、$-b-$和$-\vec{\alpha}-$,因此先分別對$-\vec{w}-$和$-b-$求偏導:

$$
\frac{\partial L}{\partial \vec{w}} = \vec{w} - \sum_{i}^{n}{\alpha_i y_i \vec{x_i}},
\frac{\partial L}{\partial b} = - \sum_{i}^{n}{\alpha_i y_i}
$$

讓偏導函數等於0,有:

$$
\vec{w} = \sum_{i}^{n}{\alpha_i y_i \vec{x_i}}, \sum_{i}^{n}{\alpha_i y_i} = 0
$$

在這裏先不求出關於$-\vec{\alpha}-$的偏導,而是把上述兩個等式代回拉格朗日函數L,從而可以得到一個關於$-\vec{\alpha}-$的函數:

$$
L(\vec{\alpha}) = \sum_{i}^{n}{\alpha_i} - \frac{1}{2}\sum_{i}{n}{\sum_{j}{n}{\alpha_i \alpha_j y_i y_j \vec{x_i}^{T} \vec{x_j}}}, \sum_{i}^{n}{\alpha_i y_i} = 0, \alpha_i,\alpha_j \ge 0, i,j = 1,2...n
$$

根據對偶問題的思想,上述最小化問題可轉爲求使$-L(\vec{\alpha})-$最大化的$-\alpha-$(參考KKT條件問題)。

對上式兩邊添加負號,進一步轉換問題:求讓$- -L(\vec{\alpha})-$最小化的$-\alpha-$。這時有:

$$
F(\vec{\alpha}) = -L(\vec{\alpha}) = \frac{1}{2}\vec{\alpha}^{T}\begin{bmatrix}
y_{1}y_{1}\vec{x_1}^{T}\vec{x_1} & y_{1}y_{2}\vec{x_1}^{T}\vec{x_2} & \cdots & y_{1}y_{n}\vec{x_1}^{T}\vec{x_n} \\\\
\vdots & \vdots & \ddots & \vdots \\\\
y_{n}y_{1}\vec{x_n}^{T}\vec{x_1} & y_{n}y_{2}\vec{x_n}^{T}\vec{x_2} & \cdots & y_{n}y_{n}\vec{x_n}^{T}\vec{x_n} \\\\
\end{bmatrix}\vec{\alpha}
+ \begin{bmatrix}
-1 & -1 & \cdots & -1 \\\\
\end{bmatrix} \vec{\alpha}, \vec{y}^{T}\vec{\alpha} = 0, \vec{\alpha} \ge 0
$$

啊哈,這是二次規劃的形式,可以利用二次規劃求解。我們需要求解能夠使$-F(\alpha)-$最小的$-\alpha-$值,然後通過$-\alpha-$纔可以得到$-\vec{w}-$和$-b-$。

這裏提供一個使用scipy求解二次規劃的代碼示範:

import numpy as np
from scipy import optimize
# 形如:F = (1/2)*x.T*H*x + c*x + c0
# 約束條件:Ax <= b
# 現在假設已知參數如下:
H = np.array([[2., 0.],
              [0., 8.]])
c = np.array([0, -32])
c0 = 64
A = np.array([[ 1., 1.],
              [-1., 2.],
              [-1., 0.],
              [0., -1.],
              [0.,  1.]])
b = np.array([7., 4., 0., 0., 4.])

# 設置初始值
x0 = np.random.randn(2)

def loss(x, sign=1.):
    return sign * (0.5 * np.dot(x.T, np.dot(H, x))+ np.dot(c, x) + c0)

def jac(x, sign=1.):
    return sign * (np.dot(x.T, H) + c)

cons = {'type':'ineq',
        'fun':lambda x: b - np.dot(A,x),
        'jac':lambda x: -1 * A}
opt = {'disp':False}

res_cons = optimize.minimize(loss, x0, jac=jac,constraints=cons,
                                 method='SLSQP', options=opt)
print(res_cons)

源碼見Github