SVM分類---識別艦船和飛機

轉載自:

http://blog.csdn.net/v_july_v/article/details/7624837

http://blog.csdn.net/gavin__zhou/article/details/49874001

SVM介紹

SVM網上已經有說的非常好的,有淺顯易懂的也有從最基礎的公式上一步步推導的,參考大神July的這篇關於SVM的博客,希望深入瞭解的可以看看這篇講的非常好。


一、線性分類器: 
首先給出一個非常非常簡單的分類問題(線性可分),我們要用一條直線,將下圖中黑色的點和白色的點分開,很顯然,圖上的這條直線就是我們要求的直線之一(可以有無數條這樣的直線) 
這裏寫圖片描述假如說,我們令黑色的點 = -1, 白色的點 = +1,直線f(x) = w.x + b,這兒的x、w是向量,其實寫成這種形式也是等價的f(x) = w1x1 + w2x2 … + wnxn + b, 當向量x的維度=2的時候,f(x) 表示二維空間中的一條直線, 當x的維度=3的時候,f(x) 表示3維空間中的一個平面,當x的維度=n > 3的時候,表示n維空間中的n-1維超平面。這些都是比較基礎的內容,如果不太清楚,可能需要複習一下微積分、線性代數的內容。 
剛剛說了,我們令黑色白色兩類的點分別爲+1, -1,所以當有一個新的點x需要預測屬於哪個分類的時候,我們用sgn(f(x)),就可以預測了,sgn表示符號函數,當f(x) > 0的時候,sgn(f(x)) = +1, 當f(x) < 0的時候sgn(f(x)) = –1。 
這裏寫圖片描述 
一個很直觀的感受是,讓這條直線到給定樣本中最近的點最遠,這句話讀起來比較拗口,下面給出幾個圖,來說明一下: 
第一種分法: 
這裏寫圖片描述 
這裏寫圖片描述 
這兩種分法哪種更好呢?從直觀上來說,就是分割的間隙越大越好,把兩個類別的點分得越開越好。就像我們平時判斷一個人是男還是女,就是很難出現分錯的情況,這就是男、女兩個類別之間的間隙非常的大導致的,讓我們可以更準確的進行分類。在SVM中,稱爲Maximum Marginal,是SVM的一個理論基礎之一。選擇使得間隙最大的函數作爲分割平面是由很多道理的,比如說從概率的角度上來說,就是使得置信度最小的點置信度最大(聽起來很拗口),從實踐的角度來說,這樣的效果非常好,等等。這裏就不展開講,作爲一個結論就ok了,:) 
上圖被紅色和藍色的線圈出來的點就是所謂的支持向量(support vector)。 
這裏寫圖片描述 
上圖就是一個對之前說的類別中的間隙的一個描述。Classifier Boundary就是f(x),紅色和藍色的線(plus plane與minus plane)就是support vector所在的面,紅色、藍色線之間的間隙就是我們要最大化的分類間的間隙。這裏寫圖片描述 
這裏直接給出M的式子:這裏寫圖片描述 
另外支持向量位於wx + b = 1與wx + b = -1的直線上,我們在前面乘上一個該點所屬的類別y(還記得嗎?y不是+1就是-1),就可以得到支持向量的表達式爲:y(wx + b) = 1,這樣就可以更簡單的將支持向量表示出來了。 
當支持向量確定下來的時候,分割函數就確定下來了,兩個問題是等價的。得到支持向量,還有一個作用是,讓支持向量後方那些點就不用參與計算了。這點在後面將會更詳細的講講。 
在這個小節的最後,給出我們要優化求解的表達式: 
這裏寫圖片描述 
||w||的意思是w的二範數,跟上面的M表達式的分母是一個意思,之前得到,M = 2 / ||w||,最大化這個式子等價於最小化||w||, 另外由於||w||是一個單調函數,我們可以對其加入平方,和前面的係數,熟悉的同學應該很容易就看出來了,這個式子是爲了方便求導。 
這個式子有還有一些限制條件,完整的寫下來,應該是這樣的:(原問題) 
這裏寫圖片描述 
s.t的意思是subject to,也就是在後面這個限制條件下的意思,這個詞在svm的論文裏面非常容易見到。這個其實是一個帶約束的二次規劃(quadratic programming, QP)問題,是一個凸問題,凸問題就是指的不會有局部最優解,可以想象一個漏斗,不管我們開始的時候將一個小球放在漏斗的什麼位置,這個小球最終一定可以掉出漏斗,也就是得到全局最優解。s.t.後面的限制條件可以看做是一個凸多面體,我們要做的就是在這個凸多面體中找到最優解。這些問題這裏不展開,因爲展開的話,一本書也寫不完。如果有疑問請看看wikipedia。 
二、轉化爲對偶問題,並優化求解: 
這裏寫圖片描述 
求解這個式子的過程需要拉格朗日對偶性的相關知識(另外pluskid也有一篇文章專門講這個問題),並且有一定的公式推導,如果不感興趣,可以直接跳到後面用藍色公式表示的結論,該部分推導主要參考自plukids的文章。 
這裏寫圖片描述 
首先讓L關於w,b最小化,分別令L關於w,b的偏導數爲0,得到關於原問題的一個表達式 
將兩式帶回L(w,b,a)得到對偶問題的表達式 
新問題加上其限制條件是(對偶問題): 
這裏寫圖片描述 
這個就是我們需要最終優化的式子。至此,得到了線性可分問題的優化式子。 
求解這個式子,有很多的方法,比如SMO等等,個人認爲,求解這樣的一個帶約束的凸優化問題與得到這個凸優化問題是比較獨立的兩件事情,所以在這篇文章中準備完全不涉及如何求解這個話題,如果之後有時間可以補上一篇文章來談談:)。 
三、線性不可分的情況: 
接下來談談線性不可分的情況,因爲線性可分這種假設實在是太有侷限性了: 
下圖就是一個典型的線性不可分的分類圖,我們沒有辦法用一條直線去將其分成兩個區域,每個區域只包含一種顏色的點。 
這裏寫圖片描述 
要想在這種情況下的分類器,有兩種方式,一種是用曲線去將其完全分開,曲線就是一種非線性的情況,跟核函數有一定的關係: 
這裏寫圖片描述 
另外一種還是用直線,不過不用去保證可分性,就是包容那些分錯的情況,不過我們得加入懲罰函數,使得點分錯的情況越合理越好。其實在很多時候,不是在訓練的時候分類函數越完美越好,因爲訓練函數中有些數據本來就是噪聲,可能就是在人工加上分類標籤的時候加錯了,如果我們在訓練(學習)的時候把這些錯誤的點學習到了,那麼模型在下次碰到這些錯誤情況的時候就難免出錯了(假如老師給你講課的時候,某個知識點講錯了,你還信以爲真了,那麼在考試的時候就難免出錯)。這種學習的時候學到了“噪聲”的過程就是一個過擬合(over-fitting),這在機器學習中是一個大忌,我們寧願少學一些內容,也堅決杜絕多學一些錯誤的知識。還是回到主題,用直線怎麼去分割線性不可分的點: 
我們可以爲分錯的點加上一點懲罰,對一個分錯的點的懲罰函數就是這個點到其正確位置的距離: 
這裏寫圖片描述 
公式中這裏寫圖片描述 藍色的部分爲在線性可分問題的基礎上加上的懲罰函數部分,當xi在正確一邊的時候,ε=0,R爲全部的點的數目,C是一個由用戶去指定的係數,表示對分錯的點加入多少的懲罰,當C很大的時候,分錯的點就會更少,但是過擬合的情況可能會比較嚴重,當C很小的時候,分錯的點可能會很多,不過可能由此得到的模型也會不太正確,所以如何選擇C是有很多學問的,不過在大部分情況下就是通過經驗嘗試得到的。 
接下來就是同樣的,求解一個拉格朗日對偶問題,得到一個原問題的對偶問題的表達式: 
這裏寫圖片描述 
藍色的部分是與線性可分的對偶問題表達式的不同之處。在線性不可分情況下得到的對偶問題,不同的地方就是α的範圍從[0, +∞),變爲了[0, C],增加的懲罰ε沒有爲對偶問題增加什麼複雜度。 
四、多分類問題: 
上面所談到的分類都是2分類的情況,當N分類的情況下,主要有兩種方式,一種是1 vs (N – 1)一種是1 vs 1,前一種方法我們需要訓練N個分類器,第i個分類器是看看是屬於分類i還是屬於分類i的補集(出去i的N-1個分類)。 
後一種方式我們需要訓練N * (N – 1) / 2個分類器,分類器(i,j)能夠判斷某個點是屬於i還是屬於j。 
這種處理方式不僅在SVM中會用到,在很多其他的分類中也是被廣泛用到,從林教授(libsvm的作者)的結論來看,1 vs 1的方式要優於1 vs (N – 1)。

應用SVM分類艦船和飛機

使用Matlab自帶的SVM分類其來進行艦船和飛機的分類,艦船和飛機的樣本如下圖所示: 
艦船包含多類,比如航母,驅逐艦,潛艇等,飛機也有比如戰鬥機,直升機等等.對於二分類問題來說,只需要將所有的艦船和飛機的樣本放一起就可以了. 
(1)提取特徵 
我們使用了Gabor濾波來進行形狀和紋理的提取,原因就是基於直觀的映像,飛機和檢查"長得"差別很大,至於如何使用Gabor濾波,可以參照這個,我也會將我使用的Gabor代碼上傳. 
Gabor濾波提取的特徵長度爲4400,按照列來進行存儲. 
(2)應用SVM分類器

SVM分類代碼:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">%% <span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">load</span> the test data <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">do</span> SVM classification
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span> = svmclassify(svmClassifier,test_all_data<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">');</span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

svmClassifier是SVM的分類器:

<code class="hljs makefile has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">%% SVM TRAIN
<span class="hljs-constant" style="box-sizing: border-box;">labels</span> = [ship_label;plane_label];
<span class="hljs-constant" style="box-sizing: border-box;">train_all_data</span> = [ship_data';plane_data'];
<span class="hljs-constant" style="box-sizing: border-box;">svmClassifier</span> = svmtrain(train_all_data,labels);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

ship_label和plane_label是相應的標籤,大小爲1xN的行向量,ship_data和plane_data是相應的Gabor特徵向量,大小爲4400*N. 
如果我們將艦船label設置爲0,飛機設置爲1,則SVM會輸出兩個值1或者0. 
(3)實際效果 
我的數據集是艦船圖片514張,飛機320張,測試集合總共50張,可以做到86%左右的成功率(對了43張),效果還是可以的

PS:我的整個代碼已經上傳CSDN,可以點擊這裏下載

參考: 
[1]Gabor濾波 
[2]SVM簡介 
[3]SVM


發佈了85 篇原創文章 · 獲贊 519 · 訪問量 183萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章