支持向量機-SVM+源碼

聲明:個人學習之作,受時間和個人能力約束,僅供大家學習參考。歡迎討論。

支持向量機(SVM),用於分類和迴歸的強大判別模型。
首先我們將重新考慮把特徵映射到更高維度的空間。
接着我們將討論支持向量機如何去緩和從映射到高維空間的數據中學習時遇到的計算問題和泛化問題。

1.1 核與核的技巧

感知機使用一個超平面作爲決策邊界來區分正向實例和負向實例。
決策邊界公式:
f(x)=<w,x>+bf(x)=<w,x>+b
預測公式:
h(x)=sign(f(x))h(x)=sign(f(x))
這種方式,我們稱之爲原始形式
而在支持向量機中,我們需要把它轉化爲對偶形式。
f(x)=<w,x>+b=aiyi<xi,x>+bf(x)=<w,x>+b=\sum a_{i}y_{i}<x_{i},x>+b
原始形式和對偶形式最大的不同在於,原始形式計算了模型參數和測試實例特徵向量的內積,而對偶形式計算了訓練實例和測試實例特徵向量的內積
而正是這個特性,被用來處理線性不可分類。
首先,我們把特徵映射到更高維度空間的定義進行形式化
將特徵映射到一個更高維度的空間中,在該空間中特徵與響應變量線性相關。映射通過創建原有特徵的二次項增加了特徵的數量。而這些合成特徵允許我們使用一個線性模型來表示一個非線性模型。
總的來說,一個映射從公式上來講,如下:
xϕ(x)x\rightarrow \phi (x)
ϕ:RdRD\phi :R^{d}\rightarrow R^{D}
效果如下圖[1]


在第二張圖中,綠色的平面可以完美的劃分紫色和紅色,數據變得可分。
回到決策邊界的對偶形式,可以看到特徵向量智慧出現在點積中。我們可以通過在特徵向量上執行映射來把數據映射到一個更高維度的空間中。
f(x)=aiyi<xi,x>+bf(x)=\sum a_{i}y_{i}<x_{i},x>+b
f(x)=aiyi<ϕ(xi),ϕ(x)>+bf(x)=\sum a_{i}y_{i}<\phi (x_{i}),\phi (x)>+b
就像我們前面說的那樣,映射操作可以讓我們表示更復雜的模型,但是也引入了計算問題和泛化問題。
這意味着,對特徵向量進行映射和計算特徵向量的點積需要大量的處理能力。
而且,雖然說我們把特徵向量映射到了一個更高維度的空間中,特徵向量仍然只出現在點積計算中。點積的計算結果是一個標量,一個這個標量被計算出來,我們不在需要映射後的特徵向量。
如果能用依衆不同的方法求出和映射後向量點積相同的標量,那就很省事了。

核技巧

一個核實這樣的一種函數,只要給定了原始特徵向量,就能返回和其相關的映射特徵向量相同的點積值。核並不會直接把特徵向量映射到一個更高維度空間,或者計算映射向量的點積。
核通過一系列不同的操作來產出相同的值,這些操作可以得到有效的計算。
核的定義公式如下:
K(x,z)=<ϕ(x),ϕ(z)>K(x,z)=<\phi (x),\phi (z)>
下面來證明覈實如何運行的。
假設我們有兩個特徵向量x和z,
x=(x1,x2)x=(x_{1},x_{2})
z=(z1,z2)z=(z_{1},z_{2})
在實際當中,我們希望能夠將特徵向量映射到更高維度空間。
ϕ(x)=(x12,x22,2x1x2)\phi (x)=(x{_{1}}^{2},x{_{2}}^{2},\sqrt{2}x_{1}x_{2})
按照之前介紹的,映射標準化後的特徵向量的點積如下:
<ϕ(x),ϕ(z)>=(x12,x22,2x1x2),(z12,z22,2z1z2)<\phi (x),\phi (z)>=(x{_{1}}^{2},x{_{2}}^{2},\sqrt{2}x_{1}x_{2}),(z{_{1}}^{2},z{_{2}}^{2},\sqrt{2}z_{1}z_{2})
核函數能產出和映射特徵項鍊點積相等的值:
K(x,z)=<x,z>2=(x1z1+x2z2)2=x12z12+2x1z1x2z2+x22z22K(x,z)=<x,z>^{2}=(x_{1}z_{1}+x_{2}z_{2})^{2}=x{_{1}}^{2}z{_{1}}^{2}+2x{_{1}}z{_{1}}x{_{2}}z{_{2}}+x{_{2}}^{2}z{_{2}}^{2}
K(x,z)=<ϕ(x),ϕ(z)>K(x,z)=<\phi (x),\phi (z)>
公式是這個意思,我這塊寫一個個人理解的實例。一是方便理解,二是增加說服力,這裏爲了方便,我就不用公式編輯器了。
x=(4,9)
z=(3,3)
K(x,z)=4X4 X3x3 +2X4X3X9X3+9X9X3X3=1521
<ϕ(x),ϕ(z)>=<(42,92,2X4X9),(32,32,2X3X3)>=1521<\phi (x),\phi (z)>=<(4^{2},9^{2},\sqrt{2}X4X9),(3^{2},3^{2},\sqrt{2}X3X3)>=1521
核函數K(x,z)生成了和映射向量點積<ϕ(x),ϕ(z)><\phi (x),\phi (z)>計算結果相等的值,但是它並沒有顯性的把特徵向量映射到高維空間,並只需要相對較少的數學運算。
在舉得這個例子中,其實只使用了二維向量。
然而即使是隻有少量特徵的數據集也會產生巨大維度的映射特徵空間。
scikit-learn類庫則有一些常用的核函數:
多項式核函數:K(x,z)=(γ<xz>+δ)kK(x,z)=(\gamma <x-z>+\delta )^{k}
平方核或者k等於2的多項式核,經常被用於自然語言處理。
S型核:K(x,z)=tanh(γ<xz>+δ)kK(x,z)=tanh(\gamma <x-z>+\delta )^{k},其中 y和r這兩個參數都是可以在交叉驗證中進行微調的超參數。
對於需要用非線性模型處理的問題來說,高斯核是第一優先選擇。高斯核是一個徑向基函數。映射特徵向量空間中作爲決策邊界的超平面和源空間中走位決策邊界的超平面類似。
由高斯核產出的特徵空間可以擁有無限維度,這是其他特徵空間不可能具有的特性。
高斯核函數的定義如下:
K(x,z)=exp(γxz2)K(x,z)=exp(-\gamma |x-z|^{2})
使用SVM時,對特徵進行縮放是很重要的,但是在使用高斯核時,特徵縮放特別重要。
選擇核函數非常難。
理想情況下,一個核函數能通過某種對任務有效的方式衡量實例之間的相似性。
雖然核函數經常和SVM一起使用,但是它也能和任何能夠被表示爲兩個特徵向量點積的模型一起使用
包括但不限於邏輯迴歸,感知機,主成分分析法PCA。(之後我會後續介紹)

