小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

SVM算法實現(xiàn)(一)

 閑來看看 2013-10-11

SVM算法實現(xiàn)(一)

 

關(guān)鍵字(keywords):SVM 支持向量機 SMO算法 實現(xiàn) 機器學(xué)習(xí)    

 

      如果對SVM原理不是很懂的,可以先看一下入門的視頻,對幫助理解很有用的,然后再深入一點可以看看這幾篇入門文章,作者寫得挺詳細,看完以后SVM的基礎(chǔ)就了解得差不多了,再然后買本《支持向量機導(dǎo)論》作者是Nello Cristianini 和 John Shawe-Taylor,電子工業(yè)出版社的。然后把書本后面的那個SMO算法實現(xiàn)就基本上弄懂了SVM是怎么一回事,最后再編寫一個SVM庫出來,比如說像libsvm等工具使用,呵呵,差不多就這樣。這些是我學(xué)習(xí)SVM的整個過程,也算是經(jīng)驗吧。

      下面是SVM的簡化版SMO算法,我將結(jié)合Java代碼來解釋一下整個SVM的學(xué)習(xí)訓(xùn)練過程,即所謂的train訓(xùn)練過程。那么什么是SMO算法呢?

 SMO算法的目的無非是找出一個函數(shù)f(x),這個函數(shù)能讓我們把輸入的數(shù)據(jù)x進行分類。既然是分類肯定需要一個評判的標(biāo)準,比如分出來有兩種情況A和B,那么怎么樣才能說x是屬于A類的,或不是B類的呢?就是需要有個邊界,就好像兩個國家一樣有邊界,如果邊界越明顯,則就越容易區(qū)分,因此,我們的目標(biāo)是最大化邊界的寬度,使得非常容易的區(qū)分是A類還是B類。

 在SVM中,要最大化邊界則需要最小化這個數(shù)值:

 

 

w:是參量,值越大邊界越明顯
C代表懲罰系數(shù),即如果某個x是屬于某一類,但是它偏離了該類,跑到邊界上后者其他類的地方去了,C越大表明越不想放棄這個點,邊界就會縮小
代表:松散變量
但問題似乎還不好解,又因為SVM是一個凸二次規(guī)劃問題,凸二次規(guī)劃問題有最優(yōu)解,于是問題轉(zhuǎn)換成下列形式(KKT條件):

 …………(1)

這里的ai是拉格朗日乘子(問題通過拉格朗日乘法數(shù)來求解)
對于(a)的情況,表明ai是正常分類,在邊界內(nèi)部(我們知道正確分類的點yi*f(xi)>=0)
對于(b)的情況,表明了ai是支持向量,在邊界上
對于(c)的情況,表明了ai是在兩條邊界之間
而最優(yōu)解需要滿足KKT條件,即滿足(a)(b)(c)條件都滿足
以下幾種情況出現(xiàn)將會出現(xiàn)不滿足:

yiui<=1但是ai<C則是不滿足的,而原本ai=C
yiui>=1但是ai>0則是不滿足的而原本ai=0
yiui=1但是ai=0或者ai=C則表明不滿足的,而原本應(yīng)該是0<ai<C
所以要找出不滿足KKT的這些ai,并更新這些ai,但這些ai又受到另外一個約束,即

 

 

因此,我們通過另一個方法,即同時更新ai和aj,滿足以下等式

 

就能保證和為0的約束。

 

利用yiai+yjaj=常數(shù),消去ai,可得到一個關(guān)于單變量aj的一個凸二次規(guī)劃問題,不考慮其約束0<=aj<=C,可以得其解為:

 

 ………………………………………(2)

這里………………(3)

表示舊值,然后考慮約束0<=aj<=C可得到a的解析解為:

…………(4)

對于

那么如何求得ai和aj呢?

對于ai,即第一個乘子,可以通過剛剛說的那幾種不滿足KKT的條件來找,第二個乘子aj可以找滿足條件 

 

…………………………………………………………………………(5)

b的更新:

在滿足條件:下更新b?!?)

 

最后更新所有ai,y和b,這樣模型就出來了,然后通過函數(shù):

 ……………………………………………………(7)

輸入是x,是一個數(shù)組,組中每一個值表示一個特征。

輸出是A類還是B類。(正類還是負類)

 

