成人av在线资源一区,亚洲av日韩av一区,欧美丰满熟妇乱XXXXX图片,狠狠做五月深爱婷婷伊人,桔子av一区二区三区,四虎国产精品永久在线网址,国产尤物精品人妻在线,中文字幕av一区二区三区欲色
    您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產(chǎn)品體驗,強(qiáng)烈建議使用更快更安全的瀏覽器
    此為臨時鏈接,僅用于文章預(yù)覽,將在時失效
    人工智能開發(fā)者 正文
    發(fā)私信給AI研習(xí)社
    發(fā)送

    0

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

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

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

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

      核函數(shù)

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

    多項式核:

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

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

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

    線性核:

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

    即是兩個矩陣空間的內(nèi)積。

      SMO算法流程

    SMO的主要兩個步驟就是:

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

    2、將目標(biāo)函數(shù)對α進(jìn)行優(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 的表達(dá)式為:

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

    y為第i個特征因素的真實標(biāo)簽值

    之后考慮約束條件 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以及對應(yīng)的和

    有了以上的公式,代碼實現(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 {

    //雙向調(diào)整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 {

    //雙向調(diào)整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);

    }

    在以上算法里面重點關(guān)注是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值,在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++;

    }

    }

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

      訓(xùn)練結(jié)果


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

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

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

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

    本算法100個數(shù)據(jù)訓(xùn)練準(zhǔn)確率可達(dá)98%。

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

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

    人工智能之神經(jīng)網(wǎng)絡(luò)特訓(xùn)班

    20年清華大學(xué)神經(jīng)網(wǎng)絡(luò)授課導(dǎo)師,帶你系統(tǒng)學(xué)習(xí)人工智能之神經(jīng)網(wǎng)絡(luò)!

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

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

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

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

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

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

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

    分享:
    相關(guān)文章

    編輯

    聚焦數(shù)據(jù)科學(xué),連接 AI 開發(fā)者。更多精彩內(nèi)容,請訪問:yanxishe.com
    當(dāng)月熱門文章
    最新文章
    請?zhí)顚懮暾埲速Y料
    姓名
    電話
    郵箱
    微信號
    作品鏈接
    個人簡介
    為了您的賬戶安全,請驗證郵箱
    您的郵箱還未驗證,完成可獲20積分喲!
    請驗證您的郵箱
    立即驗證
    完善賬號信息
    您的賬號已經(jīng)綁定,現(xiàn)在您可以設(shè)置密碼以方便用郵箱登錄
    立即設(shè)置 以后再說