Libliner 中的-s 參數選擇:primal 和dual


Libliner 中的-s 參數選擇:primal 和dual

  • LIBLINEAR的優化算法主要分為兩大類,即求解原問題(primal problem)和對偶問題(dual problem)。求解原問題使用的是TRON的優化算法,對偶問題使用的是Coordinate Descent優化算法。總的來說,兩個算法的優化效率都較高,但還是有各自更加擅長的場景。對於樣本量不大,但是維度特別高的場景,如文本分類,更適合對偶問題求解,因為由於樣本量小,計算出來的Kernel Matrix也不大,后面的優化也比較方便。而如果求解原問題,則求導的過程中要頻繁對高維的特征矩陣進行計算,如果特征比較稀疏的話,那么就會多做很多無意義的計算,影響優化的效率。相反,當樣本數非常多,而特征維度不高時,如果采用求解對偶問題,則由於Kernel Matrix過大,求解並不方便。反倒是求解原問題更加容易。

下面是libliner 和libsvm的詳細介紹:

轉自:http://blog.chinaunix.net/uid-20761674-id-4840100.html

LIBSVM與LIBLINEAR

模型與優化

LIBSVM和LIBLINEAR都提供了多種不同的模型供使用者選擇,不同的模型有各自適用的場景。下面分別介紹LIBSVM和LIBLINEAR所提供的各種模型。

LIBSVM

下面是LIBSVM幫助內容提供的介紹,給出了LIBSVM支持的5種模型。其中模型0和1對應的都是SVM的分類模型,2對應的是one-class分類器,也就是只需要標注一個標簽,模型3和4對應的是SVM的回歸模型。

1 -s svm_type : set type of SVM (default 0) 2 0 -- C-SVC (multi-class classification) 3 1 -- nu-SVC (multi-class classification) 4 2 -- one-class SVM 5 3 -- epsilon-SVR (regression) 6 4 -- nu-SVR (regression)

首先來看最基礎的C-SVC模型。SVM可以寫成如下的優化目標函數(這里不詳細介紹推導算法了):

argminw,b,ξ subjectto 12wTw+C∑i=1lξiyi(wT?(xi)?b)≥1?ξi,ξi≤0,i=1,…,l

當模型使用linear kernel,也就是?(x)=x時,上面的問題一個標准的二次凸優化問題,可以比較方便的對每一個變量進行求導。求解這樣的問題是有很多快速的優化方法的,這些方法在LIBLINEAR中都有應用。但是如果是引入kernel的SVM,情況就大不一樣了。因為很多時候我們既不能得到核函數的具體形式,又無法得到特征在核空間中新的表達。這個時候,之前用在線性SVM上的的求解思路就完全不work了。為了解決這個問題,就必須采用標准的SVM求解思路,首先把原問題轉化為對偶問題,得到下面的目標函數(具體過程可以參考任何介紹SVM的資料):

argminα subjectto f(α)=12αTQα?eTα0≤αi≤C,i=1,…,l,yTα=0

通過對偶變化,上面的目標函數變成了一個關於變量α的二次型。很顯然,上面目標函數中最重要的常亮是矩陣Q,既訓練樣本的Kernel Matrix,滿足Qi.j=?(xi)T?(xj)。先看好的一方面,根據核函數的定義,能夠保證Q是一個正定的矩陣。也就是說,上面的目標函數還是一個凸函數,優化收斂后能保證得到的解是全局最優解, 這也是SVM的重要優勢之一。但是問題也隨之而來,使用常用的核函數,只要任意給出兩個向量,總是能夠計算出一個非0的距離。這也就意味着矩陣Q將會是一個非常稠密的矩陣,如果訓練樣本足夠多,那么矩陣Q的存儲和計算將成為很大的問題,這也是SVM的優化算法中的最大挑戰。

由於矩陣Q過大,所以想一次性優化整個α是比較困難的。所以常用的方法都是先把Q大卸八塊,每次選擇一部分的Q,然后update與這部分Q相關的α的值。這其中最著名的算法就是1998由John C. Platt提出的SMO算法,而LIBSVM的優化過程也是基於SMO算法進行的。SMO算法的每一步迭代都選擇最小的優化單元,也就是固定其他的α,只挑選兩個α的值進行優化。之所以不選擇一個,是因為有yTα=0的約束,至少選擇兩個α的坐標才有可能進行更新。本文主要目的是介紹LIBSVM,所以就不詳細討論SMO的細節了。至於LIBSVM中的具體算法實現,在LIBSVM的官方論文中介紹的很詳細,這里總結部分關鍵問題:

  • Working Set,也就是需要優化的α部分的選取
  • 迭代停止條件的設置
  • α的更新算法,也就是每一步子問題的求解方法
  • Shrinking,即移除一些已經滿足條件的α,加快收斂速度
  • Cache,當Q矩陣過大時,需要對矩陣進行緩存。

