支持向量機(jī),一個有監(jiān)督的機(jī)器學(xué)習(xí)算法。通俗來講,它是一種二類分類模型,其基本模型定義為特征空間上的間隔最大的線性分類器,其學(xué)習(xí)策略便是間隔最大化,最終可轉(zhuǎn)化為一個凸二次規(guī)劃問題的求解。
除了進(jìn)行線性分類,支持向量機(jī)可以使用所謂的核技巧,它們的輸入隱含映射成高維特征空間中有效地進(jìn)行非線性分類。
給定一些數(shù)據(jù)點(diǎn),它們分別屬于兩個不同的類,現(xiàn)在要找到一個線性分類器把這些數(shù)據(jù)分成兩類。如果用
表示數(shù)據(jù)點(diǎn),用
表示類別(
可以取 1 或者 -1,分別代表兩個不同的類),一個線性分類器的學(xué)習(xí)目標(biāo)便是要在
維的數(shù)據(jù)空間中找到一個超平面(hyper plane),這個超平面的方程可以表示為
下面即簡單刻畫了這些數(shù)據(jù):
%matplotlib inline
from sklearn.datasets import make_blobs
import mglearn
import matplotlib.pyplot as plt
#生成聚類數(shù)據(jù)
X,y = make_blobs(centers=2, random_state=1)
mglearn.discrete_scatter(X[:,0], X[:,1],y)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

根據(jù)上圖我們可以很容易的作出一條線區(qū)分兩類數(shù)據(jù)點(diǎn).那么要如何確定這個超平面呢?這個超平面應(yīng)該是 最適合 分開兩類數(shù)據(jù)的直線。而判定“最適合”的標(biāo)準(zhǔn)就是這條直線離直線兩邊的數(shù)據(jù)的間隔最大。所以,得尋找有最大間隔的超平面
import numpy as np
from mglearn.plot_helpers import cm2
def plot_2d_separator1(classifier, X, fill=False, ax=None, eps=None, alpha=1,
cm=cm2, linewidth=None, threshold=None,
linestyle="dashed",a=0):
# binary?
if eps is None:
eps = X.std() / 2.
if ax is None:
ax = plt.gca()
x_min, x_max = X[:, 0].min() - eps, X[:, 0].max() + eps
y_min, y_max = X[:, 1].min() - eps, X[:, 1].max() + eps
xx = np.linspace(x_min, x_max, 1000)
yy = np.linspace(y_min, y_max, 1000)
X1, X2 = np.meshgrid(xx, yy)
X_grid = np.c_[X1.ravel(), X2.ravel()-a]
try:
decision_values = classifier.decision_function(X_grid)
levels = [0] if threshold is None else [threshold]
fill_levels = [decision_values.min()] + levels + [
decision_values.max()]
except AttributeError:
# no decision_function
decision_values = classifier.predict_proba(X_grid)[:, 1]
levels = [.5] if threshold is None else [threshold]
fill_levels = [0] + levels + [1]
if fill:
ax.contourf(X1, X2, decision_values.reshape(X1.shape),
levels=fill_levels, alpha=alpha, cmap=cm)
else:
ax.contour(X1, X2, decision_values.reshape(X1.shape), levels=levels,
colors="black", alpha=alpha, linewidths=linewidth,
linestyles=linestyle, zorder=5)
from sklearn.svm import LinearSVC
linear_svm = LinearSVC().fit(X,y)
plot_2d_separator1(linear_svm, X,a=2)
plot_2d_separator1(linear_svm, X,a=-2)
mglearn.plots.plot_2d_separator(linear_svm, X)
mglearn.discrete_scatter(X[:,0],X[:,1],y)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

