您的位置:首页 > 编程语言

libsvm简单代码解释

2015-07-12 21:59 274 查看
首先来看一下Libsvm的模型训练部分:采用为One-against-one的策略假如有1,2,3,4个类可以(1,2)(1,3)(1,4)(2,3)(2,4)(2,4)可以得到n(n-1)/2个决策函数,当进来一个样本采用对1,2,3,4进行投票进行选择,看属于哪个类。

/** 

 * Libsvm的模型训练函数 

 * @param prob 输入的问题 

 * @param param 输入的参数 

 * @return 训练好的模型 

 */  

public static svm_model svm_train(svm_problem prob, svm_parameter param)  

{  

    /**为了代码的简洁性,此处删除了部分**/  

      

    /** 

     * 此处省略了部分代码:这里的代码主要做: 

     * 1、统计类别总数,同时记录类别的标号,统计每个类的样本数目 

     * 2、计算权重C 

     * 3、初始化nozero数组,便于统计SV 

     * 4、初始化概率数组 

    */  

    svm_model model = new svm_model();  

//  获取先关参数比如惩罚值

    model.param = param;  

  

    // 将属于同一个类别的数据组织起来  

    svm_group_classes(prob,tmp_nr_class,tmp_label,tmp_start,tmp_count,perm);  

      

    //采用one-against-one进行分类  

    int p = 0;  

    //定义决策函数数组,将每一个而分类存储起来得到决策函数

    decision_function[] f = new decision_function[nr_class*(nr_class-1)/2];  

    for(i=0;i<nr_class;i++)  

        for(int j=i+1;j<nr_class;j++)  

//重新定义每个决策的svm_problem,主要用于重新训练一个新的决策函数,共有类数*(类数-1)/2

            svm_problem sub_prob = new svm_problem();  

      

    //计算第i个类与第j个类的起始位置与数目。由于每个类都是存储在一起的,所有要获取每个类的起始地址,再根据每个类有多少样本,才能从样本节点中获取值  

            int si = start[i], sj = start[j];  

            int ci = count[i], cj = count[j];  

            sub_prob.l = ci+cj;  得到2个类的样本数

    //将第i个类的标签定义为+1,第j个类的标签定义为-1  

            for(k=0;k<ci;k++)  

            {  

                sub_prob.x[k] = x[si+k];  

                sub_prob.y[k] = +1;  

            }  

            for(k=0;k<cj;k++)  

            {  

                sub_prob.x[ci+k] = x[sj+k];  

                sub_prob.y[ci+k] = -1;  

            }  

    //对第i个类与第j个类采用二分类策略,训练模型,根据新的sub_prob进行训练  

            f[p] = svm_train_one(sub_prob,param,weighted_C[i],weighted_C[j]);  

            ++p;  

        }  

    /** 

     * 此处省略了部分代码:这里的代码主要做: 

     * 1、统计一下nozero,如果nozero已经是真,就不变,如果为假,则改为真 

     * 2、输出模型,主要是填充svm_model 

    */  

    return model;  



然后再来看一下其模型预测部分:

/** 

 * Libsvm模型预测部分,预测该样本的类标签以及属于该类的分值。 

 * 这里采用的方法为投票策略 

 * @param model 已训练好的Libsvm模型 

 * @param x 一个待预测的样本向量 

 * @param dec_values 保存预测结果的向量,其维度为k*(k-1)/2 

 * @return 

 */  

public static double svm_predict_values(svm_model model, svm_node[] x, double[] dec_values)  

{  

      

    //对一些变量进行初始化  

    int i;  

    int nr_class = model.nr_class;
 //总的类数

    int l = model.l;
 //支持向量总个数

  

    double[] kvalue = new double[l];
 //每个类别的支持向量存储在一起

    //根据模型中的支持向量以及内核函数计算数值  

    for(i=0;i<l;i++)  

        kvalue[i] = Kernel.k_function(x,model.SV[i],model.param);  //进来的测试样本与每个支持向量进行内积

  

    int[] start = new int[nr_class];  

    start[0] = 0;  

    for(i=1;i<nr_class;i++)  

        start[i] = start[i-1]+model.nSV[i-1];
 //得到每个类别的起始地址,有利于方便获取相应类别的核函数的值

      

    //初始化vote向量  

    int[] vote = new int[nr_class];  

    for(i=0;i<nr_class;i++)  

        vote[i] = 0;
 //每个类的投票为0

  

    //依次计算k*(k-1)/2个二分类模型的预测值  

    int p=0;  

    for(i=0;i<nr_class;i++)  

        for(int j=i+1;j<nr_class;j++)  

        {  

            double sum = 0;  

            int si = start[i];  

            int sj = start[j];  

            int ci = model.nSV[i];
 //得到每个类的支持向量个数,方便得到每个类别的核函数的值

            int cj = model.nSV[j];  

          

        //根据决策函数计算每一个二分类对样本预测的分值  

            int k;  

            double[] coef1 = model.sv_coef[j-1];  

            double[] coef2 = model.sv_coef[i];  

            for(k=0;k<ci;k++)  

                sum += coef1[si+k] * kvalue[si+k];  

            for(k=0;k<cj;k++)  

                sum += coef2[sj+k] * kvalue[sj+k];  

            sum -= model.rho[p];//b  

            //dec_values存储的就是第p个二分类模型对样本的预测值  

            dec_values[p] = sum;     //最后的预测值                 

  

        //根据dec_values  值的正负决定给那个类别投票  

            if(dec_values[p] > 0)  

                ++vote[i];  

            else  

                ++vote[j];  

            p++;  

        }  

      

    //遍历vote向量,找出具有最大投票数的所对应类别即为所预测的类标签。  

    //而dec_values则存储了k*(k-1)/2个二分类模型的预测值  

    int vote_max_idx = 0;  

    for(i=1;i<nr_class;i++)  

        if(vote[i] > vote[vote_max_idx])  

            vote_max_idx = i;  

  

    return model.label[vote_max_idx];
 //得到投票最多的类别,就是要分到的类别。

  

}  

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: