SVM分類器實現實例


  我正在做一個關於SVM的小項目,在我執行驗證SVM訓練后的模型的時候,得到的report分數總是很高,無論是召回率(查全率)、精准度、還是f1-score都很高:

 

圖1 分類器分數report

  但是,對於訓練的效果就非常差,差到連包含訓練集的測試集都無法正確分類,如下圖所示,左邊是原圖像,右邊是分類圖像,(我標注的標簽樣本是黃色區域與褐色區域),其中SVC的默認參數為rbf、C=1.0、gamma=“auto_deprecated”,LinearSVC的默認參數為:C=1.0、class_weight=none、dual=true、loss=“squard_hinge”:

 

 

a.原圖

 

b.SVC(default parameter)

 

c.LinearSVC(default parameter)

圖2. 默認分類效果

  

  由上文可以發現,分類器分類的效果很不好,為了進一步驗證這個問題的原因,接下來我分別對LinearSVC和SVC進行參數調整:

1、LinearSVC參數調整

C:使用損失函數是用來對樣本的分類偏差進行描述,例如:

 

由上文可以發現,分類器分類的效果很不好,為了進一步驗證這個問題的原因,接下來我分別對LinearSVC和SVC進行參數調整:

1、LinearSVC參數調整

C:使用損失函數是用來對樣本的分類偏差進行描述,例如:

 

引入松弛變量后,優化問題可以寫為:

 

約束條件為: 

對於不同的C值對於本實例中的分類影響為,如圖3所示:

 

 

 

圖3. LinearSVC在不同懲罰系數C下的表現

 

 

由此可以看出SVC在懲罰系數為0.3、4.0、300時能夠較准確根據顏色對圖像進行分類。但是作者發現,懲罰系數相同,重新訓練時,會有不同的效果展示,才疏學淺,尚未能解釋,如果有知道為什么的大神,敬請指點迷津。

2、SVC參數調整

SVC模型中有兩個非常重要的參數,即C與gamma,其中C是懲罰系數,這里的懲罰系數同LinearSVC中的懲罰系數意義相同,表示對誤差的寬容度,C越高,說明越是不能容忍誤差的出現,C越小,表示越容易欠擬合,泛化能力變差。而另一個非常重要的參數gamma,是在選擇RBF函數作為核函數后,才出現的,這個也是LinearSVC中所不包含的。高斯函數RBF中的gamma值有一個自帶的默認值:gamma='auto_deprecated';表示的是數據映射到新的特征空間后的分布,gamma值越大,支持向量就越少,gamma值越小,支持向量就越多。支持向量的個數影響訓練與預測的速度。

RBF公式里面的sigma和gamma的關系為:

gamma的物理意義是關於RBF的幅寬,它可以影響每個支持向量對應的高斯的作用范圍,進而影響分類器的泛化能力。在本例中我更改了多組c的值、gamma的值效果均是差之千里:

 

 

C=2、gamma=’auto’ 

 C=default、gamma=1

 C=default、gamma=10 

C=default、gamma=100

4 SVC參數修改后分類效果

  

  如此效果真的是讓人頭疼,不過有一點可以確定的是在樣本海量的情況下,LinearSVC表現的要更好一些,算法執行時間很快,模型也較小,同樣的樣本下SVC用到的時間大概是LinearSVC的60倍左右。但是我們不能就此而已,我們要為問題尋找思路,這便轉換成了一個尋優問題。

  對於同時受到兩個參數影響的調參問題,我們可以使用一些尋優算法,常用的尋優算法可分為兩類:一類是在參數定義域空間內進行網格式搜索,例如專門針對SVC參數的GridSearch算法、交叉驗證算法,這類算法雖然穩定性高、參數估計准確,但是算法時間復雜度較高,計算量較大;另一類是采用啟發式優化,例如gaSVMForClass遺傳算法參數尋優、psoSVMForClass粒子群優化算法參數尋優等,這類算法能夠更快的尋找到最優參數組合。

本文先從GridSearch入手,畢竟它是sklearn模塊中的子模塊,導入方法也較簡單:直接from sklearn.model_selection import GridSearchCV就ok。

GridSearch網格搜索是一種調參手段,它的基本原理是暴力求解,即嘗試每一種可能性,將表現最好的認為是結果。使用的方法是窮舉搜索,在所有的候選參數中,通過循環遍歷,嘗試每一種可能性。對於要調整兩個參數c和g的高斯核函數來說,加入c的可能值有5種,g的可能值有6種,那么要遍歷所有的c與g的組合參數值,就有5*6種可能,也就是可以列一個表格包含5列6行的表格,然后依次對表格內容進行遍歷便可以實現遍歷所有的30種可能了。

例如:遍歷gamma在[0.001, 0.01, 0.1, 10, 100, 1000]范圍,C在[0.001, 0.01, 0.1, 10, 100, 1000]范圍內的最優值,便可以執行以下程序:

  

best_score = 0    
for gamma in [0.001, 0.01, 0.1, 10, 100, 1000]:
    for C in [0.001, 0.01, 0.1, 10, 100, 1000]:
        svm = SVC(gamma=gamma, C=C)
        svm.fit(X_train, y_train)
        score = svm.score(X_test, y_test)
        if score > best_score:
            best_score = score
            best_parameters = {'gamma':gamma, 'C':C}
print("best score:{:.2f}".format(best_score))
print("best parameters:{}".format(best_parameters))
最終結果便是:
best score:0.95

best parameters:{'gamma': 0.01, 'C': 10}

由此可以看出,其實這個GridSearch方法就是一個代替我們去進行嘗試的machine,它無法自己尋求合理的c與gamma的取值范圍,且比較耗時,你設置的C值和gamma值越多,尋優時間就會翻倍增加。另外我將這對最優組合放在實際預測中查看效果,效果也是不甚理想啊:

 

5 GridSearch尋到的最優C&gamma組合預測的效果

 

 

效果不理想的原因與我設置的C值與gamma值不全肯定有很大的關系,所以再利用我們這種方法就不怎么可行了,於是我們繼續更改:

第一種笨方法:

還是利用GridSearch,只不過在C、gamma賦值處將固定值替換為初值加步長的形式,用到了range()函數。

第二種方法是利用我前文所講到的離子群優化算法尋優:

離子群優化算法(Particle Swarm Optimization Algorithm, PSO)是一種基於群體協作的隨機搜索算法,其原理是源於對於鳥類捕食行為的研究,通過群體中的個體之間的協作核信息共享來尋找最優解,PSO算法的優勢在於簡單的算法實現和簡潔的參數設置,目前較廣泛的應用於函數優化、圖像處理等方面,但是其缺點也是不可忽視的:提前收斂、容易陷入局部最優、維數災難等缺點。

PSO算法的基本流程為:

 

 

 

 

Step1:初始化一群粒子(假設群體規模為已知),初始化隨機位置及速度;

Step2:評價每個粒子的適應度(計算其與最優位置的距離);

Step3:對每個微粒,將其適應值與其經過的最好位置pbest作比較,如果較好的話,則更新較好位置為最好位置;

Step4:加入權重因子,繼續迭代更改粒子的速度及位置;

Step5:重復step2和step3直至達到結束條件(全局最優/迭代次數上限),否則繼續執行2,3。

(未完待續,詳情見下篇)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM