sklearn保存svm分类模型_【菜菜的sklearn】07 支持向量机(上)
小伙伴們大家好~o( ̄▽ ̄)ブ,我是菜菜,這里是我的sklearn課堂第7期,今天分享的內容是支持向量機(上),下周還有下篇哦~
我的開發環境是Jupyter lab,所用的庫和版本大家參考:Python 3.7.1(你的版本至少要3.4以上Scikit-learn 0.20.1 (你的版本至少要0.20Numpy 1.15.4, Pandas 0.23.4, Matplotlib 3.0.2, SciPy 1.1.0本文主要內容:1 概述1.1 支持向量機分類器是如何工作的1.2 支持向量機原理的三層理解1.3 sklearn中的支持向量機2 sklearn.svm.SVC2.1 線性SVM用于分類2.1.1 線性SVM的損失函數2.1.3 線性SVM決策過程的可視化2.3 非線性SVM與核函數2.3.1 重要參數kernel & degree & gamma1 概述
支持向量機(SVM,也稱為支持向量網絡),是機器學習中獲得關注最多的算法沒有之一。它源于統計學習理論,是我們除了集成算法之外,接觸的第一個強學習器。它有多強呢?
從算法的功能來看,SVM幾乎囊括了我們前六周講解的所有算法的功能:
從分類效力來講,SVM在無論線性還是非線性分類中,都是明星般的存在:
從實際應用來看,SVM在各種實際問題中都表現非常優秀。它在手寫識別數字和人臉識別中應用廣泛,在文本和超文本的分類中舉足輕重,因為SVM可以大量減少標準歸納(standard inductive)和轉換設置(transductive settings)中對標記訓練實例的需求。同時,SVM也被用來執行圖像的分類,并用于圖像分割系統。實驗結果表明,在僅僅三到四輪相關反饋之后,SVM就能實現比傳統的查詢細化方案(query refinement schemes)高出一大截的搜索精度。除此之外,生物學和許多其他科學都是SVM的青睞者,SVM現在已經廣泛被用于蛋白質分類,現在化合物分類的業界平均水平可以達到90%以上的準確率。在生物科學的尖端研究中,人們還使用支持向量機來識別用于模型預測的各種特征,以找出各種基因表現結果的影響因素。
從學術的角度來看,SVM是最接近深度學習的機器學習算法。線性SVM可以看成是神經網絡的單個神經元(雖然損失函數與神經網絡不同),非線性的SVM則與兩層的神經網絡相當,非線性的SVM中如果添加多個核函數,則可以模仿多層的神經網絡。而從數學的角度來看,SVM的數學原理是公認的對初學者來說難于上青天的水平,對于沒有數學基礎和數學邏輯熏陶的人來說,探究SVM的數學原理本身宛如在知識的荒原上跋涉。
當然了,沒有算法是完美的,比SVM強大的算法在集成學習和深度學習中還有很多很多。但不可否認,它是我們目前為止接觸到的最強大的算法。接下來的兩周,我們將一起來探索SVM的神秘世界。
1.1 支持向量機分類器是如何工作的
支持向量機所作的事情其實非常容易理解。先來看看下面這一組數據的分布,這是一組兩種標簽的數據,兩種標簽分別由圓和方塊代表。支持向量機的分類方法,是在這組分布中找出一個超平面作為決策邊界,使模型在數據上的分類誤差盡量接近于小,尤其是在未知數據集上的分類誤差(泛化誤差)盡量小。
關鍵概念:超平面在幾何中,超平面是一個空間的子空間,它是維度比所在空間小一維的空間。 如果數據空間本身是三維的,則其超平面是二維平面,而如果數據空間本身是二維的,則其超平面是一維的直線。
在二分類問題中,如果一個超平面能夠將數據劃分為兩個集合,其中每個集合中包含單獨的一個類別,我們就說這個超平面是數據的“決策邊界”。
決策邊界一側的所有點在分類為屬于一個類,而另一側的所有點分類屬于另一個類。如果我們能夠找出決策邊界,分類問題就可以變成探討每個樣本對于決策邊界而言的相對位置。比如上面的數據分布,我們很容易就可以在方塊和圓的中間畫出一條線,并讓所有落在直線左邊的樣本被分類為方塊,在直線右邊的樣本被分類為圓。如果把數據當作我們的訓練集,只要直線的一邊只有一種類型的數據,就沒有分類錯誤,我們的訓練誤差就會為0。
但是,對于一個數據集來說,讓訓練誤差為0的決策邊界可以有無數條。
但在此基礎上,我們無法保證這條決策邊界在未知數據集(測試集)上的表現也會優秀。對于現有的數據集來說,我們有
?和? 兩條可能的決策邊界。我們可以把決策邊界? 向兩邊平移,直到碰到離這條決策邊界最近的方塊和圓圈后停下,形成兩個新的超平面,分別是 ?和 ?,并且我們將原始的決策邊界移動到? 和 ?的中間,確保? 到 ?和 ?的距離相等。在 ?和? 中間的距離,叫做 ?這條決策邊界的邊際(margin),通常記作? 。對? 也執行同樣的操作,然后我們來對比一下兩個決策邊界。現在兩條決策邊界右邊的數據都被判斷為圓,左邊的數據都被判斷為方塊,兩條決策邊界在現在的數據集上的訓練誤差都是0,沒有一個樣本被分錯。我們引入和原本的數據集相同分布的測試樣本(紅色所示),平面中的樣本變多了,此時我們可以發現,對于
?而言,依然沒有一個樣本被分錯,這條決策邊界上的泛化誤差也是0。但是對于 ?而言,卻有三個方塊被誤人類成了圓,二有兩個圓被誤分類成了方塊,這條決策邊界上的泛化誤差就遠遠大于 ?了。這個例子表現出,擁有更大邊際的決策邊界在分類中的泛化誤差更小,這一點可以由結構風險最小化定律來證明(SRM)。如果邊際很小,則任何輕微擾動都會對決策邊界的分類產生很大的影響。邊際很小的情況,是一種模型在訓練集上表現很好,卻在測試集上表現糟糕的情況,所以會“過擬合”。所以我們在找尋決策邊界的時候,希望邊際越大越好。支持向量機,就是通過找出邊際最大的決策邊界,來對數據進行分類的分類器。也因此,支持向量分類器又叫做最大邊際分類器。這個過程在二維平面中看起來十分簡單,但將上述過程使用數學表達出來,就不是一件簡單的事情了。
1.2 支持向量機原理的三層理解
目標是"找出邊際最大的決策邊界",聽起來是一個十分熟悉的表達,這是一個最優化問題,而最優化問題往往和損失函數聯系在一起。和邏輯回歸中的過程一樣,SVM也是通過最小化損失函數來求解一個用于后續模型使用的重要信息:決策邊界。
1.3 sklearn中的支持向量機
注意,除了特別表明是線性的兩個類LinearSVC和LinearSVR之外,其他的所有類都是同時支持線性和非線性的。NuSVC和NuSVC可以手動調節支持向量的數目,其他參數都與最常用的SVC和SVR一致。注意OneClassSVM是無監督的類。
除了本身所帶的類之外,sklearn還提供了直接調用libsvm庫的幾個函數。Libsvm是臺灣大學林智仁(Lin Chih-Jen)教授等人開發設計的一個簡單、易于使用和快速有效的英文的SVM庫,它提供了大量SVM的底層計算和參數選擇,也是sklearn的眾多類背后所調用的庫。目前,LIBSVM擁有C、Java、Matlab、Python、R等數十種語言版本,每種語言版本都可以在libsvm的官網上進行下載:
https://www.csie.ntu.edu.tw/~cjlin/libsvm/?
2 sklearn.svm.SVC
class sklearn.svm.SVC(C=1.0, kernel=’rbf’, degree=3, gamma=’auto_deprecated’, coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape=’ovr’, random_state=None)
2.1 線性SVM用于分類
2.1.1 線性SVM的損失函數
要理解SVM的損失函數,我們先來定義決策邊界。假設現在數據中總計有N?個訓練樣本,每個訓練樣本
?可以被表示為 ?,其中 ?是? 這樣的一個特征向量,每個樣本總共含有?n個特征。二分類標簽? 的取值是{-1, 1}。如果n等于2,則有
?,分別由我們的特征向量和標簽組成。此時我們可以在二維平面上,以 ?為橫坐標,? 為縱坐標,?y為顏色,來可視化我們所有的N個樣本:我們讓所有紫色點的標簽為1,紅色點的標簽為-1。我們要在這個數據集上尋找一個決策邊界,在二維平面上,決策邊界(超平面)就是一條直線。二維平面上的任意一條線可以被表示為:
我們將此表達式變換一下:
其中[a, -1]就是我們的參數向量
?,? 就是我們的特征向量,? 是我們的截距。注意,這個表達式長得非常像我們線性回歸的公式: 線性回歸中等號的一邊是標簽,回歸過后會擬合出一個標簽,而決策邊界的表達式中卻沒有標簽的存在,全部是由參數,特征和截距組成的一個式子,等號的一邊是0。在一組數據下,給定固定的w?和?b,這個式子就可以是一條固定直線,在?w和?b不確定的狀況下,這個表達式 ?就可以代表平面上的任意一條直線。如果在?和?固定時,給定一個唯一的?的取值,這個表達式就可以表示一個固定的點。在SVM中,我們就使用這個表達式來表示我們的決策邊界。我們的目標是求解能夠讓邊際最大化的決策邊界,所以我們要求解參數向量?和截距?。如果在決策邊界上任意取兩個點?
, ?,并帶入決策邊界的表達式,則有:將兩式相減,可以得到:
一個列向量的轉至乘以另一個列向量,可以獲得兩個向量的點積(dot product),表示為
?。兩個向量的點擊為0表示兩個向量的方向式互相垂直的。 與?是一條直線上的兩個點,相減后的得到的向量方向是由? 指向? ,所以? 的方向是平行于他們所在的直線——我們的決策邊界的。而? 與 ?相互垂直,所以參數向量 ?的方向必然是垂直于我們的決策邊界。此時,我們有了我們的決策邊界。任意一個紫色的點?就可以被表示為:
由于紫色的點所代表的標簽y是1,所以我們規定,p>0。同樣的,對于任意一個紅色的點?而言,我們可以將它表示為:由于紅色點所表示的標簽y是-1,所以我們規定,r<0。由此,如果我們有新的測試數據
?,則 的?標簽就可以根據以下式子來判定: 核心誤區:p和r的符號注意,在這里,p和r的符號是我們人為規定的。在一些博客或教材中,會認為p和r的符號是由原本的決策邊界上下移動得到。這是一種誤解。
如果k和k'是由原本的決策邊界平移得到的話,紫色的點在決策邊界上方,? 應該要向上平移,直線向上平移的話是增加截距,也就是說應該寫作 ?,那k在等號的右邊,怎么可能是一個大于0的數呢?同理,向下平移的話應該是截距減小,所以k'也不可能是一個小于0的數。所以p和r的符號,不完全是平移的結果。
有人說,“直線以上的點帶入直線為正,直線以下的點帶入直線為負”是直線的性質,這又是另一種誤解。假設我們有穿過圓點的直線y=x?,我們取點(x,y) = (0,1)這個在直線上的點為例,如果直線的表達式寫作?y - x = 0,則點(0,1)帶入后為正1,如果我們將直線的表達式寫作x-y = 0,則帶入(0,1)后結果為-1。所以,一個點在直線的上方,究竟會返回什么樣的符號,是跟直線的表達式的寫法有關的,不是直線上的點都為正,直線下的點都為負。
可能細心的小伙伴會發現,我們規定了k和k'的符號與標簽的符號一致,所以有人會說,k和k'的符號,由所代表的點的標簽的符號決定。這不是完全錯誤的,但這種說法無法解釋,為什么我們就可以這樣規定。并且,標簽可以不是{-1,1},可以是{0, 1},可以是{1,2},兩個標簽之間并不需要是彼此的負數,標簽的取值其實也是我們規定的。
那k和k'的符號,到底是依據什么來定的呢?數學中很多過程,都是可以取巧的,來看以下過程。
記得我們的決策邊界如果寫成矩陣,可以表示為:
紫色點?
毫無疑問是在決策邊界的上方的,此時我將決策邊界向上移動,形成一條過 ?的直線。根據我們平移的規則,直線向上平移,是在截距后加一個正數,則等號的右邊是一個負數,假設這個數等于-3,則有:另等式兩邊同時乘以:
可以注意到,我們的參數向量由[a,-1]變成了[-a,1],
變成了 ,但參數向量依舊可以被表示成 ?,只是它是原來的負數了,截距依舊可以被表示成? ,只是如果它原來是正,它現在就是負數了,如果它原本就是負數,那它現在就是正數了。在這個調整中,我們通過將向上平移時產生的負號放入了參數向量和截距當中,這不影響我們求解,只不過我們求解出的參數向量和截距的符號變化了,但決策邊界本身沒有變化。所以我們依然可以使用原來的字母來表示這些更新后的參數向量和截距。通過這種方法,我們讓? 中的k大于0。我們讓k大于0的目的,是為了它的符號能夠與我們的標簽的符號一致,都是為了后續計算和推導的簡便。有了這個理解,剩下的推導就簡單多了。我們之前說過,決策邊界的兩邊要有兩個超平面,這兩各超平面在二維空間中就是兩條平行線,而他們之間的距離就是我們的邊際?。這而決策邊界位于這兩條線的中間,所以這兩條平行線必然是對稱的。我們另這兩條平行線被表示為:
兩個表達式同時除以k,則可以得到:
這就是我們平行于決策邊界的兩條線的表達式。此時,我們可以讓這兩條線分別過兩類數據中距離我們的決策邊界最近的點,這些點就被稱為“支持向量”,而決策邊界永遠在這兩條線的中間,所以可以被調整。我們另紫色類的點為
?,紅色類的點為 ?,則我們可以得到:兩個式子相減,則有:
如下圖所示,?
可表示為兩點之間的連線,而我們的邊際d?是平行于? w 的,所以我們現在,相當于是得到了三角型中的斜邊,并且知道一條直角邊的方向。在線性代數中,向量有這樣的性質:向量a除以向量b的模長||b||?,可以得到向量a在向量b的方向上的投影的長度。所以,我們另上述式子兩邊同時除以||w||?,則可以得到:還記得我們想求什么嗎?最大邊界所對應的決策邊界,那問題就簡單了,要最大化d?,就求解?的w最小值。極值問題可以相互轉化,我們可以把求解?w的最小值轉化為,求解以下函數的最小值:
之所以要在模長上加上平方,是因為模長的本質是一個距離,所以它是一個帶根號的存在,我們對它取平方,是為了消除根號(其實模長的本質是向量w?的l2范式,還記得l2范式公式如何寫的小伙伴必定豁然開朗)。
我們的兩條虛線表示的超平面,是數據邊緣所在的點。所以對于任意樣本
?,我們可以把決策函數寫作:整理一下,我們可以把兩個式子整合成:
于是,我們就得到了我們SVM的損失函數:
到這里,我們就完成了,對SVM第一層理解的第一部分:線性SVM做二分類的損失函數。我們最小化這個損失函數,來求解?w的值。
【完整版】2.1.2 用拉格朗日對偶函數求解線性SVM
2.1.3 線性SVM決策過程的可視化
我們可以使用sklearn中的式子來為可視化我們的決策邊界,和決策邊界平行的兩個超平面。
我們目前所有的例子,都是基于數據是線性可分的狀況來說明的。如果數據是線性不可分呢?比如說:
from sklearn.datasets import make_circles X,y = make_circles(100, factor=0.1, noise=.1) ? X.shape ? y.shape ? plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap="rainbow") plt.show()試試看用我們已經定義的函數來劃分這個數據的決策邊界:
clf = SVC(kernel = "linear").fit(X,y) plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap="rainbow") plot_svc_decision_function(clf)明顯,現在線性SVM已經不適合于我們的狀況了,我們無法找出一條直線來劃分我們的數據集,讓直線的兩邊分別是兩種類別。這個時候,如果我們能夠在原本的X和y的基礎上,添加一個維度r,變成三維,我們可視化這個數據,來看看添加維度讓我們的數據如何變化。
#定義一個由x計算出來的新維度r r = np.exp(-(X**2).sum(1)) ? rlim = np.linspace(min(r),max(r),0.2) ? from mpl_toolkits import mplot3d ? #定義一個繪制三維圖像的函數 #elev表示上下旋轉的角度 #azim表示平行旋轉的角度 def plot_3D(elev=30,azim=30,X=X,y=y):ax = plt.subplot(projection="3d")ax.scatter3D(X[:,0],X[:,1],r,c=y,s=50,cmap='rainbow')ax.view_init(elev=elev,azim=azim)ax.set_xlabel("x")ax.set_ylabel("y")ax.set_zlabel("r")plt.show()plot_3D()#如果放到jupyter notebook中運行 from sklearn.svm import SVC import matplotlib.pyplot as plt import numpy as np ? from sklearn.datasets import make_circles X,y = make_circles(100, factor=0.1, noise=.1) plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap="rainbow") ? def plot_svc_decision_function(model,ax=None):if ax is None:ax = plt.gca()xlim = ax.get_xlim()ylim = ax.get_ylim()x = np.linspace(xlim[0],xlim[1],30)y = np.linspace(ylim[0],ylim[1],30)Y,X = np.meshgrid(y,x) xy = np.vstack([X.ravel(), Y.ravel()]).TP = model.decision_function(xy).reshape(X.shape)ax.contour(X, Y, P,colors="k",levels=[-1,0,1],alpha=0.5,linestyles=["--","-","--"])ax.set_xlim(xlim)ax.set_ylim(ylim) ? clf = SVC(kernel = "linear").fit(X,y) plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap="rainbow") plot_svc_decision_function(clf) ? r = np.exp(-(X**2).sum(1)) ? rlim = np.linspace(min(r),max(r),0.2) ? from mpl_toolkits import mplot3d ? def plot_3D(elev=30,azim=30,X=X,y=y):ax = plt.subplot(projection="3d")ax.scatter3D(X[:,0],X[:,1],r,c=y,s=50,cmap='rainbow')ax.view_init(elev=elev,azim=azim)ax.set_xlabel("x")ax.set_ylabel("y")ax.set_zlabel("r")plt.show() ? from ipywidgets import interact,fixed interact(plot_3D,elev=[0,30],azip=(-180,180),X=fixed(X),y=fixed(y)) plt.show()此時我們的數據在三維空間中,我們的超平面就是一個二維平面。明顯我們可以用一個平面將兩類數據隔開,這個平面就是我們的超平面。我們剛才做的,計算r,并將r作為數據的第三維度來講數據升維的過程,被稱為“核變換”,即是將數據投影到高維空間中,以尋找能夠將數據完美分割的超平面,而在高維空間中計算來找出超平面的函數就叫做核函數。在SVM中,這個功能由參數“kernel”控制。之前我們一直使用這個參數,但是沒有給大家解釋,我們使用的是“linear",線性核函數,只能用于線性的情況。剛才我們使用的計算r的方法,其實是高斯徑向基核函數,在參數”kernel“中輸入”rbf“就可以使用。我們來看看模型找出的決策邊界時什么樣:
clf = SVC(kernel = "rbf").fit(X,y) plt.scatter(X[:,0],X[:,1],c=y,s=50,cmap="rainbow") plot_svc_decision_function(clf)核函數是我們處理非線性問題的關鍵。
2.3 非線性SVM與核函數
2.3.1 重要參數kernel & degree & gamma
線性核:
多項式核:
Sigmoid(Hyperbolic Tangent)核函數:
高斯徑向基(rbf)函數:
直觀地,伽瑪參數定義了單個訓練樣例的影響達到了多遠,低值意味著“遠”,高值意味著“接近”。 伽馬參數可以被視為由模型選擇的樣本作為支持向量的影響半徑的倒數。 C參數將訓練樣例的錯誤分類與決策表面的簡單性進行交換。 低C使得決策表面平滑,而高C旨在通過給予模型自由選擇更多樣本作為支持向量來正確地對所有訓練示例進行分類。
從技術上講,伽瑪參數是RBF核的標準偏差(高斯函數)的倒數,其用作兩點之間的相似性度量。 直觀地,小的伽馬值定義具有大方差的高斯函數。 在這種情況下,即使彼此相距很遠,也可以認為兩個點相似。 另一方面,大的伽馬值意味著定義具有小方差的高斯函數,并且在這種情況下,兩個點被認為是相似的,只要它們彼此接近。 關于,調整參數。 我認為您的方法沒有任何問題。 我還使用網格搜索來查找C,gamma和epsilon值。
當伽瑪非常小時,模型太受約束,無法捕捉數據的復雜性或“形狀”。 任何選定支持向量的影響區域將包括整個訓練集。 得到的模型的行為類似于線性模型,其中包含一組超平面,這些超平面將任意一對兩類的高密度中心分開。
同步視頻在這里哦:
【機器學習】菜菜的sklearn課堂【全85集】Python進階_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili?www.bilibili.com完整版目錄:
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的sklearn保存svm分类模型_【菜菜的sklearn】07 支持向量机(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php mysql复杂查询_半复杂的PH
- 下一篇: commons-pool2-2.3 ja