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];
//得到投票最多的类别,就是要分到的类别。
}
/**
* 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];
//得到投票最多的类别,就是要分到的类别。
}
相关文章推荐
- Python项目六: 使用CGI进行远程编辑
- Android studio 类似于eclipse 中的 Ctrl+1 快捷键(quick fixes available)
- Python图像处理(16):图像金字塔
- Spring 3 以后的注解介绍(转载)
- Python格式化字符串
- C++ typedef 与 define 浅析
- 深入Java单例模式
- python初学遇到的问题总结
- aws ec2基本环境安装lamp和vsftp
- java设计模式学习之单例模式
- Java--finally
- 求余运算易错点
- C语言学习笔记——文件
- 如何将Java项目代码打包成exe文件
- 重庆大三学生找java实习生之路
- Java 反射调用带基本数据类型参数的方法
- C# 建造者模式
- Java无符号16位整形数组转float
- Action Filters for ASP.NET MVC
- struts2 上传文件 parseRequest()解析request为空 解决办法