本文是scikit-learn 支持向量機(jī)的翻譯停撞,原文地址:http://scikit-learn.org/stable/modules/svm.html
支持向量機(jī)是用于分類、回歸和異常檢測的監(jiān)督學(xué)習(xí)方法。
支持向量機(jī)的優(yōu)勢:
- 高維空間有效垫挨;
- 維度高于采樣數(shù)量的情況依然有效;
- 在決策函數(shù)中使用訓(xùn)練點的子集(稱為支持向量)祸轮,因此節(jié)約內(nèi)存;
- 功能多樣:可以為決策函數(shù)指定不同的 核函數(shù)柄错。這里提供了通用核函數(shù)苦酱,也可以指定之定義核函數(shù)。
支持向量機(jī)的缺點:
- 如果特征的數(shù)量大大多于采樣的數(shù)量颂跨,在選擇核函數(shù)時避免過擬合,正則化至關(guān)重要恒削。
- SVM 并不直接提供概率估計尾序,概率估計需要使用代價高昂的五重交叉驗證計算(參見 Scores and probablities)钓丰。
scikit-learn 的支持向量機(jī)的輸入為稠密矩陣(numpy.ndarray 、可以轉(zhuǎn)化為 numpy.ndarray 的 numpy.asarray ) 和稀疏矩陣(任意 scipy.sparse) 每币。然而携丁,使用 SVM 對稀疏數(shù)據(jù)進(jìn)行預(yù)測時必須使用這類數(shù)據(jù)進(jìn)行擬合。為了獲取最佳效果兰怠,請使用 dtype=float64 的 C-ordered numpy.ndarray(稠密) 或 scipy.sparse.csr_matrix(稀疏)则北。
1.4.1 分類
能夠?qū)?shù)據(jù)集進(jìn)行多分類的類包括:SVC、NuSVC 和 LinearSVC 痕慢。
SVC 和 NuSVC 是相似的方法尚揣,但是采用稍有差異的參數(shù)集和不同的數(shù)學(xué)公式( 見 Mathematical formulation )。LinearSVC 則是使用線性核函數(shù)的支持向量機(jī)的另一種實現(xiàn)方式掖举。注意快骗,由于假設(shè)線性,LinearSVC 并不接受 kernel 關(guān)鍵字的參數(shù)塔次,此外方篮,它還缺少 SVC 和 NuSVC 的一些屬性,如 support_励负。
與其它分類器類似藕溅,SVC、NuSVC 和 LinearSVC 需要輸入兩個 arrays:大小為 [n_samples, n_features] 用于保存訓(xùn)練樣本的 X 和大小為 [n_samples] 的用于表示標(biāo)記(字符串或整型)的 y 继榆。
>>> 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='ovr', degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
模型訓(xùn)練好后巾表,可以用于預(yù)測新的值:
>>> clf.predict([[2., 2.]])
array([1])
SVM 決策函數(shù)依賴訓(xùn)練集的子集汁掠,稱為支持向量。支持向量的屬性可以通過 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]...)
1.4.1.1 多分類
SVC 和 NuSVC 使用“one-against-one" 策略(Knerr et al., 1990)實現(xiàn)多分類考阱。如果有 n_class 個類別鞠苟,那么將構(gòu)造 n_class*(n_class - 1)/2 個分類器吃既,每個分類器訓(xùn)練兩個類跨细。為了與其它分類器的接口保持一致申鱼,通過設(shè)置 decision_function_shape 可以將 ”one-against-one“ 分類器聚合為 (n_samples, n_classes) 的決策函數(shù):
>>> 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 使用 ”one-vs-the-rest“ 策略訓(xùn)練 n_class 模型。如果只有兩類猴鲫,則只訓(xùn)練一個模型:
>>> 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
決策函數(shù)的完整描述見 Mathematical formulation拂共。
注意, LinearSVC 也可以設(shè)置 multi_classes='crammer_singer' 來使用 Crammer 和 Singer 的所謂的多分類策略抚恒,這種方法與前面的方法一致俭驮,但對于“one-vs-rest”而言卻并非如此混萝。實際使用時瓮恭,通常首選 one-vs-rest,它效果不會差多少但能大大節(jié)約運行時間绳姨。
one-vs-rest LinearSVC 屬性的 coef_ 和 intercept_ 的格式分別為[n_class, n_features] 和 [n_class]飘庄。coef_ 的每一行按照”一“ 類的順序?qū)?yīng) n_class 中的一個 ‘one-vs-rest' 分類器跪削,intercept_ 也是如此碾盐。
”one-vs-one“ svc 中,屬性的布局更加復(fù)雜一些凌盯。使用線性核函數(shù)時阐滩,除了 coef_ 的格式為二分類對應(yīng)的 [n_class*(n_class-1)/2, n_samples]县忌,conf_ 和 intercept_ 與上面描述的 LinearSVC 的情況類似衅疙,分類 0 到 n 的順序為 "0 vs 1","0 vs 2" ....”0 vs n“, "1 vs 2"饱溢,”1 vs 3"..."1 vs n"绩郎,..."n-1 vs n"溉仑。
dual_coef_ 的格式為[n_class-1,n_SV]浊竟,它的布局較難理解振定。列對應(yīng) n_class*(n_class-1)/2 “one-vs-one” 分類器中用到的任意支持向量。支持向量中的每一個都用于 n_class-1個分類器中暖途。每一行的 n_class - 1 條內(nèi)容對應(yīng)這些分類器的雙系數(shù)露久。
1.4.1.2 Scores 和 概率
SVC 方法 decision_function 給出每個樣本的各類得分(或者二分類中的一個得分)抱环。當(dāng)構(gòu)架器選型 probability 設(shè)置為 True 時镇草,將啟用類成員概率估計(從方法 predict_proba 和 predict_log_proba得到)。對于二分類問題因宇,使用 Platt scaling 進(jìn)行校準(zhǔn):(通過對訓(xùn)練數(shù)據(jù)進(jìn)行額外的交叉驗證) SVM score 的 logistic 回歸察滑。對于多類情況贺辰,Wu et al(2004)等對其進(jìn)行了擴(kuò)展莽鸭。
毋庸置疑硫眨,Platt scaling 涉及的交叉驗證對于大型數(shù)據(jù)集來說是一項昂貴的操作礁阁。此外氮兵,概率估計可能與 scores 不一致。score 的 'argmax' 可能不是概率的 "argmax"弥姻,(例如庭敦,在二分類中,根據(jù) predict_proba 一個標(biāo)記的樣本屬于該類的概率可能 < 1/2)疼电。Platt 方法還存在理論問題蔽豺。如果需要置信度分?jǐn)?shù),但是不必是概率魄鸦,那么建議設(shè)置 probability=False 并使用 decison_function 來代替 predict_proba拾因。
相關(guān)資料:
- Wu, Lin and Weng, “Probability estimates for multi-class classification by pairwise coupling”, JMLR 5:975-1005, 2004.
- Platt “Probabilistic outputs for SVMs and comparisons to regularized likelihood methods".
1.4.1.3 不平衡問題
特定類或者特定樣本需要設(shè)置更多權(quán)重的問題可以使用 class_weight 和 sample_weight。
SVC(但 NuSVC 不可以)在 fit 方法中使用 class_weight 關(guān)鍵字參數(shù)罩驻。它的格式是 {class_label:value}惠遏,這里 value 是大于 0 的浮點值节吮,如果相同的 class_label 設(shè)置了 c 則值為 c*value。
SVC
, NuSVC
, SVR
, NuSVR
和 OneClassSVM
可以在 fit 方法中使用關(guān)鍵詞 sample_weight 設(shè)置單個樣本的權(quán)重帚豪。與 class_weight 類似參數(shù) c 可用于第 i 個樣本 : c*sample_weight[i]狸臣。
例子:
Plot different SVM classifiers in the iris dataset](http://scikit-learn.org/stable/auto_examples/svm/plot_iris.html#sphx-glr-auto-examples-svm-plot-iris-py),
SVM: Maximum margin separating hyperplane,
SVM: Separating hyperplane for unbalanced classes
1.4.2 回歸
支持向量分類方法可以擴(kuò)展到回歸問題煤禽。這個方法稱為 支持向量回歸呜师。
由于創(chuàng)建模型的目標(biāo)函數(shù)不關(guān)心 margin 之間的訓(xùn)練點,支持向量分類(如上面描述的內(nèi)容)的模型只依賴于一部分訓(xùn)練數(shù)據(jù)知牌。
類似的角寸,由于創(chuàng)建模型的目標(biāo)函數(shù)忽略任何與模型預(yù)測距離很近的訓(xùn)練數(shù)據(jù)沮峡,支持向量回歸也只依賴一部分訓(xùn)練數(shù)據(jù)。
支持向量回歸可以使用三種方法:SVR疟游、NuSVR 和 LinearSVR 。LinearSVR 執(zhí)行速度比 SVR 快但是只用于線性核函數(shù)另绩, NuSVR 與 SVR 和 LinearSVR 的公式稍有不同。詳見下面的執(zhí)行細(xì)節(jié)。
與分類問題相似拆撼,fit 的輸入?yún)?shù)為向量 X、y,只是這里 y 的類型為浮點型窄赋。
>>> 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_deprecated', kernel='rbf', max_iter=-1, shrinking=True,
tol=0.001, verbose=False)
>>> clf.predict([[1, 1]])
array([1.5])
例子:
1.4.3 密度估計哟冬,異常檢測
OneClassSVM 類實現(xiàn)一個 One-class SVM 來進(jìn)行異常檢測。
詳見 Novelty and Outiler Dection 了解 OneClassSVM 的描述和用法忆绰。
1.4.4 復(fù)雜度
支持向量機(jī)是個強大的工具浩峡,但是隨著訓(xùn)練樣本數(shù)量的增加,支持向量機(jī)計算和存儲的需要會快速增加错敢。SVM的內(nèi)核是支持向量與其它訓(xùn)練數(shù)據(jù)分離的二次規(guī)劃問題(QP)翰灾。libsvm 使用的 QP 求解器的計算復(fù)雜度在 與
之間,具體復(fù)雜度取決于實際使用的 libsvm 緩存的效率(依賴數(shù)據(jù))。如果數(shù)據(jù)非常稀疏,應(yīng)該使用樣本向量中的非零特征的平均值替代
糜芳。
還要注意線性情況下皆撩,liblinear 的 LinearSVC 算法執(zhí)行效率比 基于 libsvm 的 SVC 效率高得多亚脆,并且可以幾乎線性的擴(kuò)展到百萬個樣本或特征。
1.4.5 實際使用過程中的 Tips
-
避免數(shù)據(jù)拷貝:對于 SVC奶赔、SVR笛钝、NuSVC和 NuSVR,如果傳入特定方法的數(shù)據(jù)不是 C-ordered 連續(xù)的以及雙精度的,那么在調(diào)用底層 C 實現(xiàn)之前將進(jìn)行拷貝。您可以通過檢查 flag 屬性確定給定的 numpy 數(shù)組是否 C 連續(xù)耗绿。
對于 LinearSVC(和 LogisticRegression)堕绩,任何傳入的 numpy數(shù)據(jù)都將被拷貝并轉(zhuǎn)換為 liblinear 內(nèi)部稀疏數(shù)據(jù)表示(雙精度浮點數(shù)浅浮,非零元素的 int32 索引)。如果你想不復(fù)制大規(guī)模線性分類器的密集 numpy C連續(xù)雙精度數(shù)據(jù)的輸入案站,我們建議使用 SGDClassifier 類,它可以設(shè)置幾乎與 LinearSVC 幾乎相同的目標(biāo)函數(shù)里伯。
核心緩存大小 對于 SVC肩碟、SVR褪猛、NuSVC和 NuSVR,對于規(guī)模較大的問題核心緩存大小對運行時間影響很大色洞。如果你有足夠的 RAM ,推薦將 cache_size 設(shè)置到高于默認(rèn)的200(MB) ,比如 500(MB) 或 1000(MB)揽涮。
設(shè)置 C 默認(rèn) C 為 1嵌牺,這是一個合理的值僻弹,如果有很多噪音樣本苛聘,應(yīng)該減小它的值两蟀,它與正則化對應(yīng)膛堤。
支持向量機(jī)的規(guī)模是變化的隧出,強烈推薦歸一化數(shù)據(jù)凄诞。例如,將輸入向量 X 的每個屬性歸一化到 [0,1] 或[-1,1]忍级,或者標(biāo)準(zhǔn)化到均值為 0 方差為 1帆谍。注意,要對訓(xùn)練向量進(jìn)行相同的歸一化來得到有意義的結(jié)果轴咱。歸一化和標(biāo)準(zhǔn)化的更多內(nèi)容見 PreProcessing data汛蝙。
NuSVC / OneClassSVM / NuSVR中的參數(shù)nu近似于訓(xùn)練誤差和支持向量的比值。
SVC 中如果分類器的數(shù)據(jù)不平衡(比如很多的正值和很少的負(fù)值)朴肺,嘗試設(shè)置 class_weight='balanced' 并/或 嘗試不同的懲罰參數(shù) C窖剑。
底層實現(xiàn)的隨機(jī)性:SVC 和 NuSVC 的底層實現(xiàn)使用一個隨機(jī)數(shù)生成器為概率估計(probability設(shè)置為 True 時)打亂數(shù)據(jù)。這種隨機(jī)性可以通過 random_state 來控制戈稿。如果 probability 設(shè)置為 False西土,估計不是隨機(jī)的,random
_state對結(jié)果沒有影響鞍盗。 OneClassSVM 與 SVC 和 NuSVC 的底層執(zhí)行類似需了,OneClassSVM 不提供概率估計,它也不是隨機(jī)的般甲。
LinearSVC 的底層實現(xiàn)使用雙坐標(biāo)下降(dual 設(shè)置為 True) 擬合模型時使用隨機(jī)數(shù)生成器來選擇特征肋乍,因此,相同的輸入數(shù)據(jù)得到稍微不同的結(jié)果并不罕見敷存。如果發(fā)生這種情況住拭,嘗試減少 tol 參數(shù)的值。這種隨機(jī)性也可以通過 random_state 來控制。 當(dāng) dual 設(shè)置為 False 時滔岳,LinearSVC 的底層實現(xiàn)不是隨機(jī)的,random_state 對結(jié)果沒有影響挽牢。
使用LinearSVC提供的L1懲罰(loss ='l2'谱煤,penalty ='l1',dual = False)產(chǎn)生稀疏解禽拔,即只有特征權(quán)重的子集不為零并且對決策函數(shù)有貢獻(xiàn)刘离。 增加 C 會產(chǎn)生更復(fù)雜的模型(選擇更多特征)。 可以使用 l1_min_c 計算產(chǎn)生“空”模型(所有權(quán)重等于零)的 C 值睹栖。
1.4.6 核函數(shù)
核函數(shù)可以是下面的任意一種:
- 線性的:(x,x')
- 多項式的: (γ?x,x′?+r)d硫惕。d 由關(guān)鍵字
degree
指定, r 由coef0
指定。 - rbf:
野来,
由關(guān)鍵字 gamma 指定恼除,必須大于 0 。
- sigmoid:
曼氛,
由
coef0
指定豁辉。
不同的核函數(shù)在初始化時由 kernel 關(guān)鍵字指定。
1.4.6.1 自定義核函數(shù)
您可以通過自定義 python 函數(shù)作為核函數(shù)或者使用預(yù)先計算的 Gram 矩陣來自定義核函數(shù)舀患。
使用自定義核函數(shù)的分類器行為與任何其它分類器一致徽级,只有以下區(qū)別:
- support_vectors_ 現(xiàn)在為空了,只有 support_ 對支持向量的索引進(jìn)行排序聊浅。
- fit() 方法的第一個參數(shù)的一個參考(不是一份拷貝)將保存用于將來參考餐抢。如果使用 fit() 和 predict() 時數(shù)據(jù)發(fā)生變化則不能得到期望的結(jié)果。
1.4.6.1.1 使用 python 函數(shù)作為核函數(shù)
您可以在構(gòu)造器中向關(guān)鍵字 kernel 傳入函數(shù)來使用自定義的核函數(shù)低匙。
自定義核函數(shù)的輸入必須為大小為(n_samples_1,n_features) 旷痕,(n_samples_2,n_features) 并返回(n_samples_1,n_samples_2)的核矩陣。
下面的代碼定義了一個線性核努咐,并創(chuàng)建了一個使用這個核函數(shù)的分類器實例:
>>> import numpy as np
>>> from sklearn import svm
>>> def my_kernel(X, Y):
... return np.dot(X, Y.T)
...
>>> clf = svm.SVC(kernel=my_kernel)
示例:
SVM with custom kernel苦蒿。
1.4.6.1.2 使用 Gram 矩陣
設(shè)置 kernel =precomputed 并在fit 方法的第一參數(shù)中傳入 Gram 矩陣來代替 X 。這里渗稍, 需要提供所有訓(xùn)練向量和測試向量的 kernel 值佩迟。
>>> import numpy as np
>>> from sklearn import svm
>>> X = np.array([[0, 0], [1, 1]])
>>> y = [0, 1]
>>> clf = svm.SVC(kernel='precomputed')
>>> # linear kernel computation
>>> gram = np.dot(X, X.T)
>>> clf.fit(gram, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
kernel='precomputed', max_iter=-1, probability=False,
random_state=None, shrinking=True, tol=0.001, verbose=False)
>>> # predict on training examples
>>> clf.predict(gram)
array([0, 1])
1.4.6.1.3 RBF 核函數(shù)的參數(shù)
使用 Radial Basis Function(RBF) 核函數(shù)訓(xùn)練 SVM 時,必須考慮兩個參數(shù) c 和 gamma竿屹。參數(shù) C 與 所有 SVM 核函數(shù)相似报强,權(quán)衡訓(xùn)練數(shù)據(jù)錯誤分類和決策表面的簡化。比較低的 c 使得決策表面比較平滑拱燃,比較高的 c 期望能夠正確分類所有樣本秉溉。gamma 定義單個樣本的影響, gamma 值越大,受到影響的樣本越近召嘶。
c 和 gamma 的正確選擇對 SVM 的性能至關(guān)重要父晶。建議使用 sklearn.model_selection.GridSearchCV
選擇足夠好的 c 和 gamma。
例子:
1.4.7 數(shù)學(xué)公式
支持向量機(jī)在高維或無限維空間中構(gòu)造超平面或超平面集弄跌,可用于分類甲喝,回歸或其他任務(wù)。 直觀來講铛只,通過與任何類的最近訓(xùn)練數(shù)據(jù)點具有最大距離(所謂的功能margin)的超平面實現(xiàn)良好的分離埠胖,因為通常 margin 越大,分類器的泛化誤差越低淳玩。
1.4.7.1 SVC
給定二分類訓(xùn)練向量 直撤、
,SVC 解決下面的問題:
subject to
它的對偶為:
subject to
這里谋竖,e為全為1的向量, 為上邊界侮东,
是一個 n*n 正半正定矩陣圈盔,
,這里
是核函數(shù)悄雅。
將訓(xùn)練向量映射到高維(可能無限)空間驱敲。
決策函數(shù)為:
注意, libsvm 和 liblinear 派生的 SVM 模型使用 c 作為正則化參數(shù)宽闲,但大多數(shù)其他估計器使用 alpha 众眨。兩個模型的正則化量之間的確切等價關(guān)系取決于模型的目標(biāo)函數(shù)。例如容诬,當(dāng)使用 sklearn_model.Ridge 回歸時娩梨,它們之間的關(guān)系為 。
這個參數(shù)可以通過包含內(nèi)積 的 dual_coef_ 進(jìn)行訪問览徒,support_vectors_ 包含支持向量狈定,intercept_ 表示獨立項
。
參考:
- “Automatic Capacity Tuning of Very Large VC-dimension Classifiers”, I. Guyon, B. Boser, V. Vapnik - Advances in neural information processing 1993.
- “Support-vector networks”, C. Cortes, V. Vapnik - Machine Learning, 20, 273-297 (1995).
1.4.7.2 NuSVC
我們引入一個新的參數(shù) 习蓬,這個參數(shù)控制支持向量數(shù)量和訓(xùn)練誤差纽什。參數(shù)
是訓(xùn)練誤差部分的上限和支持向量部分的下限。
可以證明 公式是
的另一表示方法躲叼,因此他們在數(shù)學(xué)上是等效的芦缰。
1.4.7.3 SVR
對于訓(xùn)練向量 , 向量
,
解決下面的問題:
subject to
它的對偶問題為:
subject to
這里e為全為 1 的向量枫慷, C>0 為上限让蕾,為 n*n 正半正定矩陣浪规,
為核函數(shù),這里的訓(xùn)練向量通過函數(shù)
映射到更高(可能無限)維度空間探孝。
決策函數(shù)為:
這些參數(shù)可以通過保存 的 dual_coef_ 笋婿、保存支持向量的 support_vectors 和 保存獨立項
的 intercept_ 獲取。
參考:
- “A Tutorial on Support Vector Regression”, Alex J. Smola, Bernhard Sch?lkopf - Statistics and Computing archive Volume 14 Issue 3, August 2004, p. 199-222.
1.4.8 執(zhí)行細(xì)節(jié)
算法內(nèi)部使用 libsvm 和 liblinear 處理所有計算問題再姑。這些庫使用 C 和 Cython 封裝萌抵。
參考:
詳細(xì)的算法執(zhí)行和細(xì)節(jié)描述請參考: