1. 程式人生 > >機器學習-支持向量機算法實現與實例程序

機器學習-支持向量機算法實現與實例程序

training mage 線性 opts 線性可分 tps gist 填充 rain

一. SMO算法基礎

支持向量就是離分隔超平面最近的那些點。分隔超平面是將數據集分開來的決策邊界。

支持向量機將向量映射到一個更高維的空間裏,在這個空間裏建立有一個最大間隔超平面。在分開數據的超平面的兩邊建有兩個互相平行的超平面。建立方向合適的分隔超平面使兩個與之平行的超平面間的距離最大化。其假定為,平行超平面間的距離或差距越大,分類器的總誤差越小。

我們希望找到離分隔超平面最近的點,確保他們離分隔面的距離盡可能遠,誤差盡可能小。

與logistics不同的是支持向量機采用的類別標簽是-1和+1,因為-1和+1只相差一個符號,方便數學上的處理。

分隔超平面的形式可以寫成,一個點到到分隔超平面的的法線或垂線的長度為成,我們的目標是找出間隔最大化時的w和b,間隔通過來計算,即目標式可寫作:

技術分享圖片

其中||w||為二階範數,也就是各項目平方和的平方根:

技術分享圖片

但對乘積優化是特別麻煩的,所以我們可以將超平面寫成數據點的形式:

技術分享圖片

約束條件為:

技術分享圖片

可得w與b:

技術分享圖片

但是大部分情況下數據都不會是100%線性可分的,因此我們加入松弛變量,約束條件變為:

技術分享圖片

其中求解過程是比較復雜的,如果像我一樣接觸這類計算機語言不久,可以不用太糾結於算法的計算過程,清楚原理也可以讀懂程序。接下來就是完整SMO算法程序實現。

二.程序實現

先用testSet.txt中的數據簡單了解一下支持向量機算法。

技術分享圖片

部分testSet.txt中的數據

對於testSet.txt數據集,先輔助函數loadDataSet()函數打開文件並對其進行逐行解析,從而得到每行的類標簽和整個數據矩陣。selectJrand()中參數i是第一個alpha的下標,m是所有alpha的數目。clipAlpha()用於調整大於H或小於L的alpha值。

技術分享圖片

然後需要構建一個僅包含init方法的optStructure類來實現其成員變量的填充。calcEK()計算E值並返回。selectJ()用於選擇內循環的alpha值。cpdateEK()計算在對alpha值進行優化時會用到的誤差值。

技術分享圖片

技術分享圖片

再導入innerL()函數,使用它自己的數據結構在參數os中傳遞。smoP()函數創建一個數據結構來容納所有的數據,然後對控制函數退出的變量進行初始化。CalcWs()中的for循環遍歷數據集中的所有數據,舍棄支持向量之外的其他數據點。

技術分享圖片

技術分享圖片

技術分享圖片

最後,利用matplotlib畫出圖形。

技術分享圖片

技術分享圖片

三.手寫識別問題

數據:存放在trainingDigits和testDigits兩個文件夾中的手寫識別數據。

SMO算法程序與前面相同,接下來用img2vector()函數將32x32的二進制圖像轉換為1x1024向量及loadImages()函數加載圖片。

技術分享圖片

四.測試結果與方法

用testDigits()函數測試支持向量個數、訓練集錯誤率及測試集錯誤率。

技術分享圖片

經過4次叠代以後得到:

技術分享圖片

五.核函數

核函數是SMV的核心算法,對於原本線性不可分的樣本,可以通過將原始輸入空間映射到更高維度的特征空間這一操作使其在新的核空間內變為線性可分。僅需要調整核函數就可以將特征進行低維到高維的變換,在低維上進行計算,實質結果表現在高維上。

技術分享圖片

此圖來自https://blog.csdn.net/github_38325884/article/details/74418365

比較流行的一個核函數是徑向基核函數:

技術分享圖片

由於本人對核函數還不是很懂,這裏使用的數據集比較簡單,沒有使用核函數,就不再具體介紹了,想深入了解具體算法實現過程可參考http://www.cnblogs.com/jerrylead/archive/2011/03/18/1988406.html

六.總結

支持向量機具有良好的學習能力,結果有很好的推廣性。且完整算法在很大程度上提高了優化的速度。但對參數調節和核函數的選擇敏感,若要處理二分類以外的問題需要對原始分離器加以修改。適用於數值型和標稱型數據。

機器學習-支持向量機算法實現與實例程序