我們注意到
能夠表示點(diǎn)
到距離超平面的遠(yuǎn)近(相對遠(yuǎn)近),又類標(biāo)記
的符號
表示不同類別,故我們可以用
表示間隔,稱為函數(shù)間隔(functional margin)
但是這樣定義間隔,如果成比例的改變
和
(如將它們改成
和
),則函數(shù)間隔的值
卻變成了原來的 2 倍(雖然此時超平面沒有改變),所以我們要引入幾何間隔(geometrical margin)(經(jīng)計(jì)算得)
為了得到的絕對值,令
乘上對應(yīng)的類別
,即可得出幾何間隔
對一個數(shù)據(jù)點(diǎn)進(jìn)行分類,當(dāng)超平面離數(shù)據(jù)點(diǎn)的“間隔”越大,分類的確信度也越大,為了使分類的確信度盡量高,需要讓所選擇的超平面能夠最大化這個“間隔”值。而在這個間隔值上的數(shù)據(jù)點(diǎn)被稱為是支持向量(support vector)的,這就是支持向量機(jī)的由來。于是最大間隔分類器(maximum margin classifier) 的目標(biāo)函數(shù)定義為:
同時要滿足一些條件,根據(jù)間隔的定義,有:
如果令函數(shù)間隔
等于 1,則有
且
,從而上述目標(biāo)函數(shù)轉(zhuǎn)換為
由于求
的最小值,所以上述目標(biāo)函數(shù)等價于
因?yàn)楝F(xiàn)在的目標(biāo)函數(shù)是二次的,約束條件是線性的,所以它是一個凸二次規(guī)劃問題。此外,由于這個問題的特殊結(jié)構(gòu),還可以通過拉格朗日對偶性(Lagrange Duality)變換到對偶變量的優(yōu)化問題,即通過求解與原問題等價的對偶問題得到原始問題的最優(yōu)解,這就是線性可分條件下支持向量機(jī)的對偶算法,這樣做的有點(diǎn)在于:一者對偶問題往往更容易求解;二者可以自然的引入核函數(shù)。進(jìn)而推廣到非線性分類問題
我們通過給每一個約束條件加上一個拉格朗日乘子(Lagrange multiplier)
,定義拉格朗日函數(shù)(通過拉格朗日函數(shù)將約束條件融合到目標(biāo)函數(shù)里,從而只用一個函數(shù)表達(dá)式能夠清楚表達(dá)問題):
然后令:
如果沒有對的限制,
會等于無窮大
容易驗(yàn)證,當(dāng)所有約束條件都得到滿足時,則有
,亦即最初要最小化的量,所以等價于直接最小化
![]()
故目標(biāo)函數(shù)變成:
這里用表示這個問題的最優(yōu)值,且和最初的問題是等價的。如果直接求解,那么一上來便得應(yīng)對
和
兩個參數(shù),而
又是不等式約束,這個求解過程不好做??梢园炎钚〉淖畲蟮奈恢米儞Q一下,變成:
交換以后的新問題是原始問題的對偶問題,這個問題的最優(yōu)值用來表示。而且有
。在滿足某些條件的情況下,兩者等價,這個時候就可以用求解對偶問題來間接地求解原始問題。
上面提到 “
在滿足某些條件的情況下,兩者等價”,這所謂的“滿足某些條件”就是要滿足
條件。經(jīng)過證明(省略),這里的問題是滿足
條件的,因此現(xiàn)在轉(zhuǎn)化為求解第二個問題。而求解這個對偶問題,分為3個步驟:1.首先要讓
關(guān)于
和
最小化,2.然后求對
的極大,3.最后利用
算法求解對偶問題中的拉格朗日乘子。
1.首先固定
,要讓
關(guān)于
和
最小化,我們分別對
,
求偏導(dǎo)數(shù),即令
和
等于零:
將其帶入之前的,得到:
2.對
求極大,即是關(guān)于對偶問題的最優(yōu)化問題。根據(jù)上式有:
如果求出了根據(jù):
即可求出,最終得出分類超平面和分類決策函數(shù)
3.求解上式
等價于求解(這個等價引入了后面的松弛變量,及對偶原則,不加證明):
下面要解決的問題就是:在上求上述目標(biāo)函數(shù)的最小值。為了求解這些乘子,每次從中任意抽取兩個乘子
和
,然后固定
和
以外的其它乘子
,使得目標(biāo)函數(shù)只是關(guān)于
和
的函數(shù)。這樣,不斷的從一堆乘子中任意抽取兩個求解,不斷的迭代求解子問題,最終達(dá)到求解原問題的目的。
(具體如何求解,略)
根據(jù)前面推導(dǎo)的:
帶入分類函數(shù)有:
通過這種形式我們觀察到,對于新點(diǎn)x的預(yù)測,只需要計(jì)算它與訓(xùn)練數(shù)據(jù)點(diǎn)的內(nèi)積即可,這一點(diǎn)至關(guān)重要,是之后使用Kernel進(jìn)行非線性推廣的基本前提。此外,所謂Supporting Vector 也在這里顯示出來——事實(shí)上,所有非Supporting Vector 所對應(yīng)的系數(shù)都是等于零的,因此對于新點(diǎn)的內(nèi)積計(jì)算實(shí)際上只要針對少量的“支持向量”而不是所有的訓(xùn)練數(shù)據(jù)即可。
到目前為止,我們的SVM還比較弱,只能處理線性的情況,不過,在得到對偶形式之后,通過Kernel推廣到非線性的情況就變成一件比較容易的事情。
我們觀察一下下面的數(shù)據(jù):
X,y = make_blobs(centers=4, random_state=8)
y = y%2
mglearn.discrete_scatter(X[:,0],X[:,1],y)
plt.xlabel('Feature 0')
plt.ylabel('Feature 1')

對于上面的數(shù)據(jù),我們可以知道他們是線性不可分的,對于非線性的情況,SVM的處理方法是選擇一個核函數(shù)K(.,.),通過將數(shù)據(jù)映射到高維空間,來解決在原始空間中先行不可分的問題。
為了理解這個過程(映射到高維空間),我們簡單的假設(shè)添加第二個特征的平方作為一個新特征,生成一個三維圖。
X_new = np.hstack([X, X[:,1:]** 2])
from mpl_toolkits.mplot3d import Axes3D,axes3d
figure = plt.figure()
ax=Axes3D(figure, elev=-152, azim=-26)
mask = y == 0
ax.scatter(X_new[mask,0],X_new[mask,1],X_new[mask,2],c='b',
cmap=mglearn.cm2, s=60)
ax.scatter(X_new[~mask,0],X_new[~mask,1],X_new[~mask,2],c='r',marker='^',cmap=mglearn.cm2, s=60)
ax.set_xlabel("feature0")
ax.set_ylabel("feature1")
ax.set_zlabel("feature1**2")

現(xiàn)在我們可以用線性模型將這兩個類別分開。
linear_svm_3d = LinearSVC().fit(X_new, y)
coef, intercept = linear_svm_3d.coef_.ravel(),linear_svm_3d.intercept_
figure = plt.figure()
ax = Axes3D(figure, elev=-152, azim=-26)
xx = np.linspace(X_new[:,0].min()-2,X_new[:,0].max()+2,50)
yy = np.linspace(X_new[:,1].min()-2,X_new[:,1].max()+2,50)
XX,YY = np.meshgrid(xx,yy)
ZZ = (coef[0] * XX + coef[1] * YY + intercept) / -coef[2]
ax.plot_surface(XX,YY,ZZ,rstride=8,cstride=8,alpha=0.6)
ax.scatter(X_new[mask,0], X_new[mask,1], X_new[mask,2],c='b',
cmap=mglearn.cm2,s=60)
ax.scatter(X_new[~mask,0], X_new[~mask,1], X_new[~mask,2],c='r',marker='^',
cmap=mglearn.cm2,s=60)

如果將線性SVM模型看作原始特征的函數(shù),那么它實(shí)際上已經(jīng)不是線性的了。他不是一條直線,而是一個橢圓
ZZ = YY**2
dec = linear_svm_3d.decision_function(np.c_[XX.ravel(),YY.ravel(),ZZ.ravel()])
plt.contourf(XX, YY, dec.reshape(XX.shape), levels=[dec.min(),0,dec.max()],cmap=mglearn.cm2, alpha=0.5)
mglearn.discrete_scatter(X[:,0],X[:,1],y)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

從上面的例子中,我們簡單的理解了一下處理非線性的方法
支持向量機(jī)首先在低維空間中完成計(jì)算,然后通過核函數(shù)將輸入空間映射到高維特征空間,最終在高維特征空間中構(gòu)造出最優(yōu)分離超平面,從而把平面上本身不好分的非線性數(shù)據(jù)分開。
而在我們遇到核函數(shù)之前,如果用原始的方法,那么在用線性學(xué)習(xí)器學(xué)習(xí)一個非線性關(guān)系,需要選擇一個非線性特征集,并且將數(shù)據(jù)寫成新的表達(dá)形式,這等價于應(yīng)用一個固定的非線性映射,將數(shù)據(jù)映射到特征空間,在特征空間中使用線性學(xué)習(xí)器,因此,考慮的假設(shè)集是這種類型的函數(shù):
這里的:
是從輸入空間到某個特征空間的映射,這意味著建立非線性學(xué)習(xí)器分為兩步:
1.首先使用一個非線性映射將數(shù)據(jù)變換到一個特征空間;
2.然后在特征空間使用線性學(xué)習(xí)器分類。
根據(jù)之前導(dǎo)出的內(nèi)積形式:
及上面所述,我們可以在原始特征空間中直接計(jì)算內(nèi)積,就有可能將兩個步驟融合到一起建立一個非線性的學(xué)習(xí)器,這樣直接計(jì)算法的方法稱為核函數(shù)方法
核(Kernel)是一個函數(shù)K,對所有的
,滿足
,這里
是從
到內(nèi)積特征空間
的映射
an1 = np.linspace(0, 2*np.pi, 100)
an2 = np.linspace(0, 2*np.pi, 100)
fig,ax = plt.subplots()
ax.plot(3*np.cos(an1)+np.random.rand(100)*0.3, 3*np.sin(an1)+np.random.rand(100)*0.3,'.')
ax.plot(2*np.cos(an2)+np.random.rand(100)*0.3, 2*np.sin(an2)+np.random.rand(100)*0.3,'.')

