機器學習:支持向量機3

本文來自同步博客。看原博客地址會有更好的體驗。python

前面兩篇文章介紹了支持向量機SVM的基本原理,並利用Python實踐了分割超平面的求解過程。git

本篇文章將介紹SVM如何對非線性可分的數據進行分類。github

基本原理

SVM處理線性不可分數據的關鍵在於把低維空間中線性不可分的數據映射到高維空間使其線性可分。而後再按線性可分數據進行處理。函數

就像下方展現的內容。有圓圈和星星兩種不一樣的數據,在左邊的一維空間中它們是沒法線性分割的;而在右邊二維空間中卻能夠用一條橫線進行分割。測試

 

 

基於這個原理,很直觀地,找到一個映射函數把樣本向量x映射到高維空間的一個向量z。例如:對$-\vec{x}=(x_1, x_2)-$,能夠有選擇相似$-\vec{z}=(1,x_1,x_2,x_1^2, x_2^2, 2x_1x_2)-$的映射。利用這個映射,能夠計算出每一個數據點在高維空間中對應的向量。最後用這些向量求解$-\vec{\alpha}、\vec{w}、b-$。spa

這裏須要思考一個問題:這樣把每一個數據都映射成另外一個向量,而後在進行計算,比線性可分模型的SVM複雜了好多好多。還有要找到這樣的映射也不是一件容易的事。有沒有比較好的作法?答案確定是有的,能夠利用「核技巧」。3d

核技巧

實際上咱們不須要計算每一個數據在高維空間的向量。由於不管是求解$-\vec{\alpha}-$,仍是求解分割超平面的$-\vec{w}-$和$-b-$,咱們須要僅僅只有一個高維空間下對應兩個向量的向量積。例若有數據點$-\vec{x_1},\vec{x_2}-$,對應的映射後的結果爲$-\vec{z_1},\vec{z_2}-$,那麼咱們要的僅僅是$-\vec{z_1}^{T} \vec{z_2}-$這個向量積。這種處理方式且稱爲核技巧,用函數$-K(x_1,x_2)-$表示向量積$-\vec{z_1}^{T} \vec{z_2}-$。code

首先,構造二次規劃函數只須要$-K(x_1,x_2)-$:
$$
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{z_i}^{T} \vec{z_j}}}, \sum_{i}^{n}{\alpha_i y_i} = 0, \alpha_i,\alpha_j \ge 0, i,j = 1,2...n
$$blog

獲得$-\vec{\alpha}-$向量後,能夠獲得$-\vec{w}-$:
$$
w = \sum_{i}^{n}{\alpha_i y_i \vec{z_i}}
$$
取其中一個支持向量(假設下標爲v),可計算b,也只須要$-K(x_1,x_2)-$:
$$
b = \frac{1}{y_v} - \vec{w}^{T}\vec{z_v} = \frac{1}{y_v} - \sum_{i}^{n}{\alpha_i y_i \vec{z_i}^{T}}\vec{z_v} = \frac{1}{y_v} - \sum_{i}^{n}{\alpha_i y_i K(\vec{z_i},\vec{z_v})}
$$get

最後,對新數據的決策規則函數Rule以下,也只須要$-K(x_1,x_2)-$:
$$
Rule: sign(\sum_{i}^{n}{\alpha_i y_i K(\vec{x_i},\vec{u})} + b)
$$

經常使用核函數

1. 線性核函數

$$
K(\vec{x_1},\vec{x_2}) = \vec{x_1}^{T}\vec{x_2}
$$
這是$-\vec{x_1}^{T}\vec{x_2}-$自己,也算一個線性核函數,同時它也是下面介紹的多項式核函數的特例。

2. 多項式核函數

$$
K(\vec{x_1},\vec{x_2}) = (\vec{x_1}^{T}\vec{x_2} + c)^{d}
$$

這種核函數利用多項式展開能夠了解它將把原向量映射到某個維度可數的空間內,維度數目與原向量的維度以及參數c、d有關。

3. 高斯核函數

$$
K(\vec{x_1},\vec{x_2}) = exp(-\gamma ||\vec{x_1} - \vec{x_2}||^{d}) = e^{-\gamma ||\vec{x_1} - \vec{x_2}||^{d}}
$$

高斯核函數能夠利用泰勒展開,它能夠把原向量映射到近乎無窮維空間。

斷定核函數是否有效(高維空間是否存在)

通常狀況下咱們不須要本身發明核函數,經常使用的核函數已經夠用,因此「關於多維Z空間是否存在或者核函數是否有效」的證實能夠忽略無論。

這裏依舊羅列判斷核函數是否有效的兩個條件:

  1. 核函數對輸入是對稱的,$-K(\vec{x_1}, \vec{x_2}) = K(\vec{x_2}, \vec{x_1})-$。

$-\begin{bmatrix}
K(\vec{x_1},\vec{x_1}) & K(\vec{x_1},\vec{x_2}) & \cdots & K(\vec{x_1},\vec{x_n}) \\
\vdots & \vdots & \ddots & \vdots \\
K(\vec{x_n},\vec{x_1}) & K(\vec{x_n},\vec{x_2}) & \cdots & K(\vec{x_n},\vec{x_n}) \\
\end{bmatrix} -$矩陣是一個正半定矩陣。

使用Python展現SVM對線性不可分數據的處理過程

與前一篇文章中的例子比較,這裏的代碼主要增長了一個kernel函數表示$-K(\vec{x_1},\vec{x_2})-$:

# 核函數: 多項式核函數c=0,d=2
# 選擇依據與測試數據有關,這樣的映射應該能夠把數據分隔開
# 則kernel應該返回的內積以下:
def kernel(x1, x2):
    return np.dot(x1, x2)**2

其次,在生成H矩陣的時候不是直接使用$-\vec{x_1}^{T}\vec{x_2}-$,而是使用kernel函數,以下:

# 計算H矩陣,根據樣本數目應是一個len(X)xlen(X)的矩陣
H = np.array(
    [y[i] * y[j] * kernel(X[i], X[j]) for i in range(len(X)) for j in range(len(X))]
).reshape(len(X), len(X))

其餘的流程幾乎同樣,除了繪圖代碼。

執行結果以下:

 

 

 

本文源碼