上面的每個問題,處理起來都不簡單。作為使用者,或許也沒有必要深諳里面的所有細節。我覺得最需要認識的兩個問題是:1) SVM的目標函數看起來好像是一個標准的優化問題,但實際求解卻要復雜得多。為了提高求解的速度,既要做算法上的優化,也需要做工程上的改進。如果只是簡簡單單按照教科書的方法,甚至直接調用一些優化的工具包來實現的SVM算法,最多也就算個demo。要能夠真正寫一個高效穩定、能處理大規模數據的SVM工具還是非常不容易的。所以用LIBSVM還是比自己實現算法要簡單靠譜不少。2)SVM的求解之所以要優化,就是因為這個問題本身計算和存儲比較麻煩。所以雖然做了這么多的優化,整個算法求解的效率仍然較低。所以我們在使用時還要注意各種程序的細節,提高運行的效率。另外,樣本量過大時,有時候為了充分利用數據,也不得不忍痛割愛,放棄kernel的使用。

除了標准的C-SVM,LIBSVM也提供了對其他一些SVM方法的支持。其中ν-SVM與C-SVM的算法與應用場景基本是相同的,唯一的區別是原本的參數C變成了參數ν。C-SVM中參數C調整范圍在[0,+∞),而ν-SVM中與之對應的參數ν的調整范圍變成了 (0,1]。這樣的設置使得ν-SVM更具解釋性,有時在參數設置上也能提供一定的方便。但ν-SVM與C-SVM並不存在本質上的差別,通過參數的調節,兩者可以達到完全相同的效果。所以在使用LIBSVM處理分類問題是,選擇上面任何一種方法都是OK的,只需要遵循自己的習慣就好了。

One-Class SVM也是LIBSVM所支持的一種分類方法。顧名思義,使用One Class時,只需要提供一類樣本,算法會學習一個盡量小的超球面包裹所有的訓練樣本。One-Class SVM看起來很有誘惑力,因為我們經常會遇到有一類樣本而需要學習分類器的情況。但事實上,一方面很多時候我們得到的正樣本在采樣過程中存在很大的偏差,導致學習出的One Class分類器不一定考慮到了所有正樣本的情形;另一方面,大部分問題還是存在很多構造人工負樣本的辦法。根據我的經驗,采用普通的SVM效果通常還是會好過One-Class SVM,而One-Class SVM在真實場景中的使用也並算不上多。因此在使用這個方法前也需要對問題進行更深入的研究。

最后,LIBSVM也支持基於SVM的回歸模型,即SVR。與分類模型類似,SVR也分為C-SVR和ν-SVR。SVR的目標函數與SVM的分類模型稍有區別。由於回歸問題預測值與目標值的偏差可大可小,因此SVR使用了兩個slack variable用來刻畫預測的誤差邊界。雖然存在這樣的差別,但是兩者的基本思路和優化算法與還是基本一致的。

在LIBSVM的實現中,上面五種模型,即C-SVM,ν-SVM,One-class SVM,C-SVR,ν-SVR,最終都可以轉化為一個更通用的優化框架,然后用同樣的策略進行求解,這也是LIBSVM所實現的主要功能。在實際使用中,最常用到的方法還是C-SVM,這是最傳統的SVM分類模型。

LIBLINEAR

LIBLINEAR是在LIBSVM流行多年后才開發的,要解決的問題本質上也比LIBSVM更簡單,其優勢主要在於效率與scalablility。之所以存在這樣的優勢,是因為線性SVM的求解要比kernel SVM簡單許多。

還從上面的對偶問題說起,之前SVM的求解很大程度上受到yTα=0的困擾,因此每次必須選擇一組 α進行優化。如果對這一約束項追根述源,可以發現這一項是通過令模型的常數項b導數為0而得到的。而在線性模型中,我們可以通過一個簡單地trick,令x=[x,1]和w=[w,b],這樣,在模型中的常數項就不存在了。當然,這樣的trick只能在線性模型中才適用。沒有了上面的約束,優化的目標函數變成了:

argminα subjecttof(α)=12αTQα?eTα0≤αi≤C,i=1,…,l

這個時候,就可以每次只選擇一個αi進行優化,每一輪遍歷α的所有維度,多輪迭代,直至最后收斂。這樣的優化算法叫做coordinate descent(坐標下降法)。利用線性函數的特殊性,直接根據α就可以計算出w的向量表示,於是大大提高了算法的效率。具體的優化算法可以參考文獻 A Dual Coordinate Descent Method for Large-scale Linear SVM

換一個看問題的角度,線性SVM的目標函數可以寫成下面的形式:

argminw12wTw+C∑i=1l(max(0,1?yiwTxi))

進一步對問題進行抽象,可以把一類分類問題寫成下面的形式:

argminwΩ(w)+C∑i=1l?(yi,wTxi)

其中的?作為誤差函數,用來度量預測值與目標值的損失。在上面的線性SVM的情形中,有

?(yi,wTxi)=max(0,1?yiwTxi)

這里的?稱為Hinge Loss。

又如在Logistic Regression中,loss function ?被定義為

?(yi,wTxi)=log(1+e?yiwTixi)

Ω一般被稱為正則化項(Regularizer),最常使用的就是前面出現的?2-norm,寫作wTw,也可以寫作∥w∥22,即向量w中所有元素的平方和。除?2-norm之外,?1-norm也是經常使用regularizer,而且會帶來一些特別的效果(后面會進行討論)。大量的監督學習模型都可以寫成loss function + regularizer的形式,而參數C則控制了兩者在最終損失函數中所占的比重。不同loss function與regularizer的選取以及兩者之間的平衡,是機器學習的最重要主題之一。

對於上面的問題,有很多成熟的算法可以進行模型的求解,比如最速梯度法,牛頓法等,對於樣本量較大時,也可以采用隨機梯度的方法進行訓練。 一般來說,由於考慮了二階導數,牛頓法本身的優化效率要高於只考慮一階導數的最速梯度法。但由於牛頓法本身在計算量和收斂性上存在很多局限性,所以很少直接使用,而是在牛頓法思想基礎上進行一定的改進。其中普遍使用的算法有BFGS和L-BFGS等。具體到liblinear軟件包,作者采用的是Trust Region Newton (TRON) method對模型對傳統牛頓法進行了改進,該方法被證明比L-BFGS訓練更加高效。

LIBLINEAR中實現了基於TRON方法的L-2 SVM和Logistical Regression模型訓練。其中的L2-loss SVM是標准SVM的變種,loss function變成了:

?(yi,wTxi)=(max(0,1?yiwTxi))2

從實際效果來說,L2-loss SVM與標准的L1-loss SVM並沒有太大的區別。但是在計算上,前者的求導形式更加簡單,便於梯度的計算與優化。LIBLINEAR並沒有實現Trust Region Newton法的標准L1-loss SVM實現,一方面是因為直接對hinge loss求導需要分段討論比較復雜,另一方面L2-loss SVM基本可以直接替代L1-loss SVM。不過在其他的一些軟件包中,如SVMLIN中,則實現了L1-loss SVM的原問題求解,但使用的優化算法是L-BGFS而不是TRON。

總結

前面介紹了LIBSVM和LIBLINEAR的優化算法,下面簡單總結一下不同算法的應用場景吧:

  • 所有線性問題都是用LIBLINEAR,而不要使用LIBSVM。
  • LIBSVM中的不同算法,如C-SVM和nu-SVM在模型和求解上並沒有本質的區別,只是做了一個參數的變換,所以選擇自己習慣的就好。
  • LIBLINEAR的優化算法主要分為兩大類,即求解原問題(primal problem)和對偶問題(dual problem)。求解原問題使用的是TRON的優化算法,對偶問題使用的是Coordinate Descent優化算法。總的來說,兩個算法的優化效率都較高,但還是有各自更加擅長的場景。對於樣本量不大,但是維度特別高的場景,如文本分類,更適合對偶問題求解,因為由於樣本量小,計算出來的Kernel Matrix也不大,后面的優化也比較方便。而如果求解原問題,則求導的過程中要頻繁對高維的特征矩陣進行計算,如果特征比較稀疏的話,那么就會多做很多無意義的計算,影響優化的效率。相反,當樣本數非常多,而特征維度不高時,如果采用求解對偶問題,則由於Kernel Matrix過大,求解並不方便。反倒是求解原問題更加容易。

多分類問題

LIBSVM和LIBLINEAR都支持多分類(Multi-class classification)問題。所謂多分類問題,就是說每一個樣本的類別標簽可以超過2個,但是最終預測的結果只能是一個類別。比如經典的手寫數字識別問題,輸入是一幅圖像,最后輸出的是0-9這十個數字中的某一個。

LIBSVM與LIBLINEAR但實現方式卻完全不同。LIBSVM采取的one vs one的策略,也就是所有的分類兩兩之間都要訓練一個分類器。這樣一來,如果存在k個class,理論上就需要訓練 k(k?1)/2個分類器。實際上,libsvm在這一步也進行了一定的優化,利用已有分類的關系,減少分類器的個數。盡管如此,LIBSVM在多分類問題上還是要多次訓練分類器。但是,考慮到前面說的LIBSVM的優化方法,隨着樣本數量的增加,訓練的復雜度會非線性的增加。而通過1VS1的策略,可以保證每一個子分類問題的樣本量不至於太多,其實反倒是方便了整個模型的訓練。

而LIBLINEAR則采取了另一種訓練策略,即one vs all。每一個class對應一個分類器,副樣本就是其他類別的所有樣本。由於LIBLINEAR能夠和需要處理的訓練規模比LIBSVM大得多,因此這種方式要比one vs one更加高效。此外,LIBLINEAR還實現了基於Crammer and Singer方法的SVM多分類算法,在一個統一的目標函數中學習每一個class對應的分類器。

輸出文件

一般來說,我們使用LIBLINEAR或者LIBSVM,可以直接調用系統的訓練與預測函數,不需要直接去接觸訓練得到的模型文件。但有時候我們也可能需要在自己的平台實現預測的算法,這時候就不可避免的要對模型文件進行解析。

由於LIBLINEAR與LIBSVM的訓練模型不同,因此他們對應的模型文件格式也不同。LIBLINEAR訓練結果的格式相對簡單,例如:

 1 solver_type L2R_L2LOSS_SVC_DUAL  2 nr_class 3  3 label 0 1 2  4 nr_feature 5  5 bias -1  6 w  7 -0.4021097293855418 0.1002472498884907 -0.1619908595357437  8 0.008699468444669581 0.2310109611908343 -0.2295723940247394  9 -0.6814324057724231 0.4263611607497726 -0.4190714505083906 10 -0.1505088594898125 0.2709227166451816 -0.1929294695905781 11 2.14656708009991 -0.007495770268046003 -0.1880325536062815

上面的solver_type表示求解算法,w以下表示求解得到的模型權重。其中每一列對應一個class的分類器,而每一行對應特征的一個維度。其中nr_class表示求解的個數,nr_feature表示特征的維度,bias表示模型的bias,可以人工設置權重。這里容易產生誤解的是label這個字段,表示的是每一個用戶訓練文件中label對應w的列數。比如在上面的模型中,用戶指定編號為0的分類器對應w的第一列。但是上面的對應關系並不是一定存在的,比如在二分類場景中,用將整樣本標為1,負樣本標為0,但在模型訓練中,LIBLINEAR會按照自己的編號系統進行訓練,因而有可能出現負樣本在前,正樣本在后的情形。這時候,就必須要根據label 1 0將LIBLIENAR內部的編號體系與真實的用戶標簽進行對應。當然,后來LIBLINEAR和LIBSVM做了一些優化,在二分類時,如果正負樣本標簽分別是-1和+1,那么可以始終保證正樣本出現在w的第一列。但是這個機制也不是完全靠譜,比如說在LIBLINEAR的spark實現代碼中,就沒有實現這個特性,曾經把我整的很慘。因此在這里還是需要十分注意。

LIBSVM的訓練結果格式就更復雜一些,例如:

 1 kernel_type rbf  2 gamma 0.0769231  3 nr_class 3  4 total_sv 140  5 rho -1.04496 0.315784 1.03037  6 label 1 0 -1  7 nr_sv 2 2 1  8 SV  9 0 1 1:0.583333 2:-1 3:0.333333 4:-0.603774 5:1 6:-1 7:1 8:0.358779 9:-1 10:-0.483871 12:-1 13:1 10 0 0.6416468628860974 1:0.125 2:1 3:0.333333 4:-0.320755 5:-0.406393 6:1 7:1 8:0.0839695 9:1 10:-0.806452 12:-0.333333 13:0.5 11 0 1 1:0.333333 2:1 3:-1 4:-0.245283 5:-0.506849 6:-1 7:-1 8:0.129771 9:-1 10:-0.16129 12:0.333333 13:-1 12 0.2685466895842373 0 1:0.583333 2:1 3:1 4:-0.509434 5:-0.52968 6:-1 7:1 8:-0.114504 9:1 10:-0.16129 12:0.333333 13:1 13 0 1 1:0.208333 2:1 3:0.333333 4:-0.660377 5:-0.525114 6:-1 7:1 8:0.435115 9:-1 10:-0.193548 12:-0.333333 13:1

上面參數的意義都比較直接,需要注意的是SV后面就是訓練出的模型參數,以支持向量的方式進行存儲。nr_sv給出了每一個支持向量所對應的模型,比如“2 2 1”就表示前兩行是標簽為1類的支持向量,其后面兩行是標簽為0類的支持向量,最后一行是標簽為-1類的支持向量。而具體每一行支持向量,在上面的模型中,由於存在三類,所以每一個支持向量有可能都會存在於兩個分類器中,所以前兩列的數分別對應了對剩下兩個分類作為支持向量時候的α值,后面才是真正的支持向量。


免責聲明!

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



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