以下是主要的代碼段:

 

  1. /* 
  2.  * 默認輸入?yún)?shù)值 
  3.  * C: regularization parameter 
  4.  * tol: numerical tolerance 
  5.  * max passes 
  6.  */  
  7. double C = 1//對不在界內(nèi)的懲罰因子  
  8. double tol = 0.01;//容忍極限值  
  9. int maxPasses = 5//表示沒有改變拉格朗日乘子的最多迭代次數(shù)  
  10.   
  11. /* 
  12.  * 初始化a[], b, passes  
  13.  */  
  14.   
  15. double a[] = new double[x.length];//拉格朗日乘子  
  16. this.a = a;  
  17.   
  18. //將乘子初始化為0  
  19. for (int i = 0; i < x.length; i++) {  
  20.     a[i] = 0;  
  21. }  
  22. int passes = 0;  
  23.   
  24.   
  25. while (passes < maxPasses) {  
  26.     //表示改變乘子的次數(shù)(基本上是成對改變的)  
  27.     int num_changed_alphas = 0;  
  28.     for (int i = 0; i < x.length; i++) {  
  29.         //表示特定階段由a和b所決定的輸出與真實yi的誤差  
  30.         //參照公式(7)  
  31.         double Ei = getE(i);  
  32.         /* 
  33.          * 把違背KKT條件的ai作為第一個 
  34.          * 滿足KKT條件的情況是: 
  35.          * yi*f(i) >= 1 and alpha == 0 (正確分類) 
  36.          * yi*f(i) == 1 and 0<alpha < C (在邊界上的支持向量) 
  37.          * yi*f(i) <= 1 and alpha == C (在邊界之間) 
  38.          *  
  39.          *  
  40.          *  
  41.          * ri = y[i] * Ei = y[i] * f(i) - y[i]^2 >= 0 
  42.          * 如果ri < 0并且alpha < C 則違反了KKT條件 
  43.          * 因為原本ri < 0 應(yīng)該對應(yīng)的是alpha = C 
  44.          * 同理,ri > 0并且alpha > 0則違反了KKT條件 
  45.          * 因為原本ri > 0對應(yīng)的應(yīng)該是alpha =0 
  46.          */  
  47.         if ((y[i] * Ei < -tol && a[i] < C) ||  
  48.             (y[i] * Ei > tol && a[i] > 0))   
  49.         {  
  50.             /* 
  51.              * ui*yi=1邊界上的點 0 < a[i] < C 
  52.              * 找MAX|E1 - E2| 
  53.              */  
  54.             int j;  
  55.             /* 
  56.              * boundAlpha表示x點處于邊界上所對應(yīng)的 
  57.              * 拉格朗日乘子a的集合 
  58.              */  
  59.             if (this.boundAlpha.size() > 0) {  
  60.                 //參照公式(5)  
  61.                 j = findMax(Ei, this.boundAlpha);  
  62.             } else   
  63.                 //如果邊界上沒有,就隨便選一個j != i的aj  
  64.                 j = RandomSelect(i);  
  65.               
  66.             double Ej = getE(j);  
  67.               
  68.             //保存當(dāng)前的ai和aj  
  69.             double oldAi = a[i];  
  70.             double oldAj = a[j];  
  71.               
  72.             /* 
  73.              * 計算乘子的范圍U, V 
  74.              * 參考公式(4) 
  75.              */  
  76.             double L, H;  
  77.             if (y[i] != y[j]) {  
  78.                 L = Math.max(0, a[j] - a[i]);  
  79.                 H = Math.min(C, C - a[i] + a[j]);  
  80.             } else {  
  81.                 L = Math.max(0, a[i] + a[j] - C);  
  82.                 H = Math.min(0, a[i] + a[j]);  
  83.             }  
  84.               
  85.               
  86.             /* 
  87.              * 如果eta等于0或者大于0 則表明a最優(yōu)值應(yīng)該在L或者U上 
  88.              */  
  89.             double eta = 2 * k(i, j) - k(i, i) - k(j, j);//公式(3)  
  90.               
  91.             if (eta >= 0)  
  92.                 continue;  
  93.               
  94.             a[j] = a[j] - y[j] * (Ei - Ej)/ eta;//公式(2)  
  95.             if (0 < a[j] && a[j] < C)  
  96.                 this.boundAlpha.add(j);  
  97.               
  98.             if (a[j] < L)   
  99.                 a[j] = L;  
  100.             else if (a[j] > H)   
  101.                 a[j] = H;  
  102.               
  103.             if (Math.abs(a[j] - oldAj) < 1e-5)  
  104.                 continue;  
  105.             a[i] = a[i] + y[i] * y[j] * (oldAj - a[j]);  
  106.             if (0 < a[i] && a[i] < C)  
  107.                 this.boundAlpha.add(i);  
  108.               
  109.             /* 
  110.              * 計算b1, b2 
  111.              * 參照公式(6) 
  112.              */  
  113.             double b1 = b - Ei - y[i] * (a[i] - oldAi) * k(i, i) - y[j] * (a[j] - oldAj) * k(i, j);  
  114.             double b2 = b - Ej - y[i] * (a[i] - oldAi) * k(i, j) - y[j] * (a[j] - oldAj) * k(j, j);  
  115.               
  116.             if (0 < a[i] && a[i] < C)  
  117.                 b = b1;  
  118.             else if (0 < a[j] && a[j] < C)  
  119.                 b = b2;  
  120.             else   
  121.                 b = (b1 + b2) / 2;  
  122.               
  123.             num_changed_alphas = num_changed_alphas + 1;  
  124.         }  
  125.     }  
  126.     if (num_changed_alphas == 0) {  
  127.         passes++;  
  128.     } else   
  129.         passes = 0;  
  130. }  
  131.   
  132. return new SVMModel(a, y, b);  

運行后的結(jié)果還算可以吧,測試數(shù)據(jù)主要是用了libsvm的heart_scale的數(shù)據(jù)。

預(yù)測的正確率達到73%以上。

如果我把核函數(shù)從線性的改為基于RBF將會更好點。

最后,說到SVM算法實現(xiàn)包,應(yīng)該有很多,包括svm light,libsvm,有matlab本身自帶的svm工具包等。

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多