1. 程式人生 > >Sequential Minimal Optimization(SMO,序列最小優化演算法)初探

Sequential Minimal Optimization(SMO,序列最小優化演算法)初探

什麼是SVM


SVM是Support Vector Machine(支援向量機)的英文縮寫,是上世紀九十年代興起的一種機器學習演算法,在目前神經網路大行其道的情況下依然保持著生命力。有人說現在是神經網路深度學習的時代了,AI從業者可以不用瞭解像SVM這樣的古董了。姑且不說SVM是否真的已經沒有前途了,僅僅是SVM在數學上優美的推導就值得後來者好好欣賞一番,這也是筆者迄今為止見過機器學習領域最優美的數學推導。

和大多數二分類演算法一樣,SVM演算法也是致力於在正例和反例之間找出一個超平面來將它們區分開來,如下圖所示:

 
圖1

如圖所示,正例用“+”號表示,反例用“-”號表示。從圖中可以看出,正例和反例是線性可分的。學習器的目的就是要學出一條如圖所示的紅色超平面將正例和反例區分開來。這也是其他非SVM分類器的共同目標,即:

   

而SVM與其它分類器所不同的是它引入了“支援向量”這一概念,反映到圖中也就是紅色的小點所代表的向量。(注:由於筆者作圖時採用的SVM是軟間隔的版本,因此支援向量不像是大多數教科書上採用硬間隔的SVM那樣)由SVM的優化目標我們可以知道:樣本空間中任意一個點x到該超平面的的距離可寫為:

   

假設超平面可以完全正確地將所有樣本分類,則對於任意一個樣本(xi,yi)來說都有如下性質(注:樣本的標籤用+1代表正例,-1代表反例):

   

訓練樣本中使上式成立的樣本稱為支援向量,兩個異類支援向量到超平面距離之和為:

 
 

上式被稱為“間隔”。SVM的優化目標是為了找到這樣一個劃分超平面,該超平面能使間隔最大化,則SVM的優化目標可以表示為如下形式:

   

這就是SVM的基本數學表達,接下來就要對SVM問題進行求解。從上面的數學形式可以看出這是一個優化問題,可以使用拉格朗日乘子法求解其對偶問題。由於本文不是專門介紹SVM的,因此忽略掉具體的推導,直接給出SVM的對偶問題表達:

   

由於採用了拉格朗日乘子法,因此該對偶問題還有一個KKT條件約束,即要求:

   

以上,就是SVM的一些相關介紹。需要特別說明的是,以上的推導都是建立在“硬間隔”的基礎上,“硬間隔”要求樣本集中每一個樣本都滿足約束條件。在現實中往往很難確定合適的核函式使得訓練樣本在特徵空間中是線性可分的,緩解該問題的一個辦法是允許支援向量機在一些樣本上出錯,為此引入“軟間隔”的概念。具體來說,“硬間隔”要求所有參與訓練的樣本都必須滿足SVM的約束條件,而“軟間隔”允許有部分樣本不滿足這樣的約束。由於本文不是專門論述SVM的,因此就不展開講“軟間隔”所帶來的一些新的問題,只說一下“軟間隔”條件下新的優化目標:

   

KKT條件為:

   

其中,C為容忍度因子,可以理解為SVM對“軟間隔”的支援度。若C為無窮大,則所有的訓練樣本均必須滿足SVM的約束條件,C值越小就允許越多的樣本不滿足約束條件。

SMO演算法思想


通過觀察SVM的優化目標我們可以發現其最終的目的是要計算出一組最優的alpha和常數項b的值。SMO演算法的中心思想就是每次選出兩個alpha進行優化(之所以是兩個是因為alpha的約束條件決定了其與標籤乘積的累加等於0,因此必須一次同時優化兩個,否則就會破壞約束條件),然後固定其他的alpha值。重複此過程,直到達到某個終止條件程式退出並得到我們需要的優化結果。接下來,就具體推導一下SMO演算法的細節。

演算法數學推導


由於SVM中有核函式的概念,因此我們用Kij來表示在核函式K下向量i和向量j的計算值。現在假定我們已經選出alpha1和alpha2兩個待優化項,然後將原優化目標函式展開為與alpha1和alpha2有關的部分和無關的部分:

   

其中c是與alpha1和alpha2無關的部分,在本次優化中當做常數項處理。由SVM優化目標函式的約束條件:

   

可以得到:

   

將優化目標中所有的alpha1都替換為用alpha2表示的形式,得到如下式子:

   

此時,優化目標中僅含有alpha2一個待優化變量了,我們現在將待優化函式對alpha2求偏導得到如下結果:

   

已知:

   

將以上三個條件帶入偏導式子中,得到如下結果:

   

化簡後得:

   

記:

   

若n<=0則退出本次優化,若n>0則可得到alpha2的更新公式

   

此時,我們已經得到了alpha2的更新公式。不過我們此時還需要考慮alpha2的取值範圍問題。因為alpha2的取值範圍應該是在0到C之間,但是在這裡並不能簡單地把取值範圍限定在0至C之間,因為alpha2的取值不僅僅與其本身的範圍有關,也與alpha1,y1和y2有關。設alpha1*y1+alpha2*y2=k,畫出其約束,在這裡要分兩種情況,即y1是否等於y2。我們在這裡先來考慮y1!=y2的情況:在這種情況下alpha1-alpha2=k:

  圖2

可以看出此時alpha2的取值範圍為:

   

當y1=y2時,alpha1+alpha2=k:

  圖3

可以看出此時alpha2的取值範圍為:

   

以上,可以總結出alpha2的取值上下界的規律:

   

故可得到alpha2的取值範圍:

   

由alpha_old1y1+alpha_old2y2=alpha_new1y1+alpha_new2y2可得alpha1的更新公式:

   

接下來,需要確定常數b的更新公式,在這裡首先需要根據“軟間隔”下SVM優化目標函式的KKT條件推匯出新的KKT條件,得到結果如下:

   

由於現在alpha的取值範圍已經限定在0至C之間,也就是上面KKT條件的第三種情況。接下來我們將第三種KKT條件推廣到任意核函式的情境下:

   

由此我們可以得到常數b的更新公式:

   

其中Ei是SVM的預測誤差,計算式為:

   

以上,筆者就已經把SMO演算法的大部分細節推匯出來了。接下來,我們可以根據這些推導對SMO演算法進行實現,並且用我們的演算法訓練一個SVM分類器。

SMO的演算法實現


SMO演算法的實現還是比較複雜的,有很多細節,我們不用一一關注,只用抓住其中兩個特別重要的點就行了:1、如何選取每次迭代的alpha對;2、如何確定SVM優化程式的退出條件。筆者將就這兩個主要問題進行論述。首先關注第一個問題:如何選取alpha對。

我們可以簡化一下第一個問題:假定現在已經選取了第一個待優化的alpha,如何選取另一個alpha?在SMO演算法中為了讓迭代次數儘量少,收斂速度儘量快,演算法要求我們選取的兩個alpha有儘可能大的“差異”。在演算法的實現中我們用預測的誤差值來表徵一個alpha的效果。那麼兩個aplha儘可能不同反映在演算法上就是兩個alpha所對應的預測誤差值之差的絕對值最大,該思想用程式碼表現出來如下圖所示:

  圖4

上面的程式碼反映出了這樣一種思想:首先傳入第一個alpha所對應的索引值“i”,然後搜尋誤差列表eCache,在其中找到與“i”所對應的誤差值相差絕對值最大的那個索引值“j”,則另一個alpha的索引值就定為“j”。若誤差值列表eCache還沒有初始化則從所有的索引值中隨機選取一個索引值作為另一個alpha的索引值。

那麼第一個alpha如何選取呢?這個問題與另外兩個問題是相關的:第一個問題是選取的alpha值是否違反KKT條件,如果該alpha值違反了KKT條件則該alpha是不能夠作為優化物件的;第二個問題與SMO優化演算法的優化終止條件有關,通常SMO演算法會在一個死迴圈中反覆執行兩個過程,第一個過程是遍歷所有的alpha值,每掃描到一個alpha就將其作為alpha對的第一個值傳入內迴圈,同時根據上一段提出的選取準則選擇另一個alpha。遍歷完一次alpha值之後若alpha值被優化器改變的次數不為0則本次迴圈結束同時修改一些標誌量然後進入下一次迴圈。下一次迴圈執行第二個過程:遍歷alpha值列表中所有不為0的值,每掃描到一個不為0的alpha值之後就將其傳入內迴圈,然後執行和上面相同的過程。重複執行上述過程,最終,當某次迴圈遍歷優化所有alpha列表後卻沒有一個alpha值被優化器改變則程式認為優化任務完成了,程式退出。程式碼如下:

  圖5

以上,就是SMO演算法在實現時的一些細節。完整的SMO實現還是比較複雜的,有很多的小細節需要注意,在這裡就不一一論述了。