【機(jī)器學(xué)習(xí)基礎(chǔ)】(四):通俗理解支持向量機(jī)SVM及代碼實(shí)踐
上一篇文章我們介紹了使用邏輯回歸來(lái)處理分類問(wèn)題,本文我們講一個(gè)更強(qiáng)大的分類模型。本文依舊側(cè)重代碼實(shí)踐,你會(huì)發(fā)現(xiàn)我們解決問(wèn)題的手段越來(lái)越豐富,問(wèn)題處理起來(lái)越來(lái)越簡(jiǎn)單。
支持向量機(jī)(Support Vector Machine, SVM)是最受歡迎的機(jī)器學(xué)習(xí)模型之一。它特別適合處理中小型復(fù)雜數(shù)據(jù)集的分類任務(wù)。
一、什么是支持向量機(jī)
SMV在眾多實(shí)例中尋找一個(gè)最優(yōu)的決策邊界,這個(gè)邊界上的實(shí)例叫做支持向量,它們“支持”(支撐)分離開(kāi)超平面,所以它叫支持向量機(jī)。
那么我們?nèi)绾伪WC我們得到的決策邊界是最優(yōu)的呢?

如上圖,三條黑色直線都可以完美分割數(shù)據(jù)集。由此可知,我們僅用單一直線可以得到無(wú)數(shù)個(gè)解。那么,其中怎樣的直線是最優(yōu)的呢?

如上圖,我們計(jì)算直線到分割實(shí)例的距離,使得我們的直線與數(shù)據(jù)集的距離盡可能的遠(yuǎn),那么我們就可以得到唯一的解。最大化上圖虛線之間的距離就是我們的目標(biāo)。而上圖中重點(diǎn)圈出的實(shí)例就叫做支持向量。
這就是支持向量機(jī)。
二、從代碼中映射理論
2.1 導(dǎo)入數(shù)據(jù)集
添加引用:
import?numpy?as?np
import?pandas?as?pd
import?seaborn?as?sns
import?matplotlib.pyplot?as?plt
導(dǎo)入數(shù)據(jù)集(大家不用在意這個(gè)域名):
df?=?pd.read_csv('https://blog.caiyongji.com/assets/mouse_viral_study.csv')
df.head()
| Med_1_mL | Med_2_mL | Virus Present | |
|---|---|---|---|
| 0 | 6.50823 | 8.58253 | 0 |
| 1 | 4.12612 | 3.07346 | 1 |
| 2 | 6.42787 | 6.36976 | 0 |
| 3 | 3.67295 | 4.90522 | 1 |
| 4 | 1.58032 | 2.44056 | 1 |
該數(shù)據(jù)集模擬了一項(xiàng)醫(yī)學(xué)研究,對(duì)感染病毒的小白鼠使用不同劑量的兩種藥物,觀察兩周后小白鼠是否感染病毒。
特征:1. 藥物Med_1_mL 藥物Med_2_mL 標(biāo)簽:是否感染病毒(1感染/0不感染)
2.2 觀察數(shù)據(jù)
sns.scatterplot(x='Med_1_mL',y='Med_2_mL',hue='Virus?Present',data=df)
我們用seaborn繪制兩種藥物在不同劑量特征對(duì)應(yīng)感染結(jié)果的散點(diǎn)圖。

sns.pairplot(df,hue='Virus?Present')
我們通過(guò)pairplot方法繪制特征兩兩之間的對(duì)應(yīng)關(guān)系。

我們可以做出大概的判斷,當(dāng)加大藥物劑量可使小白鼠避免被感染。
2.3 使用SVM訓(xùn)練數(shù)據(jù)集
#SVC:?Supprt?Vector?Classifier支持向量分類器
from?sklearn.svm?import?SVC
#準(zhǔn)備數(shù)據(jù)
y?=?df['Virus?Present']
X?=?df.drop('Virus?Present',axis=1)?
#定義模型
model?=?SVC(kernel='linear',?C=1000)
#訓(xùn)練模型
model.fit(X,?y)
#?繪制圖像
#?定義繪制SVM邊界方法
def?plot_svm_boundary(model,X,y):
????
????X?=?X.values
????y?=?y.values
????
????#?Scatter?Plot
????plt.scatter(X[:,?0],?X[:,?1],?c=y,?s=30,cmap='coolwarm')
????
????#?plot?the?decision?function
????ax?=?plt.gca()
????xlim?=?ax.get_xlim()
????ylim?=?ax.get_ylim()
????#?create?grid?to?evaluate?model
????xx?=?np.linspace(xlim[0],?xlim[1],?30)
????yy?=?np.linspace(ylim[0],?ylim[1],?30)
????YY,?XX?=?np.meshgrid(yy,?xx)
????xy?=?np.vstack([XX.ravel(),?YY.ravel()]).T
????Z?=?model.decision_function(xy).reshape(XX.shape)
????#?plot?decision?boundary?and?margins
????ax.contour(XX,?YY,?Z,?colors='k',?levels=[-1,?0,?1],?alpha=0.5,
???????????????linestyles=['--',?'-',?'--'])
????#?plot?support?vectors
????ax.scatter(model.support_vectors_[:,?0],?model.support_vectors_[:,?1],?s=100,
???????????????linewidth=1,?facecolors='none',?edgecolors='k')
????plt.show()
plot_svm_boundary(model,X,y)

