支持向量機(SVM)廣泛應用於模式分類和非線性迴歸領域。SVM算法的原始形式由Vladimir N.Vapnik和Alexey Ya提出。自從那以後,SVM已經被巨大地改變以成功地用於許多現實世界問題。
1.什麼是支持向量機(SVM)?
支持向量機是一種有監督的機器學習算法,可用於分類和迴歸問題。它遵循一種用核函數技巧來轉換數據的技術,並且基於這些轉換,它找到可能輸出之間的最佳邊界。
簡單來說,它做一些非常複雜的數據轉換,以找出如何根據標籤或輸出定義的數據分離。本文我們將看到SVM分類算法如何通過python實現並可視化。
2.SVM的原理
尋找一個分離超平面,使得它到各分類的平均距離是最大的。
什麼是分離超平面?
把數據劃分爲多個類別的一個圖形,如線、面、超平面,我們統稱爲超平面。
一個最簡單的示例,即數據集位於2維平面中,一條線就可以把樣本分成兩類。但是支持向量機也可以用於一般的n維數據集,所以我們統稱超平面。
更正式地說,它是n維歐幾里德空間的n-1維子空間。所以一個
1維數據集,單點表示超平面。
2維數據集,線是超平面。
3維數據集,平面是超平面。
在更高的維度上,就被稱爲超平面。
SVM的目標是找到最佳分離超平面。那麼什麼時候分離超平面是最優的?讓我們通過一組圖來理解最佳超平面。
有多個超平面,但其中哪一個是分離超平面?可以很容易地看出,線B是比較好地分離這兩個類的線,但我們如何計算出來最佳的超平面呢?
直觀地,如果我們選擇接近一個類的數據點的超平面,那麼它可能不能很好地推廣。因此,要選擇儘可能遠離每個類別的數據點的超平面。
在上圖中,滿足指定條件的最佳超平面爲B。
因此,最大化每個類的最近點和超平面之間的距離就能找到最優分離超平面。這個距離稱爲邊距,下圖是邊距的計算原理圖。
SVM的目標是找到最佳超平面,因爲它不僅分類現有數據集,而且有助於預測未知數據的類。最優超平面是邊距最大的平面。
3、支持向量機的優缺點
每個分類算法都有自己的優點和缺點,它們根據正在分析的數據集發揮作用。
SVM的一些優點如下:
凸優化方法的本質是保證最優性。該解決方案保證是全局最小值,而不是局部最小值
SVM是一種適用於線性和非線性可分離數據(使用核函數技巧)的算法。唯一要做的是找出正則化項C。
SVM在低維和高維數據空間上工作良好。它能有效地對高維數據集工作,因爲SVM中的訓練數據集的複雜度通常由支持向量的數量而不是維度來表徵。即使刪除所有其他訓練示例並重複訓練,我們將獲得相同的最佳分離超平面。
SVM可以在較小的訓練數據集上工作,因爲它們不依賴於整個數據。
SVM的缺點如下:
它們不適合較大的數據集,因爲在較大的數據集上使用SVM的訓練時間可能很高,並且計算量更大。
它們在具有重疊類的嘈雜數據集上效率較低。
4、Python實現
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 初始化數據
從datasets數據集中加載iris數據,提取data中的兩列作爲特徵值,提取target爲分類值,並把特徵值和分類值轉換爲pandas的DataFrame數據框,併合併到data中,重命名各特徵爲x1,x2和y。
找出x1和x2的最大值和最小值,生成滿布座標系的點,用於描繪超平面。
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用散點圖描繪出來,如下圖。
在這個圖中我們看到有三個分類,接下來我們用SVM支持向量機爲這些訓練數據建立一個模型。
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)
用數據集合的80%作爲訓練集,建立一個C=0.1的線性SVM模型,並用data的所有x1和x2用這個SVM模型去預測y,預測的y和原來的y計算準確率。
accuracy_score(data.y,y_pre)
結果0.95333333333333337,即約95.33%的準確率,可以和上面第一個圖進行精細對比是哪個點分類錯了。
4.4 尋找最好的模型
我們通過網格搜索,尋找一個最好的模型。GridSearchCV可以配置一個參數列表(超參數)、模型,在這個超參數中自動尋找最好的模型。GridSearchCV已經自動按照cv=5把樣本分成5等分進行訓練和驗證的了。
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_
結果如下:
自動尋找到上面的紅色框的模型參數,準確率是96.67%。
從上表可以看出來核函數rbf的擬合比較好。那麼我們再用GridSearchCV去變量rbf的degree看看能不能有進一步優化的空間。
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_
最好的結果是:
{‘C’: 0.10000000000000001, ‘degree’: 2},
0.9666666666666668)
沒有得到進一步優化。
接下來我們就用rbf核函數c=0.1去重新建立模型並看看可視化的效果。
4.5 最優模型
我們直接用全集去擬合這個c=0.1,核函數rbf的SVM模型。我們看看可視化的結果。
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)
準確率爲0.96666666666666667,即96.67%
4.6 學習曲線
接下來我們就用這個模型看看樣本的學習曲線
scores = []
for m in range(2,X_train.size):#循環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)
可以看出來,樣本引入50個後,模型的準確率已經穩定下來了。
長按二維碼關注