天天看點

scikit-learn中的SVM

主要參考資料: http://scikit-learn.org/stable/modules/svm.html#

SVM優點:

       高維空間有效性;

       資料次元遠大于樣本數量時的有效性;

       決策函數實際使用訓練集的子集(也叫支援向量),記憶體使用高效;

       多樣性:核函數可選,也可自己定義。

SVM缺點:

       特征數大于樣本數,SVM方法不太适用了。

       沒有直接提供誤差估計,計算需花很大代價;

scikit-learn中的SVM輸入支援諸如numpy.ndarray (或者可以轉化為numpy.asarray形式) 的密集資料及類似scipy.sparse的稀疏資料。然而,用SVM給稀疏資料做預測,需要有合适的資料。最好是,密集資料用numpy.ndarrsy形式,稀疏資料用scipy.sparse.csr_matrix形式,資料格式均用dtype=float64。

SVC和NuSVC是相似的方法,但是輸入參數和數學公式不一樣。另一方面,LinearSVC是另一種線性核的SVM方法。注意,LinearSVC不用給定參數kernel,從命名可以看出其預設為linear核,對比SVC和NuSVC,缺少support_參數。

SVC, NuSVC和linearSVC接受兩個數組為輸入,X大小為[ n_samples, n_features],是訓練樣本;y的大小是 [n_samples],是類标簽,可以是strings或者integers。

>>> from sklearn import svm

>>> X= [[0,0], [1,1]]

>>> y= [0,1]

>>> clf= svm.SVC()

>>> clf.fit(X, y) 

SVC(C=1.0, cache_size=200,class_weight=None, coef0=0.0,

   decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',

   max_iter=-1, probability=False, random_state=None, shrinking=True,

   tol=0.001, verbose=False)

在fiitted之後,模型就能進行預測了。

>>> clf.predict([[2.,2.]])      
array([1])      

SVMs的決策函數依賴于訓練集的子集,稱之為支援向量。這些支援向量的屬性能在成員support_vectors, support_和n_support中看到:

>>> # get support vectors      
>>> clf.support_vectors_      
array([[ 0.,  0.],      
       [ 1.,  1.]])      
>>> # get indices of support vectors      
>>> clf.support_      
array([0, 1]...)      
>>> # get number of support vectors for each class      
>>> clf.n_support_      
array([1, 1]...)      

SVC和NuSVC在處理多分類問題上采用的是“1 vs 1”的政策。若n_class是類别數,那需要訓練的模型數量就是 n_class*(n_class-1)/2 ,每次訓練使用兩個類别的資料。為了提供跟其他分類器類似的接口,decision_funxtion_shape選項能将 “1 vs 1”分類器的結果組合成形如(n_samples, n_classes)的決策器。

>>> X= [[0], [1], [2], [3]]      
>>> Y= [0,1,2,3]      
>>> clf= svm.SVC(decision_function_shape='ovo')      
>>> clf.fit(X, Y)       
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,      
    decision_function_shape='ovo', degree=3, gamma='auto', kernel='rbf',      
    max_iter=-1, probability=False, random_state=None, shrinking=True,      
    tol=0.001, verbose=False)      
>>> dec= clf.decision_function([[1]])      
>>> dec.shape[1]# 4 classes: 4*3/2 = 6      
6      
>>> clf.decision_function_shape="ovr"      
>>> dec= clf.decision_function([[1]])      
>>> dec.shape[1]# 4 classes      
4      

另一方面,LinearSVC采用的是“1vs 其他”多分類政策,是以訓練n_class 個模型即可。如果隻有兩類,那隻需要訓練一個模型:

>>> lin_clf= svm.LinearSVC()      
>>> lin_clf.fit(X, Y)       
LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,      
     intercept_scaling=1, loss='squared_hinge', max_iter=1000,      
     multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,      
     verbose=0)      
>>> dec= lin_clf.decision_function([[1]])      
>>> dec.shape[1]      
4      

注意LinearSVC配置了多分類政策,也就是所謂的Crammer和Singer公式中的所分類SVM方法,實作中使用參數multi_class=’crammer_singer’。這種方法是固定的,但是不太适用于“1 vs其他”的情況。實踐中,“1vs其他”分類适用較多,因為結果簡單,運作周期短。

在“1 vs其他”情況下,LinearSVC的coef_和intercept_屬性的大小分别是[n_class, n_features]和 [n_class],系數矩陣的每一行是“1 vs其他”中的一個分類器,順序與類别的順序相同。

SVC中的“1 vs 1”模式在屬性中有點差異。當核函數選擇Linear時,coef_和intercept_的數值與LinearSVC中相同,但是coef_的大小是 [n_class*(n_class-1)]/2, n_features],對應于二分類器。分類器的順序是“0 vs 1”,“0 vs 2”……“0 vs n”,“1 vs 2”,“1 vs 3”……

“n-1 vs n”。

Deal_coef_的大小是 [n_class-1, n_SV],支援向量的列在任意一個“1 vs 1”分類器中,每個支援向量都在n_class-1個分類器中使用到了。

【scores 和 probabilities】

SVC方法decision_function會給每個樣本一個屬于某個類别的機率。如果構造器probability=True,則會啟用類成員機率估計(用predict_proba或者predict_log_proba)。二分類情況下,機率通過Platt-scalling校準,比如用svm分數進行線性回歸,用額外的訓練集的十字交叉驗證法實作。

不用說,Platt-scalling校準中的十字交叉驗證在大資料集下是個費時費力的操作。另外,用scores做的機率估計是不穩定的,參數argmax并不是機率的argmax。Platt方法也存在理論問題,如果要求可信的scores,但不必要是機率,那可以設probability=False,而且用decision_function來代替predict_proba。

【unbalabced problems】

如果要更加關注類别和參數,可以使用參數class_weight和sample_weight。

SVC(注意不是NuSVC)的fit方法中有個很重要的關鍵字class_weight,是字典類型{class_label : value},其中value是>0的浮點類型,那麼此時class_label的C參數就成了C*value。

SVC、NuSVC、SVR、NuSVR和OneClassSVM同樣也有通過參數sample_weight給單個樣本添權重重,此時類别class_label的C參數就成了C*value。

【回歸】

SVM方法同樣可以做回歸,此時叫做SVR。

如上所述,SVM模型的建立隻與訓練資料中的一部分子集有關,因為建立模型的代價函數不關心遠離超平面的訓練點。類似的,SVR模型也隻與訓練集的一部分有關,因為代價函數忽略訓練集中靠近模型預測的點。

SVR有三種不同的實作方式,SVR、NuSVR和LinearSVR,其中LinearSVR的實作比SVR更快,但是隻支援線性核,NuSVR的實作使用明顯不同于SVR和LinearSVR的公式,可在官網檢視細節。

>>> from sklearn import svm
>>> X = [[0, 0], [2, 2]]
>>> y = [0.5, 2.5]
>>> clf = svm.SVR()
>>> clf.fit(X, y) 
SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1, gamma='auto',
    kernel='rbf', max_iter=-1, shrinking=True, tol=0.001, verbose=False)
>>> clf.predict([[1, 1]])
array([ 1.5])      

【scores 和 probabilities】

SVC方法decision_function會給每個樣本一個屬于某個類别的機率。如果構造器probability=True,則會啟用類成員機率估計(用predict_proba或者predict_log_proba)。二分類情況下,機率通過Platt-scalling校準,比如用svm分數進行線性回歸,用額外的訓練集的十字交叉驗證法實作。

不用說,Platt-scalling校準中的十字交叉驗證在大資料集下是個費時費力的操作。另外,用scores做的機率估計是不穩定的,參數argmax并不是機率的argmax。Platt方法也存在理論問題,如果要求可信的scores,但不必要是機率,那可以設probability=False,而且用decision_function來代替predict_proba。

【unbalabced problems】

如果要更加關注類别和參數,可以使用參數class_weight和sample_weight。

SVC(注意不是NuSVC)的fit方法中有個很重要的關鍵字class_weight,是字典類型{class_label : value},其中value是>0的浮點類型,那麼此時class_label的C參數就成了C*value。

SVC、NuSVC、SVR、NuSVR和OneClassSVM同樣也有通過參數sample_weight給單個樣本添權重重,此時類别class_label的C參數就成了C*value。

【回歸】

SVM方法同樣可以做回歸,此時叫做SVR。

如上所述,SVM模型的建立隻與訓練資料中的一部分子集有關,因為建立模型的代價函數不關心遠離超平面的訓練點。類似的,SVR模型也隻與訓練集的一部分有關,因為代價函數忽略訓練集中靠近模型預測的點。

SVR有三種不同的實作方式,SVR、NuSVR和LinearSVR,其中LinearSVR的實作比SVR更快,但是隻支援線性核,NuSVR的實作使用明顯不同于SVR和LinearSVR的公式,可在官網檢視細節。