0.前言
之前的文章講過,感知機作爲一種線性分類模型,難以解決非線性問題。爲了處理非線性的情況,在感知機模型的基礎上發展出了兩個方向,一個是神經網絡,另一個就是本文要講述的一個模型——支持向量機,同樣也能夠解決非線性問題。
而我們知道分類學習的基本想法其實就是:基於訓練集D在樣本空間中找到一個劃分的超平面。SVM就是求解一個超平面。
**SVM可以簡單分爲三種類型:**線性可分支持向量機、線性支持向量機(疑似線性可分,但存在少部分數據不可分)、線性不可分支持向量機。
1、補充下超平面的基本知識
對於一個超平面的方程如下:可簡單記作(w,b)
滿足如下的性質:
- 法向量w恆垂直於超平面;
- 和法向量w方向相同的點代入超平面方程恆大於0,否則恆小於等於0;
- 法向量w和位移項b唯一確定一個超平面;
- 等倍縮放法向量和位移項,超平面是不變的。
2、支持向量機原始模型的建立
(1)點到超平面的距離公式推導
從西瓜書中我們可以直接看到這樣一個公式:點x到超平面(w,b)的距離公式
而這個公式如何推導的呢?如下所示:
(2)引入SVM主問題
首先看個定義:
定義超平面到一個樣本的函數間隔爲:
則定義超平面到整個數據集的函數間隔爲超平面關於樣本的函數間隔的最小值,即:
而超平面存在三種劃分情況:
- 穿過正樣本
- 處於正負樣本之間
- 穿過負樣本
代入不同的正負樣本值可以得到,穿過正樣本的函數間隔<0,處於正負樣本之間的函數間隔>0,穿過負樣本的函數間隔<0。而我們要找到這樣一個能夠處於正負樣本之間的劃分超平面,則需要求解最大函數間隔值,也就是超平面儘可能遠離正負樣本;且要完美分開正負樣本,也就是處於正中間,則還需要求解幾何間隔,定義如下:
則以上問題就變爲SVM的核心問題:求解幾何間隔的最大值的那個超平面,即滿足以下優化問題:
進一步優化如下,常見對於 伽馬y我們約束定義爲一個常數值如1或者2,這裏定義爲1,同時將最大化問題轉化爲最小化問題,約束條件變爲<=0,則問題轉化爲如下的凸優化問題:這就是支持向量的基本型。
其中1/2和加的平方項並不影響求解參數w,b的值,所以,這裏爲了方便後續的計算和引入核函數。
西瓜書中的一個圖對以上的一些定義給出了幾何圖的解釋:
(3)對偶求解法來求解以上優化問題
SVM的拉格朗日對偶形式爲:
以上對偶形式繼續推導,得到一個分段函數:
由該分段函數定義SVM的對偶問題:
繼續計算得到SVM的對偶問題的具體形式,也就是西瓜書上的公式6.11。
剩下的問題就是求解式中的參數阿法a,可以採用凸二次規劃法求解,但不建議,對於數據量很大時,建議採用SMO(序列最小最優化)算法求解,可以百度一下。求解阿發a之後,求出w和b即可得到超平面:
特別的,對於SVM的優化形式問題中的約束條件是不等式條件,則需要滿足KKT條件纔可以進行以上的對偶問題求解。
KKT條件的定義爲:
,由以上的定義導出SVM的KKT條件爲:
至此,SVM的原始模型構建原理基本講完了。
3、軟間隔
在第二節中介紹的是硬間隔的SVM,也就是線性可分的數據,算法對於所有樣本都劃分正確;而軟間隔問題可以解決實際問題中疑似線性可分數據的劃分,算法對於部分樣本劃分允許存在誤差,意味着某些樣本點不滿足此前線性可分中的函數間隔大於1的約束條件,線性支持向量機這裏的處理方法是對每個實例引入一個鬆弛變量,使得函數間隔加上鬆弛變量大於等於1。對應於線性可分時的硬間隔最大化(hard margin svm),線性支持向量機可稱爲軟間隔最大化問題(soft margin svm)。
4、非線性支持向量機
所謂非線性可分問題,就是對於給定數據集,如果能用一個超曲面將正負實例正確分開,則這個問題爲非線性可分問題。非線性問題的一個關鍵在於將原始數據空間轉換到一個新的數據空間,在原始空間中的非線性可分問題轉化爲到新空間就是線性可分問題。
一般來說,用線性可分方法來解決非線性可分問題可分爲兩步:首先用一個變換將原始空間的數據映射到新空間,再在新空間中用線性分類學習方法訓練分類模型。這種將原始空間轉換到新空間的方法稱爲核技巧(kernel trick)。所以說引入核函數的目的就是解決面對非線性可分的數據劃分問題,常見的核函數如下:多項式核函數、高斯核函數以及sigmoid核函數等
核函數的定義:
假設存在一個從輸入空間到特徵空間的映射,使得所有的x和z都有函數K(x,z)=&(x).&(z),則稱K(x,z)爲核函數。在實際問題中,通常直接給定核函數的形式,然後進行求解。
因此,可以給出核函數的SVM對偶問題形式:
5、Sklearn包實現SVM算法
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm, datasets
#網格繪圖
def make_meshgrid(x, y, h=.02):
"""Create a mesh of points to plot in
Parameters
----------
x: data to base x-axis meshgrid on
y: data to base y-axis meshgrid on
h: stepsize for meshgrid, optional
Returns
-------
xx, yy : ndarray
"""
x_min, x_max = x.min() - 1, x.max() + 1
y_min, y_max = y.min() - 1, y.max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
return xx, yy
#繪製決策邊界
def plot_contours(ax, clf, xx, yy, **params):
"""Plot the decision boundaries for a classifier.
Parameters
----------
ax: matplotlib axes object
clf: a classifier
xx: meshgrid ndarray
yy: meshgrid ndarray
params: dictionary of params to pass to contourf, optional
"""
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
out = ax.contourf(xx, yy, Z, **params)
return out
#導入iris數據集
iris = datasets.load_iris()
#提取前兩個數據特徵:Sepal length和Sepal width
X = iris.data[:, :2]
y = iris.target
#創建SVM模型
C = 1.0 # SVM 正則化參數
#四種模型處理,rbf爲高斯核,poly爲多項式核
models = (svm.SVC(kernel='linear', C=C),
svm.LinearSVC(C=C, max_iter=10000),
svm.SVC(kernel='rbf', gamma=0.7, C=C),
svm.SVC(kernel='poly', degree=3, gamma='auto', C=C))
models = (clf.fit(X, y) for clf in models)
# 圖的標題
titles = ('SVC with linear kernel',
'LinearSVC (linear kernel)',
'SVC with RBF kernel',
'SVC with polynomial (degree 3) kernel')
# Set-up 2x2 grid for plotting.
fig, sub = plt.subplots(2, 2)
plt.subplots_adjust(wspace=0.4, hspace=0.4)
X0, X1 = X[:, 0], X[:, 1]
xx, yy = make_meshgrid(X0, X1)
for clf, title, ax in zip(models, titles, sub.flatten()):
plot_contours(ax, clf, xx, yy,
cmap=plt.cm.coolwarm, alpha=0.8)
ax.scatter(X0, X1, c=y, cmap=plt.cm.coolwarm, s=20, edgecolors='k')
ax.set_xlim(xx.min(), xx.max())
ax.set_ylim(yy.min(), yy.max())
ax.set_xlabel('Sepal length')
ax.set_ylabel('Sepal width')
ax.set_xticks(())
ax.set_yticks(())
ax.set_title(title)
plt.show()
參數詳解:
- C: 目標函數的懲罰係數C,用來平衡分類間隔margin和錯分樣本的,default C = 1.0;
- kernel:參數選擇有RBF, Linear, Poly, Sigmoid, 默認的是"RBF";
- degree:如果kernel的參數選擇的是“poly”,則該參數有效.degree決定了多項式的最高次冪;
- gamma:核函數的係數(‘Poly’, ‘RBF’ and ‘Sigmoid’), 默認是gamma = 1 / n_features;
- coef0:核函數中的獨立項,‘RBF’ and 'Poly’有效;
- probablity: 可能性估計是否使用(true or false);
- shrinking:是否進行啓發式;
- tol(default = 1e - 3): svm結束標準的精度;
- cache_size: 制定訓練所需要的內存(以MB爲單位);
- class_weight: 每個類所佔據的權重,不同的類設置不同的懲罰參數C, 缺省的話自適應;
- verbose: 跟多線程有關,不大明白啥意思具體;
- max_iter: 最大迭代次數,default = 1, if max_iter = -1, no limited;
- decision_function_shape : ‘ovo’ 一對一, ‘ovr’ 多對多 or None 無,默認爲None;
- random_state :用於概率估計的數據重排時的僞隨機數生成器的種子。
模型調參的過程中,以上參數shrinking、tol、 cache_size可以不做考慮。
運行結果: