在支持向量機(以下簡稱SVM)的核函數中,高斯核(以下簡稱RBF)是最常用的,從理論上講, RBF一定不比線性核函數差,但是在實際應用中,卻面臨着幾個重要的超參數的調優問題。如果調的不好,可能比線性核函數還要差。所以我們實際應用中,能用線性核函數得到較好效果的都會選擇線性核函數。如果線性核不好,我們就需要使用RBF,在享受RBF對非線性數據的良好分類效果前,我們需要對主要的超參數進行選取。本文我們就對scikit-learn中 SVM RBF的調參做一個小結。
1. SVM RBF 主要超參數概述
如果是SVM分類模型,這兩個超參數分別是懲罰系數$C$和RBF核函數的系數$\gamma$。當然如果是nu-SVC的話,懲罰系數$C$代替為分類錯誤率上限nu, 由於懲罰系數$C$和分類錯誤率上限nu起的作用等價,因此本文只討論帶懲罰系數C的分類SVM。
懲罰系數$C$即我們在之前原理篇里講到的松弛變量的系數。它在優化函數里主要是平衡模型的復雜度和誤分類率這兩者之間的關系,可以理解為正則化系數。當$C$比較大時,我們的損失函數也會越大,這意味着我們不願意放棄比較遠的離群點。這樣我們會有比較少的支持向量,也就是說支持向量和超平面的模型也會變得越復雜,也容易過擬合。反之,當$C$比較小時,意味我們不想理那些離群點,會選擇較多的樣本來做支持向量,最終的支持向量和超平面的模型也會簡單。scikit-learn中默認值是1。
另一個超參數是RBF核函數的參數$\gamma$。回憶下RBF 核函數$K(x, z) = exp(-\gamma||x-z||^2)\;\;\gamma>0$,$\gamma$主要定義了單個樣本對整個分類超平面的影響,當$\gamma$比較小時,單個樣本對整個分類超平面的影響距離比較遠,容易被選擇為支持向量,反之,當$\gamma$比較大時,單個樣本對整個分類超平面的影響距離比較近,不容易被選擇為支持向量,或者說整個模型的支持向量也會少,模型會變得更復雜。scikit-learn中默認值是$\frac{1}{樣本特征數}$
如果把懲罰系數$C$和RBF核函數的系數$\gamma$一起看,當$C$比較大, $\gamma$比較大時,我們會有更少的支持向量,我們的模型會比較復雜,容易過擬合一些。如果$C$比較小 , $\gamma$比較小時,模型會變得簡單,支持向量的個數會多。
以上是SVM分類模型,我們再來看看回歸模型。
SVM回歸模型的RBF核比分類模型要復雜一點,因為此時我們除了懲罰系數$C$和RBF核函數的系數$\gamma$之外,還多了一個損失距離度量$\epsilon$。如果是nu-SVR的話,損失距離度量$\epsilon$代替為分類錯誤率上限nu,由於損失距離度量$\epsilon$和分類錯誤率上限nu起的作用等價,因此本文只討論帶距離度量$\epsilon$的回歸SVM。
對於懲罰系數$C$和RBF核函數的系數$\gamma$,回歸模型和分類模型的作用基本相同。對於損失距離度量$\epsilon$,它決定了樣本點到超平面的距離損失,當$\epsilon$比較大時,損失$|y_i - w \bullet \phi(x_i ) -b| - \epsilon$較小,更多的點在損失距離范圍之內,而沒有損失,模型較簡單,而當$\epsilon$比較小時,損失函數會較大,模型也會變得復雜。scikit-learn中默認值是0.1。
如果把懲罰系數$C$,RBF核函數的系數$\gamma$和損失距離度量$\epsilon$一起看,當$C$比較大, $\gamma$比較大,$\epsilon$比較小時,我們會有更少的支持向量,我們的模型會比較復雜,容易過擬合一些。如果$C$比較小 , $\gamma$比較小,$\epsilon$比較大時,模型會變得簡單,支持向量的個數會多。
2. SVM RBF 主要調參方法
對於SVM的RBF核,我們主要的調參方法都是交叉驗證。具體在scikit-learn中,主要是使用網格搜索,即GridSearchCV類。當然也可以使用cross_val_score類來調參,但是個人覺得沒有GridSearchCV方便。本文我們只討論用GridSearchCV來進行SVM的RBF核的調參。
我們將GridSearchCV類用於SVM RBF調參時要注意的參數有:
1) estimator :即我們的模型,此處我們就是帶高斯核的SVC或者SVR
2) param_grid:即我們要調參的參數列表。 比如我們用SVC分類模型的話,那么param_grid可以定義為{"C":[0.1, 1, 10], "gamma": [0.1, 0.2, 0.3]},這樣我們就會有9種超參數的組合來進行網格搜索,選擇一個擬合分數最好的超平面系數。
3) cv: S折交叉驗證的折數,即將訓練集分成多少份來進行交叉驗證。默認是3,。如果樣本較多的話,可以適度增大cv的值。
網格搜索結束后,我們可以得到最好的模型estimator, param_grid中最好的參數組合,最好的模型分數。
下面我用一個具體的分類例子來觀察SVM RBF調參的過程
3. 一個SVM RBF分類調參的例子
這里我們用一個實例來講解SVM RBF分類調參。推薦在ipython notebook運行下面的例子。
完整代碼參看我的github:https://github.com/ljpzzz/machinelearning/blob/master/classic-machine-learning/svm_classifier.ipynb
首先我們載入一些類的定義。
import numpy as np import matplotlib.pyplot as plt from sklearn import datasets, svm from sklearn.svm import SVC from sklearn.datasets import make_moons, make_circles, make_classification %matplotlib inline
接着我們生成一些隨機數據來讓我們后面去分類,為了數據難一點,我們加入了一些噪音。生成數據的同時把數據歸一化
X, y = make_circles(noise=0.2, factor=0.5, random_state=1); from sklearn.preprocessing import StandardScaler X = StandardScaler().fit_transform(X)
我們先看看我的數據是什么樣子的,這里做一次可視化如下:
from matplotlib.colors import ListedColormap cm = plt.cm.RdBu cm_bright = ListedColormap(['#FF0000', '#0000FF']) ax = plt.subplot() ax.set_title("Input data") # Plot the training points ax.scatter(X[:, 0], X[:, 1], c=y, cmap=cm_bright) ax.set_xticks(()) ax.set_yticks(()) plt.tight_layout() plt.show()
生成的圖如下, 由於是隨機生成的所以如果你跑這段代碼,生成的圖可能有些不同。
好了,現在我們要對這個數據集進行SVM RBF分類了,分類時我們使用了網格搜索,在C=(0.1,1,10)和gamma=(1, 0.1, 0.01)形成的9種情況中選擇最好的超參數,我們用了4折交叉驗證。這里只是一個例子,實際運用中,你可能需要更多的參數組合來進行調參。
from sklearn.model_selection import GridSearchCV grid = GridSearchCV(SVC(), param_grid={"C":[0.1, 1, 10], "gamma": [1, 0.1, 0.01]}, cv=4) grid.fit(X, y) print("The best parameters are %s with a score of %0.2f" % (grid.best_params_, grid.best_score_))
最終的輸出如下:
The best parameters are {'C': 10, 'gamma': 0.1} with a score of 0.91
也就是說,通過網格搜索,在我們給定的9組超參數中,C=10, Gamma=0.1 分數最高,這就是我們最終的參數候選。
到這里,我們的調參舉例就結束了。不過我們可以看看我們的普通的SVM分類后的可視化。這里我們把這9種組合各個訓練后,通過對網格里的點預測來標色,觀察分類的效果圖。代碼如下:
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max,0.02), np.arange(y_min, y_max, 0.02)) for i, C in enumerate((0.1, 1, 10)): for j, gamma in enumerate((1, 0.1, 0.01)): plt.subplot() clf = SVC(C=C, gamma=gamma) clf.fit(X,y) Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) # Put the result into a color plot Z = Z.reshape(xx.shape) plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8) # Plot also the training points plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.coolwarm) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) plt.xticks(()) plt.yticks(()) plt.xlabel(" gamma=" + str(gamma) + " C=" + str(C)) plt.show()
生成的9個組合的效果圖如下:
以上就是SVM RBF調參的一些總結,希望可以幫到朋友們。
(歡迎轉載,轉載請注明出處。歡迎溝通交流: liujianping-ok@163.com)