一、SVM簡介
(一)Support Vector Machine
-
- 支持向量機(SVM:Support Vector Machine)是機器學習中常見的一種分類算法。
- 線性分類器,也可以叫做感知機,其中機表示的是一種算法。
- 在實際應用中,我們往往遇到這樣的問題:
給定一些數據點,它們分別屬於兩個不同的類。我們現在要找到一個線性分類器把這些數據分成AB兩類。最簡單的辦法當然是,畫一條線,然后將它們分成兩類。線的一側,屬於A類,另一側,則屬於B類。SVM算法可以讓我們找到這樣一個最佳的線(超平面),來划分數據。相比於KNN之類的算法,SVM算法只需要計算一次,得出最佳線(超平面)即可。面對測試數據,只需要判斷數據點落在線的哪一側,就可以知道該數據點所屬分類了。比起KNN每次都需要計算一遍鄰居點的分類,SVM算法顯得簡單無比。
(二)Sklearn參數詳解—SVM
1 sklearn.svm.LinearSVC(penalty='l2', loss='squared_hinge', dual=True, tol=0.0001, C=1.0, multi_class='ovr', fit_intercept=True, intercept_scaling=1, class_weight=None, verbose=0, random_state=None, max_iter=1000)
-
-
penalty:
正則化參數,L1和L2兩種參數可選,僅LinearSVC有。loss:
損失函數,有‘hinge’和‘squared_hinge’兩種可選,前者又稱L1損失,后者稱為L2損失,默認是是’squared_hinge’,其中hinge是SVM的標准損失,squared_hinge是hinge的平方。dual:
是否轉化為對偶問題求解,默認是True。tol:
殘差收斂條件,默認是0.0001,與LR中的一致。C:
懲罰系數,用來控制損失函數的懲罰系數,類似於LR中的正則化系數。multi_class:
負責多分類問題中分類策略制定,有‘ovr’和‘crammer_singer’ 兩種參數值可選,默認值是’ovr’,'ovr'的分類原則是將待分類中的某一類當作正類,其他全部歸為負類,通過這樣求取得到每個類別作為正類時的正確率,取正確率最高的那個類別為正類;‘crammer_singer’ 是直接針對目標函數設置多個參數值,最后進行優化,得到不同類別的參數值大小。fit_intercept:
是否計算截距,與LR模型中的意思一致。class_weight:
與其他模型中參數含義一樣,也是用來處理不平衡樣本數據的,可以直接以字典的形式指定不同類別的權重,也可以使用balanced參數值。verbose:
是否冗余,默認是False.random_state:
隨機種子的大小。max_iter:
最大迭代次數,默認是1000。
-
對象
-
-
coef_
:各特征的系數(重要性)。intercept_
:截距的大小(常數值)。
-
1 sklearn.svm.NuSVC(nu=0.5, kernel='rbf', degree=3, gamma='auto', 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))
nu
:訓練誤差部分的上限和支持向量部分的下限,取值在(0,1)之間,默認是0.5kernel
:核函數,核函數是用來將非線性問題轉化為線性問題的一種方法,默認是“rbf”核函數,常用的核函數有以下幾種:
表示 |
解釋 |
---|---|
linear |
線性核函數 |
poly |
多項式核函數 |
rbf |
高斯核函數 |
sigmod |
sigmod核函數 |
precomputed |
自定義核函數 |
-
-
degree
:當核函數是多項式核函數的時候,用來控制函數的最高次數。(多項式核函數是將低維的輸入空間映射到高維的特征空間)gamma
:核函數系數,默認是“auto”,即特征維度的倒數。coef0
:核函數常數值(y=kx+b中的b值),只有‘poly’和‘sigmoid’核函數有,默認值是0。max_iter
:最大迭代次數,默認值是-1,即沒有限制。probability
:是否使用概率估計,默認是False。decision_function_shape
:與'multi_class'參數含義類似。cache_size
:緩沖大小,用來限制計算量大小,默認是200M。
-
對象
support_
:以數組的形式返回支持向量的索引。support_vectors_
:返回支持向量。n_support_
:每個類別支持向量的個數。dual_coef_
:支持向量系數。coef_
:每個特征系數(重要性),只有核函數是LinearSVC的時候可用。intercept_
:截距值(常數值)。
1 sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', 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)
-
-
C:
懲罰系數。
-
SVC和NuSVC方法基本一致,唯一區別就是損失函數的度量方式不同(NuSVC中的nu參數和SVC中的C參數)
-
-
-
decision_function(X)
:獲取數據集X到分離超平面的距離。 fit(X, y)
:在數據集(X,y)上使用SVM模型。get_params([deep])
:獲取模型的參數。-
predict(X)
:預測數據值X的標簽。 score(X,y)
:返回給定測試集和對應標簽的平均准確率。
-
-
二、感知機簡介
三、超平面
- 當我們的數據點集是二維的時候(意味着有兩個特征),我們只需要用一根線,就可以將數據分成兩個部分。
- 當我們的數據點集是三維的時候(意味着有三個特征),我們需要一個二維的平面,才能把數據分成兩個部分。
- 當我們的數據點集為N維的時候(意味着有N個特征),此時我們需要一個N-1維的超平面,才可以把數據分成兩個部分。
- 我們有無數個超平面可以將數據集分成兩個部分,我們應該怎么找到最佳的分割線呢?https://www.kesci.com/home/project/5cf08e4dc84534002b03cdfd
-
虛線中心的綠色實線,就是我們在保持超平面方向不變的時候,得到的最佳超平面。
-
兩條虛線之間的垂直距離,代表這這個超平面的分類間隔。
-
改變超平面的方向的時候,我們會得到不同方向的最佳超平面。
- “分類間隔”最大的那個超平面,就是真正的最佳超平面。即最佳超平面為兩條虛線的中軸線
- 該平面所對應的兩側虛線穿過的樣本點,就是SVM中的支持樣本點,被稱為“支持向量”
四、核函數
(一)核函數介紹
https://blog.csdn.net/batuwuhanpei/article/details/52354822
實際生活中,我們會碰到很多線性不可分的數據集,將其放在一個高維空間中去就有可能變得可分。如圖所示:
理論上任意的數據樣本都能夠找到一個合適的映射,使得這些在低維空間不能划分的樣本到高維空間中之后能夠線性可分。以二維平面的數據為例,我們可以找到一個映射,將二維平面的點映射到三維平面之中。
常見的核函數有:
-
- Linear Kernel 線性核函數
- Polynomial Kernel 多項式核函數
- Radial Basis Function (RBF) kernel 徑向基核函數(RBF) …………
常用核函數公式如下:
(二)核函數的選擇
在選用核函數的時候,希望通過將輸入空間內線性不可分的數據映射到一個高緯的特征空間內使得數據在特征空間內是可分的,如果我們對我們的數據有一定的先驗知識,就利用先驗來選擇符合數據分布的核函數;如果不知道的話,通常使用交叉驗證的方法,來試用不同的核函數,誤差最下的即為效果最好的核函數,或者也可以將多個核函數結合起來,形成混合核函數。在吳恩達的課上,也曾經給出過一系列的選擇核函數的方法:
- 如果特征的數量大到和樣本數量差不多,則選用LR或者線性核的SVM;
- 如果特征的數量小,樣本的數量正常,則選用SVM+高斯核函數;
- 如果特征的數量小,而樣本的數量很大,則需要手工添加一些特征從而變成第一種情況。
五、乳腺癌數據集(選取2特征)實驗
1 import numpy as np 2 import matplotlib.pyplot as plt 3 from sklearn import svm 4 from sklearn.datasets import make_blobs,load_breast_cancer 5 6 print(load_breast_cancer().keys()) 7 # dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names', 'filename']) 8 data1 = load_breast_cancer().data 9 target1 = load_breast_cancer().target 10 11 print('data1,target1',data1.shape,target1.shape) 12 # data1,target1 (569, 30) (569,) 13 #一共有三十列特征,可以任意選擇特征的數目,這里以二維為例 14 data = load_breast_cancer().data[:, 0:2] 15 target = load_breast_cancer().target 16 print(np.unique(target)) 17 18 #創建SVM模型 19 #選擇核函數為'linear' 20 #C: 目標函數的懲罰系數C,用來平衡分類間隔margin和錯分樣本的,default C = 1.0; 21 #kernel:參數選擇有RBF, Linear, Poly, Sigmoid, 默認的是"RBF" 22 23 model = svm.SVC(kernel='linear',C=10000) 24 25 #使用模型訓練數據集 26 model.fit(data, target) 27 28 #繪制數據集散點圖 29 # plt.scatter(data[:, 0], data[:, 1], c=target) 30 plt.scatter(data[:, 0], data[:, 1], c=target, s=30, cmap=plt.cm.prism) 31 32 #創建坐標軸刻度線 33 axis = plt.gca() 34 x_limit = axis.get_xlim() 35 y_limit = axis.get_ylim() 36 37 x = np.linspace(x_limit[0], x_limit[1], 50) 38 y = np.linspace(y_limit[0], y_limit[1], 50) 39 print('x,y',x.shape,y.shape)#x,y (50,) (50,) 40 X, Y = np.meshgrid(x, y) 41 print('X, Y ',X.shape, Y.shape )#X, Y (50, 50) (50, 50) 42 xy = np.c_[X.ravel(), Y.ravel()] 43 print('xy',xy.shape)#xy (2500, 2) 44 45 46 # 創建最佳分割線 47 decision_line = model.decision_function(xy).reshape(Y.shape) #計算樣本點到分割超平面的函數距離
48
49 # 繪制分割線的圖
50 axis.contour(X, Y, decision_line, colors = 'k', levels=[0],
51 linestyles=['-'])
52
53 # 展示一下支持向量點
54 plt.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s=100,
55 linewidth=1, facecolors='none', edgecolors='k')
56 plt.show()
(一)線性完全可分問題 hard margin classfication
https://www.jianshu.com/p/6ebdfe0cf1a4
1 # coding = utf-8 2 import numpy as np 3 import matplotlib.pyplot as plt 4 from sklearn import svm 5 from sklearn.datasets import make_blobs 6 7 a,b = make_blobs() 8 print('make_blobs()',a.shape,b.shape)#make_blobs() (100, 2) (100,) 9 10 x,y = make_blobs(n_samples=40,centers=2,random_state=9) 11 print('x,y',x.shape,y.shape)#x,y (40, 2) (40,) 12 13 ''' 14 centers就是數據分布點,我們現在解決的是二分類問題,\ 15 那么就需要兩個center,數據點都分別圍繞着center進行分布 16 random_state確定一個數字后,每次運行都會出現相同的隨機數。 17 ''' 18 plt.scatter(x[:,0],x[:,1],c = y,cmap=plt.cm.Paired) 19 ''' 20 plt.scatter中的c代表color,cmap代表colormap,可選 21 s是size, c=y是標簽分類和plt.cm.Paired聯合使用 22 ''' 23 plt.show()
(二)線性不可分SVM
1 import numpy as np 2 import matplotlib.pyplot as plt 3 from sklearn import svm 4 import warnings 5 warnings.filterwarnings('ignore') 6 np.random.seed(0) 7 X=np.random.randn(300,2) 8 Y=np.logical_xor(X[:,0]>0, X[:,1]>0) 9 xx,yy = np.meshgrid(np.linspace(-3,3,500),np.linspace(-3,3,500)) 10 #fit 11 clf = svm.SVC() #所有參數采用默認 12 clf.fit(X,Y) 13 xy = np.vstack([xx.ravel(),yy.ravel()]).T 14 Z=clf.decision_function(xy).reshape(xx.shape) 15 plt.imshow(Z, interpolation='nearest',extent=(xx.min(),xx.max(), yy.min(),yy.max(),),aspect='auto',origin='lower',cmap=plt.cm.PuOr_r) #這一段是背景設置 16 plt.contour(xx,yy,Z,levels=[0],linewidths=2,linestyle='-') 17 plt.scatter(X[:,0],X[:,1],s=30,c=Y,cmap=plt.cm.Paired, edgecolors='k') 18 plt.show()
(三)SVM-人臉識別
http://www.hongweipeng.com/index.php/archives/1406/
(四)make_blobs實驗
https://www.jianshu.com/p/f7d2ed8aac54
六、拉格朗日乘子法
https://blog.csdn.net/on2way/article/details/47729419
- 有拉格朗日乘法的地方,必然是一個組合優化問題。
- 凸的就是開口朝一個方向(向上或向下),拉格朗日法是一定適合於凸問題的,不一定適合於其他問題。
- 有了約束(即等式 f(x)=2x**2+3y**2+7z**2,其中約束條件為2x+y=3,x+3z=9)不能直接求導,那么我們把這個約束乘一個系數加到目標函數中去,這樣就相當於既考慮了原目標函數,也考慮了約束條件,即f(x)=2x**2+3y**2+7z**2+a(2x+y-3)+b(x+3z-9),分別對x\y\z求導等於零,帶入約束條件,得到a\b;
七、KKT
- 帶有不等式的約束問題怎么辦?就需要用更一般化的拉格朗日乘法即KKT條件來解決這種問題了。
- KKT條件是解決最優化問題的時用到的一種方法,求其在指定作用域上的全局最小值。https://blog.csdn.net/on2way/article/details/47729419
- 任何原始問題約束條件無非最多3種,等式約束,大於號約束,小於號約束,而這三種最終通過將約束方程化簡化為兩類:約束方程等於0和約束方程小於0。
八、cancer數據集PCA
九、cancer數據集實驗
十、總結
在分類問題中,SVM是一種很優秀的機器學習算法。
優點
-
-
- 可以有效的分離高維度的數據
- 更節省內存空間,因為只需要用向量來創建最佳超平面
- 是針對於可分離數據集的最佳方法
-
缺點
-
-
- 當數據量級較大的時候,分類效果不好
- 針對於不可分類的數據集,效果有些不太好
-