我們導(dǎo)入sklearn下的SVC(Supprt Vector Classifier)分類器,它是SVM的一種實(shí)現(xiàn)。
2.4 SVC參數(shù)C
SVC方法參數(shù)C代表L2正則化參數(shù),正則化的強(qiáng)度與C的值成反比,即C值越大正則化強(qiáng)度越弱,其必須嚴(yán)格為正。
model?=?SVC(kernel='linear',?C=0.05)
model.fit(X,?y)
plot_svm_boundary(model,X,y)
我們減少C的值,可以看到模型擬合數(shù)據(jù)的程度減弱。

2.5 核技巧
SVC方法的kernel參數(shù)可取值{'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'}。像前文中所使用的那樣,我們可以使kernel='linear'進(jìn)行線性分類。那么如果我們想進(jìn)行非線性分類呢?
2.5.1 多項(xiàng)式內(nèi)核
多項(xiàng)式內(nèi)核kernel='poly'的原理簡(jiǎn)單來(lái)說(shuō)就是,用單一特征生成多特征來(lái)擬合曲線。比如我們拓展X到y(tǒng)的對(duì)應(yīng)關(guān)系如下:
| X | X^2 | X^3 | y | |
|---|---|---|---|---|
| 0 | 6.50823 | 6.50823**2 | 6.50823**3 | 0 |
| 1 | 4.12612 | 4.12612**2 | 4.12612**3 | 1 |
| 2 | 6.42787 | 6.42787**2 | 6.42787**3 | 0 |
| 3 | 3.67295 | 3.67295**2 | 3.67295**3 | 1 |
| 4 | 1.58032 | 1.58032**2 | 1.58032**3 | 1 |
這樣我們就可以用曲線來(lái)擬合數(shù)據(jù)集。
model?=?SVC(kernel='poly',?C=0.05,degree=5)
model.fit(X,?y)
plot_svm_boundary(model,X,y)
我們使用多項(xiàng)式內(nèi)核,并通過(guò)degree=5設(shè)置多項(xiàng)式的最高次數(shù)為5。我們可以看出分割出現(xiàn)了一定的弧度。

2.5.2 高斯RBF內(nèi)核
SVC方法默認(rèn)內(nèi)核為高斯RBF,即Radial Basis Function(徑向基函數(shù))。這時(shí)我們需要引入gamma參數(shù)來(lái)控制鐘形函數(shù)的形狀。增加gamma值會(huì)使鐘形曲線變得更窄,因此每個(gè)實(shí)例影響的范圍變小,決策邊界更不規(guī)則。減小gamma值會(huì)使鐘形曲線變得更寬,因此每個(gè)實(shí)例的影響范圍變大,決策邊界更平坦。
model?=?SVC(kernel='rbf',?C=1,gamma=0.01)
model.fit(X,?y)
plot_svm_boundary(model,X,y)

2.6 調(diào)參技巧:網(wǎng)格搜索
from?sklearn.model_selection?import?GridSearchCV
svm?=?SVC()
param_grid?=?{'C':[0.01,0.1,1],'kernel':['rbf','poly','linear','sigmoid'],'gamma':[0.01,0.1,1]}
grid?=?GridSearchCV(svm,param_grid)
grid.fit(X,y)
print("grid.best_params_?=?",grid.best_params_,",?grid.best_score_?="?,grid.best_score_)
我們可以通過(guò)GridSearchCV方法來(lái)遍歷超參數(shù)的各種可能性來(lái)尋求最優(yōu)超參數(shù)。這是通過(guò)算力碾壓的方式暴力調(diào)參的手段。當(dāng)然,在分析問(wèn)題階段,我們必須限定了各參數(shù)的可選范圍才能應(yīng)用此方法。
因?yàn)閿?shù)據(jù)集太簡(jiǎn)單,我們?cè)诒闅v第一種可能性時(shí)就已經(jīng)得到100%的準(zhǔn)確率了,輸出如下:
grid.best_params_?=??{'C':?0.01,?'gamma':?0.01,?'kernel':?'rbf'}?,?grid.best_score_?=?1.0
總結(jié)
當(dāng)我們處理線性可分的數(shù)據(jù)集時(shí),可以使用SVC(kernel='linear')方法來(lái)訓(xùn)練數(shù)據(jù),當(dāng)然我們也可以使用更快的方法LinearSVC來(lái)訓(xùn)練數(shù)據(jù),特別是當(dāng)訓(xùn)練集特別大或特征非常多的時(shí)候。
當(dāng)我們處理非線性SVM分類時(shí),可以使用高斯RBF內(nèi)核,多項(xiàng)式內(nèi)核,sigmoid內(nèi)核來(lái)進(jìn)行非線性模型的的擬合。當(dāng)然我們也可以通過(guò)GridSearchCV尋找最優(yōu)參數(shù)。
往期文章:
機(jī)器學(xué)習(xí)(三):理解邏輯回歸及二分類、多分類代碼實(shí)踐 機(jī)器學(xué)習(xí)(二):理解線性回歸與梯度下降并做簡(jiǎn)單預(yù)測(cè) 機(jī)器學(xué)習(xí)(一):5分鐘理解機(jī)器學(xué)習(xí)并上手實(shí)踐 前置機(jī)器學(xué)習(xí)(五):30分鐘掌握常用Matplotlib用法 前置機(jī)器學(xué)習(xí)(四):一文掌握Pandas用法 前置機(jī)器學(xué)習(xí)(三):30分鐘掌握常用NumPy用法 前置機(jī)器學(xué)習(xí)(二):30分鐘掌握常用Jupyter Notebook用法 前置機(jī)器學(xué)習(xí)(一):數(shù)學(xué)符號(hào)及希臘字母
往期精彩回顧
本站qq群704220115,加入微信群請(qǐng)掃碼:
