支持向量機(jī)(SVM)廣泛應(yīng)用于模式分類和非線性回歸領(lǐng)域。 SVM算法的原始形式由Vladimir N.Vapnik和Alexey Ya提出。自從那以后,SVM已經(jīng)被巨大地改變以成功地用于許多現(xiàn)實(shí)世界問(wèn)題。
1.什么是支持向量機(jī)(SVM)?
支持向量機(jī)是一種有監(jiān)督的機(jī)器學(xué)習(xí)算法,可用于分類和回歸問(wèn)題。它遵循一種用核函數(shù)技巧來(lái)轉(zhuǎn)換數(shù)據(jù)的技術(shù),并且基于這些轉(zhuǎn)換,它找到可能輸出之間的最佳邊界。簡(jiǎn)單來(lái)說(shuō),它做一些非常復(fù)雜的數(shù)據(jù)轉(zhuǎn)換,以找出如何根據(jù)標(biāo)簽或輸出定義的數(shù)據(jù)分離。本文我們將看到SVM分類算法如何通過(guò)python實(shí)現(xiàn)并可視化。
2.SVM的原理
尋找一個(gè)分離超平面,使得它到各分類的平均距離是最大的。
什么是分離超平面?
把數(shù)據(jù)劃分為多個(gè)類別的一個(gè)圖形,如線、面、超平面,我們統(tǒng)稱為超平面。一個(gè)最簡(jiǎn)單的示例,即數(shù)據(jù)集位于2維平面中,一條線就可以把樣本分成兩類。但是支持向量機(jī)也可以用于一般的n維數(shù)據(jù)集,所以我們統(tǒng)稱超平面。更正式地說(shuō),它是n維歐幾里德空間的n-1維子空間。
所以一個(gè)
- 1維數(shù)據(jù)集,單點(diǎn)表示超平面。
- 2維數(shù)據(jù)集,線是超平面。
- 3維數(shù)據(jù)集,平面是超平面。
- 在更高的維度上,就被稱為超平面。
SVM的目標(biāo)是找到最佳分離超平面。那么什么時(shí)候分離超平面是最優(yōu)的?讓我們通過(guò)一組圖來(lái)理解最佳超平面。有多個(gè)超平面,但其中哪一個(gè)是分離超平面? 可以很容易地看出,線B是比較好地分離這兩個(gè)類的線,但我們?nèi)绾斡?jì)算出來(lái)最佳的超平面呢?

直觀地,如果我們選擇接近一個(gè)類的數(shù)據(jù)點(diǎn)的超平面,那么它可能不能很好地推廣。因此,要選擇盡可能遠(yuǎn)離每個(gè)類別的數(shù)據(jù)點(diǎn)的超平面。

在上圖中,滿足指定條件的最佳超平面為B。
因此,最大化每個(gè)類的最近點(diǎn)和超平面之間的距離就能找到最優(yōu)分離超平面。這個(gè)距離稱為邊距,下圖是邊距的計(jì)算原理圖。

SVM的目標(biāo)是找到最佳超平面,因?yàn)樗粌H分類現(xiàn)有數(shù)據(jù)集,而且有助于預(yù)測(cè)未知數(shù)據(jù)的類。最優(yōu)超平面是邊距最大的平面。
3、支持向量機(jī)的優(yōu)缺點(diǎn)
每個(gè)分類算法都有自己的優(yōu)點(diǎn)和缺點(diǎn),它們根據(jù)正在分析的數(shù)據(jù)集發(fā)揮作用。
SVM的一些優(yōu)點(diǎn)如下:
- 凸優(yōu)化方法的本質(zhì)是保證最優(yōu)性。該解決方案保證是全局最小值,而不是局部最小值
- SVM是一種適用于線性和非線性可分離數(shù)據(jù)(使用核函數(shù)技巧)的算法。唯一要做的是找出正則化項(xiàng)C
- SVM在低維和高維數(shù)據(jù)空間上工作良好。它能有效地對(duì)高維數(shù)據(jù)集工作,因?yàn)镾VM中的訓(xùn)練數(shù)據(jù)集的復(fù)雜度通常由支持向量的數(shù)量而不是維度來(lái)表征。即使刪除所有其他訓(xùn)練示例并重復(fù)訓(xùn)練,我們將獲得相同的最佳分離超平面。
- SVM可以在較小的訓(xùn)練數(shù)據(jù)集上工作,因?yàn)樗鼈儾灰蕾囉谡麄€(gè)數(shù)據(jù)。
SVM的缺點(diǎn)如下:
- 它們不適合較大的數(shù)據(jù)集,因?yàn)樵谳^大的數(shù)據(jù)集上使用SVM的訓(xùn)練時(shí)間可能很高,并且計(jì)算量更大。
- 它們?cè)诰哂兄丿B類的嘈雜數(shù)據(jù)集上效率較低。
4、Python實(shí)現(xiàn)
4.1 加載需要用到的模塊
- import numpy as np
- from sklearn import datasets
- from sklearn.pipeline import Pipeline
- from sklearn.svm import SVC
- import seaborn as sns
- import pandas as pd
- from sklearn.model_selection import cross_val_score
- from sklearn.grid_search import GridSearchCV
- from sklearn.model_selection import train_test_split
- from sklearn.metrics import accuracy_score
- import matplotlib.pyplot as plt
4.2 初始化數(shù)據(jù)
從datasets數(shù)據(jù)集中加載iris數(shù)據(jù),提取data中的兩列作為特征值,提取target為分類值,并把特征值和分類值轉(zhuǎn)換為pandas的DataFrame數(shù)據(jù)框,并合并到data中,重命名各特征為x1,x2和y。
找出x1和x2的最大值和最小值,生成滿布坐標(biāo)系的點(diǎn),用于描繪超平面。
- iris = datasets.load_iris()
- X = iris['data'][:,[2,3]]
- y = iris['target']
- X = pd.DataFrame(X)
- y = pd.DataFrame(y)
- data = pd.merge(X,y,left_index=True,right_index=True,how='outer')
- data.columns=['x1','x2','y']
- h = 0.002
- x_min, x_max = data.x1.min() - 0.2, data.x1.max() + 0.2
- y_min, y_max = data.x2.min() - 0.2, data.x2.max() + 0.2
- xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
- np.arange(y_min, y_max, h))
- sns.scatterplot(data.x1, y=data.x2,hue=data.y)
- X = data[['x1','x2']]
- y = data.y
我們用seaborn的scatterplot把x1和x2用散點(diǎn)圖描繪出來(lái),如下圖。