1.2 最大間隔分類和支持向量

還是用實際例子來描述:

這三條線,也就是我們所謂的三個分類器,都可以劃分樣本分類。
直觀的來講,紅色的線最優
但是對於技術人員來講,我們要求的是嚴謹和論證。

假定圖中的線是一個邏輯迴歸分類器的決策便捷。標記爲A的實例遠離決策邊界,它有很高的概率被預測爲正向類。標記爲B的實例仍然被預測爲屬於正向類,但是實例越靠近決策邊界被預測爲正向類的概率機會越低。
最後,標記爲C的實例有很低的概率被預測爲正向類,即使是訓練書記的一個微笑變化也會導致預測類發生變化。
如何解決?
最可信的預測是遠離決策邊界的訓練實例,因此我們可以使用其函數間隔來評估預測的可信度。
訓練集的函數間隔如下:
funct=minyif(xi)funct=min y_{i}f(x_{i})
f(x)=<w,x>+bf(x)=<w,x>+b
實例A的函數間隔很大,實例C的函數間隔很小。如果C分類錯誤,函數間隔將爲負值。
函數間隔等於1的實例稱爲支持向量。(?爲啥)
和函數間隔相關聯的有幾何間隔,或者支持向量的最大寬度。幾何間隔等於標準化函數間隔,由於函數間隔能通過w進行縮放,
所以對函數間隔進行標準化非常有必要。
當w是一個單位向量時,幾何間隔等於函數間隔。
最大化幾何間隔的參數模型可以通過約束優化條件得出。
min12<w,w>min\frac{1}{2}<w,w>
yi(<wixi>+b)1y_{i}(<w_{i}x_{i}>+b)\geq 1

(待解決問題:)
SVM的一個特性:約束優化問題是一個凸優化問題,它的局部最小值也是全局最小值(如何證明?)
找出使得幾何間隔最大化的參數是一個二次規劃問題,該問題 通常使用序列最小優化算法SMO解決。(未研究)

使用實例來進行測試:手寫數字分類

import matplotlib.pyplot as plt
from sklearn.datasets import fetch_mldata
import matplotlib.cm as cm
from sklearn import datasets

#引入數據集
mnist = datasets.fetch_mldata("mnist-original", data_home='/home/tianchi/myspace/datapanbo/mnist')
#mnist = fetch_mldata("MINIST original", data_home='/home/tianchi/myspace/datapanbo/mnist')
counter = 1
for i in range(1,4):
    for j in range(1,6):
        plt.subplot(3,5,counter)
        plt.imshow(mnist.data[(i-1) * 8000+j].reshape((28,28)),cm.Greys_r)
        plt.axis('off')
        counter+=1
plt.show

在這裏插入圖片描述

from sklearn.pipeline import   Pipeline

from sklearn.model_selection import  train_test_split
from sklearn.svm import SVC
from  sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
X,y =mnist.data, mnist.target 
X = X/255.0*2-1
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=11)
pipeline =Pipeline([
        ('clf',SVC(kernel='rbf', gamma=0.01, C=100))
    ])
parameters ={
        'clf__gamma':(0.01, 0.03, 0.1, 0.3, 1),
        'clf__C' : (0.1, 0.3, 1, 3, 10 , 30),
    }
grid_search =GridSearchCV(pipeline,parameters,n_jobs=2, verbose=1, scoring='accuracy')
grid_search.fit(X_train[:100],y_train[:100])

在這裏插入圖片描述
這裏我要說一下,因爲是爲了測試代碼跑通,所以我選擇了100個數據。

print('最好的分數: %0.3f' %grid_search.best_score_)
print('最好的參數集:')
best_parameters= grid_search.best_estimator_.get_params()
for param_name in sorted(parameters.keys()):
    print('\t%s: % r '%(param_name,best_parameters[param_name]))

predictions=grid_search.predict(X_test)
print(classification_report(y_test,predictions))

在這裏插入圖片描述
這個是用電腦跑一萬個數據,大約花了一個小時:63min
在這裏插入圖片描述
後續的代碼和數據集我會上傳到git
GIT代碼地址

參考文獻

1.核函數 https://blog.csdn.net/zb1165048017/article/details/49280979

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章