libsvm简单代码解释

  1. 首先来看一下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进行投票进行选择,看属于哪个类。
  2. /** 
  3.  * Libsvm的模型训练函数 
  4.  * @param prob 输入的问题 
  5.  * @param param 输入的参数 
  6.  * @return 训练好的模型 
  7.  */  
  8. public static svm_model svm_train(svm_problem prob, svm_parameter param)  
  9. {  
  10.     /**为了代码的简洁性,此处删除了部分**/  
  11.       
  12.     /** 
  13.      * 此处省略了部分代码:这里的代码主要做: 
  14.      * 1、统计类别总数,同时记录类别的标号,统计每个类的样本数目 
  15.      * 2、计算权重C 
  16.      * 3、初始化nozero数组,便于统计SV 
  17.      * 4、初始化概率数组 
  18.     */  
  19.     svm_model model = new svm_model();  
  20. //  获取先关参数比如惩罚值
  21.     model.param = param;  
  22.   
  23.     // 将属于同一个类别的数据组织起来  
  24.     svm_group_classes(prob,tmp_nr_class,tmp_label,tmp_start,tmp_count,perm);  
  25.       
  26.     //采用one-against-one进行分类  
  27.     int p = 0;  
  28.     //定义决策函数数组,将每一个而分类存储起来得到决策函数
  29.     decision_function[] f = new decision_function[nr_class*(nr_class-1)/2];  
  30.     for(i=0;i<nr_class;i++)  
  31.         for(int j=i+1;j<nr_class;j++)  
  32. //重新定义每个决策的svm_problem,主要用于重新训练一个新的决策函数,共有类数*(类数-1)/2
  33.             svm_problem sub_prob = new svm_problem();  
  34.       
  35.     //计算第i个类与第j个类的起始位置与数目。由于每个类都是存储在一起的,所有要获取每个类的起始地址,再根据每个类有多少样本,才能从样本节点中获取值  
  36.             int si = start[i], sj = start[j];  
  37.             int ci = count[i], cj = count[j];  
  38.             sub_prob.l = ci+cj;  得到2个类的样本数
  39.     //将第i个类的标签定义为+1,第j个类的标签定义为-1  
  40.             for(k=0;k<ci;k++)  
  41.             {  
  42.                 sub_prob.x[k] = x[si+k];  
  43.                 sub_prob.y[k] = +1;  
  44.             }  
  45.             for(k=0;k<cj;k++)  
  46.             {  
  47.                 sub_prob.x[ci+k] = x[sj+k];  
  48.                 sub_prob.y[ci+k] = -1;  
  49.             }  
  50.     //对第i个类与第j个类采用二分类策略,训练模型,根据新的sub_prob进行训练  
  51.             f[p] = svm_train_one(sub_prob,param,weighted_C[i],weighted_C[j]);  
  52.             ++p;  
  53.         }  
  54.     /** 
  55.      * 此处省略了部分代码:这里的代码主要做: 
  56.      * 1、统计一下nozero,如果nozero已经是真,就不变,如果为假,则改为真 
  57.      * 2、输出模型,主要是填充svm_model 
  58.     */  
  59.     return model;  

  60. 然后再来看一下其模型预测部分:
    1. /** 
    2.  * Libsvm模型预测部分,预测该样本的类标签以及属于该类的分值。 
    3.  * 这里采用的方法为投票策略 
    4.  * @param model 已训练好的Libsvm模型 
    5.  * @param x 一个待预测的样本向量 
    6.  * @param dec_values 保存预测结果的向量,其维度为k*(k-1)/2 
    7.  * @return 
    8.  */  
    9. public static double svm_predict_values(svm_model model, svm_node[] x, double[] dec_values)  
    10. {  
    11.       
    12.     //对一些变量进行初始化  
    13.     int i;  
    14.     int nr_class = model.nr_class;  //总的类数
    15.     int l = model.l;  //支持向量总个数
    16.   
    17.     double[] kvalue = new double[l];  //每个类别的支持向量存储在一起
    18.     //根据模型中的支持向量以及内核函数计算数值  
    19.     for(i=0;i<l;i++)  
    20.         kvalue[i] = Kernel.k_function(x,model.SV[i],model.param);  //进来的测试样本与每个支持向量进行内积
    21.   
    22.     int[] start = new int[nr_class];  
    23.     start[0] = 0;  
    24.     for(i=1;i<nr_class;i++)  
    25.         start[i] = start[i-1]+model.nSV[i-1];  //得到每个类别的起始地址,有利于方便获取相应类别的核函数的值
    26.       
    27.     //初始化vote向量  
    28.     int[] vote = new int[nr_class];  
    29.     for(i=0;i<nr_class;i++)  
    30.         vote[i] = 0;  //每个类的投票为0
    31.   
    32.     //依次计算k*(k-1)/2个二分类模型的预测值  
    33.     int p=0;  
    34.     for(i=0;i<nr_class;i++)  
    35.         for(int j=i+1;j<nr_class;j++)  
    36.         {  
    37.             double sum = 0;  
    38.             int si = start[i];  
    39.             int sj = start[j];  
    40.             int ci = model.nSV[i];  //得到每个类的支持向量个数,方便得到每个类别的核函数的值
    41.             int cj = model.nSV[j];  
    42.           
    43.         //根据决策函数计算每一个二分类对样本预测的分值  
    44.             int k;  
    45.             double[] coef1 = model.sv_coef[j-1];  
    46.             double[] coef2 = model.sv_coef[i];  
    47.             for(k=0;k<ci;k++)  
    48.                 sum += coef1[si+k] * kvalue[si+k];  
    49.             for(k=0;k<cj;k++)  
    50.                 sum += coef2[sj+k] * kvalue[sj+k];  
    51.             sum -= model.rho[p];//b  
    52.             //dec_values存储的就是第p个二分类模型对样本的预测值  
    53.             dec_values[p] = sum;     //最后的预测值                 
    54.   
    55.         //根据dec_values  值的正负决定给那个类别投票  
    56.             if(dec_values[p] > 0)  
    57.                 ++vote[i];  
    58.             else  
    59.                 ++vote[j];  
    60.             p++;  
    61.         }  
    62.       
    63.     //遍历vote向量,找出具有最大投票数的所对应类别即为所预测的类标签。  
    64.     //而dec_values则存储了k*(k-1)/2个二分类模型的预测值  
    65.     int vote_max_idx = 0;  
    66.     for(i=1;i<nr_class;i++)  
    67.         if(vote[i] > vote[vote_max_idx])  
    68.             vote_max_idx = i;  
    69.   
    70.     return model.label[vote_max_idx];  //得到投票最多的类别,就是要分到的类别。
    71.   
    72. }  
     




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值