<label id="jgr5k"></label>
    <legend id="jgr5k"><track id="jgr5k"></track></legend>

    <sub id="jgr5k"></sub>
  1. <u id="jgr5k"></u>
      久草国产视频,91资源总站,在线免费看AV,丁香婷婷社区,久久精品99久久久久久久久,色天使av,无码探花,香蕉av在线
      您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產品體驗,強烈建議使用更快更安全的瀏覽器
      此為臨時鏈接,僅用于文章預覽,將在時失效
      人工智能開發(fā)者 正文
      發(fā)私信給AI研習社
      發(fā)送

      0

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      本文作者: AI研習社 2017-05-14 14:34
      導語:SVM 算法實現(xiàn)指南。

      雷鋒網(wǎng)按:本文作者謝輝,原文載于作者個人博客,雷鋒網(wǎng)已獲授權。

      支持向量機SVM(Support Vector Machine)是一種有監(jiān)督的學習模型,它的核心有兩個:一、核函數(shù)(kernel trick);二、序列最小優(yōu)化算法SMO(Sequential minimal optimization)是John Platt在1996年發(fā)布的用于訓練SVM的有效算法。本文不打算細化SVM支持向量機的詳細推倒算法,只涉及以上兩點的內容做一個說明,最后給出算法實現(xiàn)和一個實驗對比圖。

        核函數(shù)

      核函數(shù)在處理復雜數(shù)據(jù)時效果顯著,它的做法是將某一個維度的線性不可分數(shù)據(jù)采取核函數(shù)進行特征空間的隱式映射到高維空間,從而在高維空間將數(shù)據(jù)轉化為線性可分,最后回歸到原始維度空間實施分類的過程,常見的幾個核函數(shù)如下:

      多項式核:

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      高斯核(徑向基函數(shù)):

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      線性核:

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      即是兩個矩陣空間的內積。

        SMO算法流程

      SMO的主要兩個步驟就是:

      1、選擇需要更新的一對α,采取啟發(fā)式的方式進行選擇,以使目標函數(shù)最大程度的接近其全局最優(yōu)值;

      2、將目標函數(shù)對α進行優(yōu)化,以保持其它所有α不變。

      以上是兩個基本步驟,實現(xiàn)具體推到公式如下:

      所需要收到的約束條件為:

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      同時更新α,要求滿足如下條件,就可以保證為0的約束

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      消去α可得

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      其中

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      u 的表達式為:

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      y為第i個特征因素的真實標簽值

      之后考慮約束條件 0<α<c 則

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      約束條件的線性表示

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      依據(jù) y 同號或是異號,可得出上下兩個邊界為

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      對于α有

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      對于α首先可以通過E求得j,之后計算方式可為:

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      而b的更新為

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      其中

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      每次更新完和都需要重新計算b以及對應的和

      有了以上的公式,代碼實現(xiàn)就比較簡單了。

        算法實現(xiàn)

      完整的Platt-smo算法實現(xiàn)入口:

      public SvmResult plattSmo(final SvmResult svmResult) {

      double b = svmResult.getB();

      double[] alphas = svmResult.getAlphas();


      for(int i=0;i<featuresArray.length;i++){

      double ei = this.calcEk(i, alphas, b);

      if (((lablesArray[i] * ei < -tolerFactor)

      && (alphas[i] < penaltyFactor))

      || ((lablesArray[i] * ei > tolerFactor) && (alphas[i] > 0))) {

      double[] jSelected = this.selectJ(i, ei, alphas, b); //啟發(fā)式實現(xiàn)j的選擇

      int j = (int) jSelected[0]; 

      double ej = jSelected[1];

      double alphaIold = alphas[i];

      double alphaJold = alphas[j];

      double L = 0;

      double H = 0;

      //邊界計算

      if (lablesArray[i] != lablesArray[j]) {

      L = Math.max(0, alphas[j] - alphas[i]);

      H = Math.min(penaltyFactor, penaltyFactor + alphas[j]

      - alphas[i]);

      } else {

      L = Math.max(0, alphas[j] + alphas[i] - penaltyFactor);

      H = Math.min(penaltyFactor, alphas[j] + alphas[i]);

      }

      if (L == H) {

      logger.info("L==H");

      } else {

      double eta = (2.0 * this.kernelArray[i][j] - this.kernelArray[i][i] - this.kernelArray[j][j]);

      if (eta >= 0) {

      logger.info("eta>=0");

      } else {

      //雙向調整alphas[j]遞減

      alphas[j] -= lablesArray[j] * (ei - ej) / eta;

      if (alphas[j] > H) {

      alphas[j] = H;

      }

      if (L > alphas[j]) {

      alphas[j] = L;

      }

      //更新ej

      this.updateEk(j, alphas, b);

      if (Math.abs(alphas[j] - alphaJold) < 0.00001) {

      logger.info("j not moving enough");

      } else {

      //雙向調整alphas[i]遞減

      alphas[i] += lablesArray[j] * lablesArray[i]

      * (alphaJold - alphas[j]);

      //更新ei

      this.updateEk(i, alphas, b);

      //計算b

      double b1 = b - ei- lablesArray[i]*(alphas[i]-alphaIold)*this.kernelArray[i][i] - lablesArray[j]*(alphas[j]-alphaJold)*this.kernelArray[i][j];

      double b2 = b - ej- lablesArray[i]*(alphas[i]-alphaIold)*this.kernelArray[i][j] - lablesArray[j]*(alphas[j]-alphaJold)*this.kernelArray[j][j];

      if ((0 < alphas[i]) && (penaltyFactor > alphas[i])){

      b = b1;

      }else if ((0 < alphas[j]) && (penaltyFactor > alphas[j])){

      b = b2;

      }else{

      b = (b1 + b2)/2.0;

      }


      }

      }

      }

      }

      }

      return new SvmResult(b, alphas);

      }

      在以上算法里面重點關注是j的選擇,

      J的選擇:

      private double[] selectJ(int i,double ei,double[] alphas,double b){

      int maxK = -1; 

      double maxDeltaE = 0; 

      double ej = 0;

      int j = -1;

      double[] eiArray= new double[2];

      eiArray[0] = 1d;

      eiArray[1] = ei;

      this.eCache[i] = eiArray;

      boolean hasValidEcacheList = false;

      for(int k=0;k<this.eCache.length;k++){

      if(this.eCache[k][0] > 0){

      if(k == i){

      continue;

      }

      hasValidEcacheList = true;

      if(k == this.m){

      k = m-1;

      }

      double ek = this.calcEk(k, alphas, b);

      double deltaE = Math.abs(ei - ek);

      if (deltaE > maxDeltaE){

                     maxK = k; 

                     maxDeltaE = deltaE; 

                     ej = ek;

      }

      }

      }

      j = maxK;

      if(!hasValidEcacheList || j == -1){

      j = this.selectJRandom(i);

      ej = this.calcEk(j, alphas, b); 

      }

      if(j == this.m){

      j = m-1;

      }

      return new double[]{j,ej};

      }

      首選采取啟發(fā)式選擇j,通過計算deltaE的最大值來逼近j的選擇,如果選擇不到就隨機選擇一個j值,在j選擇里面有一個Ek的計算方式

      private double calcEk(int k,double[] alphas,double b){

      Matrix alphasMatrix = new Matrix(alphas);

      Matrix lablesMatrix = new Matrix(lablesArray);

      Matrix kMatrix = new Matrix(this.kernelArray[k]);

      double fXk = alphasMatrix.multiply(lablesMatrix).dotMultiply(kMatrix.transpose()).dotValue() + b;

      double ek = fXk - (float)this.lablesArray[k];

      return ek;

      }

      下面再介紹一下核函數(shù)計算方式,本文主要采取徑向基函數(shù)(RBF)實現(xiàn),如下:

      public double[] kernelTrans(double[][] featuresArray,double[] featuresIArray){

      int mCount = featuresArray.length;

      double[] kernelTransI = new double[mCount];

      Matrix featuresMatrix = new Matrix(featuresArray);

      Matrix featuresIMatrix = new Matrix(featuresIArray);

      if(trainFactorMap.get("KT").equals("lin")){

      Matrix result = featuresMatrix.dotMultiply(featuresIMatrix.transpose());

      kernelTransI = result.transpose().values()[0];

      }else if(trainFactorMap.get("KT").equals("rbf")){

      double rbfDelta = (double)trainFactorMap.get("rbfDelta");

      for(int j=0;j<mCount;j++){

      Matrix xj = new Matrix(featuresArray[j]);

      Matrix delta = xj.reduce(featuresIMatrix);

      double deltaValue = delta.dotMultiply(delta.transpose()).dotValue();

      kernelTransI[j] = Math.exp((-1.0*deltaValue)/(2*Math.pow(rbfDelta, 2)));

      }

      }

      return kernelTransI;

      }

      最后看下測試代碼實現(xiàn):

      double[][] datasvs = new double[m][d[0].length];

      double[] labelsvs = new double[m];

      double[] alphassvs = new double[m];

      int n = 0;

      for(int i=0;i<alphas.length;i++){

      if(alphas[i] != 0){

      datasvs[n] = d[i];

      labelsvs[n] = l[i];

      alphassvs[n] = alphas[i];

      n++;

      }

      }


      //model test

      int errorCount = 0;

      for(int i=0;i<d.length;i++){

      double[] kernelTransI = learner.kernelTrans(datasvs, d[i]);

      Matrix kernelTransIM = new Matrix(kernelTransI);

      Matrix labelsvsM = new Matrix(labelsvs);

      Matrix alphassvsM = new Matrix(alphassvs);

      double predict = kernelTransIM.dotMultiply(labelsvsM.multiply(alphassvsM).transpose()).dotValue() + b;

      System.out.println(i+"\t"+predict+"\t"+l[i]);

      if(AdaBoost.sigmoid(predict) != l[i]){

      errorCount++;

      }

      }

      測試代碼是首先找出所有的支持向量,并提取支持向量下的特征向量和標簽向量,采取核函數(shù)進行隱式映射,最后計算預測值。

        訓練結果


      本文采取100個二維平面無法線性可分的數(shù)據(jù)集合,如下:

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      通過徑向基函數(shù)映射后采取支持向量預測計算得到的可分平面如下

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      本算法100個數(shù)據(jù)訓練準確率可達98%。

      注:本文算法均來自Peter Harrington的《Machine Learning in action》

      ———————————————————————————————————————

      人工智能之神經網(wǎng)絡特訓班

      20年清華大學神經網(wǎng)絡授課導師,帶你系統(tǒng)學習人工智能之神經網(wǎng)絡!

      一站式深入了解深度學習的發(fā)展現(xiàn)狀、基本原理和主要方法。

      課程鏈接:http://www.mooc.ai/course/65 

      雷鋒網(wǎng)(公眾號:雷鋒網(wǎng))相關閱讀:

      從理論到實踐,一文詳解 AI 推薦系統(tǒng)的三大算法

      監(jiān)督學習最常見的五種算法,你知道幾個?

      雷峰網(wǎng)版權文章,未經授權禁止轉載。詳情見轉載須知

      基于Spark如何實現(xiàn)SVM算法?這里有一份詳盡的開發(fā)教程(含代碼)

      分享:
      相關文章

      編輯

      聚焦數(shù)據(jù)科學,連接 AI 開發(fā)者。更多精彩內容,請訪問:yanxishe.com
      當月熱門文章
      最新文章
      請?zhí)顚懮暾埲速Y料
      姓名
      電話
      郵箱
      微信號
      作品鏈接
      個人簡介
      為了您的賬戶安全,請驗證郵箱
      您的郵箱還未驗證,完成可獲20積分喲!
      請驗證您的郵箱
      立即驗證
      完善賬號信息
      您的賬號已經綁定,現(xiàn)在您可以設置密碼以方便用郵箱登錄
      立即設置 以后再說
      主站蜘蛛池模板: 国产极品粉嫩福利姬萌白酱| 2020亚洲男人天堂| 国产成人a∨激情视频厨房| 久久精品国产77777蜜臀| 镇远县| 制服丝袜人妻中出第一页| 日韩精品亚洲 国产| 午夜成人无码福利免费视频| 国产精品第一区亚洲精品| 成人AV一区二区三区| 久久国产精品萌白酱免费| 欧美日韩精品一区二区在线观看 | 亚洲最大无码中文字幕网站| 丁香五月缴情在线| 18禁裸乳无遮挡啪啪无码免费| 乱码午夜-极国产极内射| 五月丁香六月综合缴情在线 | 狠狠色综合久久狠狠色综合| 欧美性极品| 51国精产品自偷自偷综合| 日韩综合| 国产中年熟女大集合| 亚洲中文字幕av无码区| 亚洲无码资源| 久久av高潮av无码av喷吹| 中文字幕在线精品视频入口一区| 人妻少妇久久久久久97人妻| 日日机机天天干| 无码精品人妻一区二区三区人妻斩| 99这里有精品视频| 香蕉久久精品日日躁夜夜躁夏 | 国产无遮挡裸体免费视频在线观看| 久久久久久人妻精品一区| 亚洲区综合区小说区激情区| 精品av| 山西省| 色网站免费在线观看| 国产精品国产高清国产av| 天天摸天天做天天爽| 欧洲码亚洲码的区别入口| 大色欧美|