本文主要介紹SVM算法的過程:
目錄
1.SVM算法
1.1 SVM
SVM(Support Vector Machine)又稱爲支持向量機,最初是一種二分類的模型,後來修改之後也是可以用於多類別問題的分類。支持向量機可以分爲線性核非線性兩大類。其主要思想爲找到空間中的一個更夠將所有數據樣本劃開的超平面,並且使得本本集中所有數據到這個超平面的距離最短。
1.2 最大邊際的超平面和向量點
我們都知道空間中,有無數個可能的超平面去區分兩個點。那麼如何選取使邊際最大的超平面呢?超平面到一側最近點的距離等於到另一側最近點的距離,並且兩側的兩個超平面平行,其中這些點就是向量點。如下圖所示:
超平面定義爲: 。
W是權重向量,。
X是訓練實例。
b是偏置。
1.3公式建立過程
對n維空間中的點,到超平面的距離爲:
其中||W||爲超平面的範數,常數b類似於直線方程中的截距。
假設2維特徵向量:X = (x1, X2),則超平面方程變爲: 。由於b是偏置,方便數學運算令b=w0。
那麼,所有超平面右上方的點都滿足:;
所有超平面左下方的點都滿足:。
調整weight,使超平面定義邊際的兩邊:
H1:
H2:
綜合以上兩個等式得到: ,其中y爲數據點的標籤,於是推廣到,公式就滿足:y(W*X+b)1。
調整w和b,使得對任意一點到超平面的邊際最大。目標函數優化爲:
而min(y(W*X+b))=1,故目標函數爲:1/||W|| ,對於矩陣等同於,min1/2*|W||^2。
這是一個有約束條件的優化問題,通常我們可以用拉格朗日乘子法來求解,應用拉格朗日乘子法如下:
令,
求L關於求偏導數得:
帶入化簡得到:
原問題的對偶問題爲:
該對偶問題的KKT條件爲:
到此,似乎問題就能夠完美地解決了。但是這裏有個假設:數據必須是百分之百可分的。但是實際狀況中訓練集的數據是不可分的,那怎麼處理呢?且看下文介紹。
1.4線性不可分(linear inseparable)
如下所示,數據集是線性不可分的情形。
主要兩個步驟來解決:
1、利用一個非線性的映射把原數據集中的向量點轉化到一個更高維度的空間中;
2、在這個高維度的空間中找一個線性的超平面來根據線性可分的情況處理。
如何把原始數據轉化到高維的空間?
例如將3維向量X = (x1,x2,x3)映射到6維空間中爲,
新的決策超平面:d = WX+b,根據這個超平面是線性的解出W和b之後,並且帶入回原方程計算d。
1.5核方法
在線性SVM中轉化爲最優化問題時求解的公式計算都是以內積的形式出現的,因爲內積的算法複雜度非常大,所以我們利用核函數來取代計算非線性映射函數的內積。
常用的核函數有:
- h度多項式核函數(polynomial kernel of degree h):
- 高斯徑向基核函數(Gaussian radial basis function kernel):
- S型核函數(Sigmoid function kernel):
根據先驗知識,比如圖像分類,通常使用RBF,文字不使用RBF。嘗試不同的kernel,根據結果準確度而定。
例如:
假設定義兩個向量: x = (x1, x2, x3); y = (y1, y2, y3)。定義方程:f(x) = (x1x1, x1x2, x1x3, x2x1, x2x2, x2x3, x3x1, x3x2, x3x3) ,K(x, y ) = (<x, y>)^2,假設x = (1, 2, 3); y = (4, 5, 6)。則有:
f(x) = (1, 2, 3, 2, 4, 6, 3, 6, 9), f(y) = (16, 20, 24, 20, 25, 36, 24, 30, 36)
<f(x), f(y)> = 16 + 40 + 72 + 40 + 100+ 180 + 72 + 180 + 324 = 1024
K(x, y) = (4 + 10 + 18 ) ^2 = 32^2 = 1024
同樣的結果,使用核方法計算容易很多。
2 SVM算法的簡單運用
如下代碼:
from sklearn import svm
import numpy as np
import matplotlib.pyplot as plt
def plot_figure(data_mat, labels):
fig = plt.figure()
ax = fig.add_subplot(111)
l = []
for label in labels:
if label ==0:
l.append(1)
elif label ==1:
l.append(2)
else:print('ERR:',label)
labels = l
t = ax.scatter(data_mat[:,1],data_mat[:,0],10 * np.array(labels),np.array(labels), marker='o')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.title('SVM DEMO')
plt.show()
x = [[2, 0], [1, 1], [1.5,1.5],[2, 3],[3,3],[4,4],[3,4],[0,2],[0,1],[1,0]]
x = np.array(x)
y = [0, 0 ,1,1,1,1,1,0,0,0]
clf = svm.SVC(kernel = 'linear')
clf.fit(x, y)
#show SVM
print (clf)
# get support vectors
print (clf.support_vectors_)
# get indices of support vectors
print (clf.support_)
# get number of support vectors for each class
print (clf.n_support_)
# visiable SVM
plot_figure(x,y)
# SVM predict
test = np.array([[1,2],])
test_y = clf.predict(test)
y_pred_train = clf.predict(x)
y_score_train = clf.decision_function(x)
y_score_cv = clf.decision_function(test)
print(test_y)
print(y_pred_train)
print(y_score_train)
print(y_score_cv)