對于上面的數(shù)據(jù),(用兩個橢圓加了點(diǎn)噪聲生成),理想的分界應(yīng)該是一個“圓圈”,我們知道任意一條二次曲線都可以寫成下面的形式:
注意上面的形式,如果我們構(gòu)造另外一個五維的空間,其中五個坐標(biāo)的值分別為
,那么上面的方程在新的坐標(biāo)系下可以寫成:
此時的坐標(biāo),是一個超平面方程,也就是,我們做的一個映射
:
,將
按照上面的規(guī)則映射為
,那么在新的空間中原來的數(shù)據(jù)將變成線性可分的(可以參照上面的特征平方的例子)。這正是Kernel方法處理非線性問題的基本思想。
核函數(shù)相當(dāng)于把原來的分類函數(shù):
映射成:
這樣看似我們的問題得到了解決,其實(shí)不然,因?yàn)槲覀儼l(fā)現(xiàn)對一個二維空間做映射,得到一個五維空間。如果原始空間是三維的話,那么就會得到一個19維空間,這會給計(jì)算帶來非常大的困難。如果遇到無窮維的情況,就變得無從計(jì)算。
我們從剛才的例子出發(fā)。設(shè)兩個向量
和
映射后的內(nèi)積為:
另外我們注意到:
兩者有很多相似的地方,實(shí)際上,上面這個式子的計(jì)算結(jié)果實(shí)際上和映射:
之后的內(nèi)積的結(jié)果是相等的,它們的區(qū)別在于:
1.一個是映射到高維空間中,然后再根據(jù)內(nèi)積的公式進(jìn)行計(jì)算;
2.而另一個則直接在原來的低維空間中進(jìn)行計(jì)算,而不需要顯式地寫出映射后的結(jié)果。
我們把計(jì)算兩個向量在隱式映射過后的空間中的內(nèi)積的函數(shù)叫做核函數(shù)。
常用的核函數(shù)有:
1.多項(xiàng)式核
2.高斯核(通過調(diào)控
,高斯核實(shí)際上具有相當(dāng)高的靈活性)
3.線性核
到此為止,還有些問題沒有解決。例如可能并不是因?yàn)閿?shù)據(jù)本身是非線性結(jié)構(gòu)的,而只是因?yàn)閿?shù)據(jù)有噪聲。對于這種偏離正常位置很遠(yuǎn)的數(shù)據(jù)點(diǎn),我們稱之為outlier,outlier的存在有可能造成很大的影響,因?yàn)槌矫姹旧砭褪侵挥猩贁?shù)幾個support vector組成的,這樣就會造成很大的影響。
為此我們引入松弛變量,那么約束條件變成:
它為對應(yīng)數(shù)據(jù)點(diǎn)允許偏移的量,但是
又不能隨意擴(kuò)大,所以我們在目標(biāo)函數(shù)后加一項(xiàng),使得
總和最小:
其中C是一個參數(shù),用于控制目標(biāo)函數(shù)中兩項(xiàng)(“尋找margin最大的超平面”和“保證數(shù)據(jù)點(diǎn)偏移量最小”)之間的權(quán)重。用之前的方法將限制約束條件加入到目標(biāo)函數(shù)中,得到新的拉格朗日函數(shù),如下所示:
經(jīng)過計(jì)算,現(xiàn)在問題寫作:
這樣一個稍微完整的,可以處理線性核非線性并能容忍噪聲和outliers的支持向量機(jī)差不多簡單介紹完了。