在這個(gè)圖中我們看到有三個(gè)分類,接下來(lái)我們用SVM支持向量機(jī)為這些訓(xùn)練數(shù)據(jù)建立一個(gè)模型。
4.3 線性SVM模型
- X_train,X_val,y_train,y_val = train_test_split(X,y,test_size=0.2) #80%和20%劃分X和y
- clf = SVC(C=0.1,kernel='linear')
- clf.fit(X_train,y_train)
- y_pre = clf.predict(X)
- Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
- Z = Z.reshape(xx.shape)
- sns.scatterplot(data.x1, y=data.x2,hue=y_pre)
- plt.contourf(xx, yy, Z, cmap=plt.cm.ocean, alpha=0.2)
- accuracy_score(data.y,y_pre)
用數(shù)據(jù)集合的80%作為訓(xùn)練集,建立一個(gè)C=0.1的線性SVM模型,并用data的所有x1和x2用這個(gè)SVM模型去預(yù)測(cè)y,預(yù)測(cè)的y和原來(lái)的y計(jì)算準(zhǔn)確率。

- accuracy_score(data.y,y_pre)
結(jié)果0.95333333333333337,即約95.33%的準(zhǔn)確率,可以和上面第一個(gè)圖進(jìn)行精細(xì)對(duì)比是哪個(gè)點(diǎn)分類錯(cuò)了。
4.4 尋找最好的模型
我們通過(guò)網(wǎng)格搜索,尋找一個(gè)最好的模型。GridSearchCV可以配置一個(gè)參數(shù)列表(超參數(shù))、模型,在這個(gè)超參數(shù)中自動(dòng)尋找最好的模型。GridSearchCV已經(jīng)自動(dòng)按照cv=5把樣本分成5等分進(jìn)行訓(xùn)練和驗(yàn)證的了。
- params = {'C':np.arange(0.1,1,0.1),'kernel':['linear', 'poly', 'rbf', 'sigmoid']}
- gsearch = GridSearchCV(estimator = SVC(kernel='linear'),
- param_grid = params, scoring='accuracy',iid=False, cv=5)
- gsearch.fit(X,data.y)
- gsearch.grid_scores_, gsearch.best_params_, gsearch.best_score_
結(jié)果如下:

自動(dòng)尋找到上面的紅色框的模型參數(shù),準(zhǔn)確率是96.67%。
從上表可以看出來(lái)核函數(shù)rbf的擬合比較好。那么我們?cè)儆肎ridSearchCV去變量rbf的degree看看能不能有進(jìn)一步優(yōu)化的空間。
- params = {'C':np.arange(0.1,1,0.1),'degree':np.arange(1,5,1)}
- gsearch = GridSearchCV(estimator = SVC(kernel='poly'),
- param_grid = params, scoring='accuracy',iid=False, cv=5)
- gsearch.fit(X,data.y)
- gsearch.grid_scores_, gsearch.best_params_, gsearch.best_score_
最好的結(jié)果是:
{‘C’: 0.10000000000000001, ‘degree’: 2},
0.9666666666666668)
沒有得到進(jìn)一步優(yōu)化。
接下來(lái)我們就用rbf核函數(shù)c=0.1去重新建立模型并看看可視化的效果。
4.5 最優(yōu)模型
我們直接用全集去擬合這個(gè)c=0.1,核函數(shù)rbf的SVM模型。我們看看可視化的結(jié)果。
clf = SVC(C=0.2,kernel='rbf')
clf.fit(X,y)
y_pre = clf.predict(X)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
ax = sns.scatterplot(data.x1, y=data.x2,hue=y_pre)
ax.legend(loc="lower right")
plt.contourf(xx, yy, Z, cmap=plt.cm.ocean, alpha=0.2)

- accuracy_score(data.y,y_pre)
準(zhǔn)確率為0.96666666666666667,即96.67%
4.6 學(xué)習(xí)曲線
接下來(lái)我們就用這個(gè)模型看看樣本的學(xué)習(xí)曲線
- scores = []
- for m in range(2,X_train.size):#循環(huán)2-79
- clf.fit(X_train[:m],y_train[:m])
- y_train_predict = clf.predict(X_train[:m])
- y_val_predict = clf.predict(X_val)
- scores.append(accuracy_score(y_train_predict,y_train[:m]))
- plt.plot(range(2,X_train.size),scores,c='green', alpha=0.6)

可以看出來(lái),樣本引入50個(gè)后,模型的準(zhǔn)確率已經(jīng)穩(wěn)定下來(lái)了。