我們構造svm模型的時候是有如下的參數可以設置的。
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)
我們先來看一下這些參數的含義:
(1)C: 目標函數的懲罰系數C,用來平衡分類間隔margin和錯分樣本的,default C=1.0;
(2)kernel:參數選擇有RBF(高斯核), Linear(線性核函數), Poly(多項式核函數), Sigmoid(sigmoid核函數), 默認的是"RBF";
(3)degree:如果kernel使用多項式核函數, degree決定了多項式的最高次冪;
(4)gamma:核函數的系數('Poly', 'RBF' and 'Sigmoid'), 默認是gamma=1 / n_features;
(5)coef0:核函數中的獨立項,'RBF' and 'sigmoid'有效;
(6)probablity: 可能性估計是否使用(true or false);
(7)shrinking:是否進行啟發式;
(8)tol(default=1e - 3): svm結束標准的精度;
(9)cache_size: 制定訓練所需要的內存(以MB為單位),在大樣本的時候,緩存大小會影響訓練速度,因此如果機器內存大,推薦用500MB甚至1000MB。默認是200,即200MB.
(10)class_weight: 指定樣本各類別的的權重,主要是為了防止訓練集某些類別的樣本過多,導致訓練的決策過於偏向這些類別。這里可以自己指定各個樣本的權重,或者用“balanced”,如果使用“balanced”,則算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。當然,如果你的樣本類別分布沒有明顯的偏倚,則可以不管這個參數,選擇默認的"None"(11)verbose: 跟多線程有關,不大明白啥意思具體;
(12)max_iter: 最大迭代次數,default=1, if max_iter=-1, no limited;
(13)decision_function_shape : 分類決策
‘ovo’ 一對一, ‘ovr’ 多對多 or None 無, default=ovr
OvR(one ve rest)的思想很簡單,無論你是多少元分類,我們都可以看做二元分類。具體做法是,對於第K類的分類決策,我們把所有第K類的樣本作為正例,除了第K類樣本以外的所有樣本都作為負例,然后在上面做二元分類,得到第K類的分類模型。其他類的分類模型獲得以此類推。
OvO(one-vs-one)則是每次每次在所有的T類樣本里面選擇兩類樣本出來,不妨記為T1類和T2類,把所有的輸出為T1和T2的樣本放在一起,把T1作為正例,T2作為負例,進行二元分類,得到模型參數。我們一共需要T(T-1)/2次分類。
從上面的描述可以看出OvR相對簡單,但分類效果相對略差(這里指大多數樣本分布情況,某些樣本分布下OvR可能更好)。而OvO分類相對精確,但是分類速度沒有OvR快。一般建議使用OvO以達到較好的分類效果。
(14)random_state :用於概率估計的數據重排時的偽隨機數生成器的種子。
1)線性核函數(Linear Kernel)表達式為:K(x,z)=x?zK(x,z)=x?z,就是普通的內積,LinearSVC 和 LinearSVR 只能使用它。
2) 多項式核函數(Polynomial Kernel)是線性不可分SVM常用的核函數之一,表達式為:K(x,z)=(γx?z+r)dK(x,z)=(γx?z+r)d ,其中,γ,r,dγ,r,d都需要自己調參定義,比較麻煩。
3)高斯核函數(Gaussian Kernel),在SVM中也稱為徑向基核函數(Radial Basis Function,RBF),它是libsvm默認的核函數,當然也是scikit-learn默認的核函數。表達式為:K(x,z)=exp(?γ||x?z||2)K(x,z)=exp(?γ||x?z||2), 其中,γγ大於0,需要自己調參定義。
4)Sigmoid核函數(Sigmoid Kernel)也是線性不可分SVM常用的核函數之一,表達式為:K(x,z)=tanh(γx?z+r)K(x,z)=tanh(γx?z+r), 其中,γ,rγ,r都需要自己調參定義。
雖然有這么多的核函數,但是實際上我們常用的只有兩個一個是線性核函數,還是有一個是高斯核函數,原因是它們的效果往往最好,調參數量也比較少,不是很麻煩。當我們使用線性核函數的時候我們的主要的調參的目標就是C,當我們使用高斯核函數的時候我們的主要的調參的目標就是C和gamma。
要就是調節兩個參數,一個是C,一個是gamma
C是懲罰系數也就是松弛變量的系數。它在優化函數里主要是平衡支持向量的復雜度和誤分類率這兩者之間的關系,可以理解為正則化系數。當比較大時,我們的損失函數也會越大,這意味着我們不願意放棄比較遠的離群點。這樣我們會有更加多的支持向量,也就是說支持向量和超平面的模型也會變得越復雜,也容易過擬合。反之,當比較小時,意味我們不想理那些離群點,會選擇較少的樣本來做支持向量,最終的支持向量和超平面的模型也會簡單。scikit-learn中默認值是1。
另一個超參數是RBF核函數的參數。回憶下RBF 核函數 ,主要定義了單個樣本對整個分類超平面的影響,當比較大時,單個樣本對整個分類超平面的影響比較小,不容易被選擇為支持向量,或者說整個模型的支持向量也會少。scikit-learn中默認值是'auto'
實際上我們最常見的就是調整這兩個參數。下面案例就是實際使用高斯核函數時的調參的案例。它使用sklearn封裝好的調參庫進行網格調參,也叫暴力調參。
from sklearn import svm
from sklearn.model_selection import GridSearchCV
from sklearn import metrics
import numpy as np
import pandas as pd
import scipy.io as sio
mat=sio.loadmat('ex6data3.mat')
print(mat.keys())
training=pd.DataFrame(mat.get('X'), columns=['X1', 'X2'])
training['y']=mat.get('y')
cv=pd.DataFrame(mat.get('Xval'), columns=['X1', 'X2'])
cv['y']=mat.get('yval')
candidate=[0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30, 100]
combination=[(C, gamma) for C in candidate for gamma in candidate]
if __name__=="__main__":
parameters={'C': candidate, 'gamma': candidate}
svc=svm.SVC()
clf=GridSearchCV(svc, parameters, n_jobs=-1)
clf(training[['X1', 'X2']], training['y'])
print (clf.best_params_)
print (clf.best_score_)
ypred=clf.predict(cv[['X1', 'X2']])
print(metrics.classification_report(cv['y'], ypred))