封装libsvm为C++类

项目需要做分类任务,没法直接使用libsvm库自带的train.exe和predict.exe,于是参考这里https://www.cnblogs.com/cv-pr/p/5646434.html一篇博文,封装libsvm为C++类。

在vs2012建立一个工程,把libsvm里的svm.h和svm.cpp导入你的项目中。

CxLibSVM.h

#ifndef _CXLIBSVM_H_H
#define _CXLIBSVM_H_H

#include <string>
#include <vector>
#include <iostream>
#include "svm.h"

using namespace std;

//内存分配
#define Malloc(type,n) (type *)malloc((n)*sizeof(type))

class CxLibSVM
{
public:

	struct svm_parameter    param;

private:

	struct svm_model*    model_;

	struct svm_problem        prob;

	struct svm_node *        x_space;

public:

	CxLibSVM();

	~CxLibSVM();

	void init_svm_param(struct svm_parameter& param);

	void train(const vector<vector<double>>&  x, const vector<double>& y, const struct svm_parameter& param);

	int predict(const vector<double>& x,double& prob_est);

	void do_cross_validation(const vector<vector<double>>&  x, const vector<double>& y, const struct svm_parameter& param, const int & nr_fold);

	int load_model(string model_path);

	int save_model(string model_path);

	void free_model();
};



#endif // !_CXLIBSVM_H_H

CxLibSVM.cpp

#include "stdafx.h"
#include "CxLibSVM.h"

CxLibSVM::CxLibSVM()
{
	model_ = NULL;
}

CxLibSVM::~CxLibSVM()
{
	 free_model();
}

void CxLibSVM::init_svm_param(struct svm_parameter& param)
{
	//参数初始化,参数调整部分在这里修改即可
	// 默认参数
	param.svm_type = C_SVC;        //算法类型
	param.kernel_type = LINEAR;    //核函数类型
	param.degree = 3;    //多项式核函数的参数degree
	param.coef0 = 0;    //多项式核函数的参数coef0
	param.gamma = 0.5;    //1/num_features,rbf核函数参数
	param.nu = 0.5;        //nu-svc的参数
	param.C = 10;        //正则项的惩罚系数
	param.eps = 1e-3;    //收敛精度
	param.cache_size = 100;    //求解的内存缓冲 100MB
	param.p = 0.1;
	param.shrinking = 1;
	param.probability = 1;    //1表示训练时生成概率模型,0表示训练时不生成概率模型,用于预测样本的所属类别的概率
	param.nr_weight = 0;    //类别权重
	param.weight = NULL;    //样本权重
	param.weight_label = NULL;    //类别权重
}

void CxLibSVM::train(const vector<vector<double>>& x, const vector<double>& y, const struct svm_parameter& param)
{
	if (x.size() == 0)
	{
		return;
	}

	//释放先前的模型
	free_model();

	/*初始化*/        
	long    len = x.size();
	long    dim = x[0].size();
	long    elements = len * dim;

	//转换数据为libsvm格式
	prob.l = len;
	prob.y = Malloc(double, prob.l);
	prob.x = Malloc(struct svm_node *, prob.l);
	x_space = Malloc(struct svm_node, elements + len);
	int j = 0;
	for (int l = 0; l < len; l++)
	{
		prob.x[l] = &x_space[j];
		for (int d = 0; d < dim; d++)
		{                
			x_space[j].index = d+1;
			x_space[j].value = x[l][d];    
			j++;
		}
		x_space[j++].index = -1;
		prob.y[l] = y[l];
	}

	/*训练*/
	model_ = svm_train(&prob, &param);    
}

int CxLibSVM::predict(const vector<double>& x,double& prob_est)
{
	//数据转换
	svm_node* x_test = Malloc(struct svm_node, x.size()+1);
	for (unsigned int i=0; i<x.size(); i++)
	{
		x_test[i].index = i + 1;
		x_test[i].value = x[i];
	}
	x_test[x.size()].index = -1;
	double *probs = new double[model_->nr_class];//存储了所有类别的概率
	//预测类别和概率
	int value = (int)svm_predict_probability(model_, x_test, probs);
	for (int k = 0; k < model_->nr_class;k++)
	{//查找类别相对应的概率
		if (model_->label[k] == value)
		{
			prob_est = probs[k];
			break;
		}
	}
	delete[] probs;
	return value;
}

void CxLibSVM::do_cross_validation(const vector<vector<double>>& x, const vector<double>& y, const struct svm_parameter& param, const int & nr_fold)
{
	if (x.size() == 0)return;

	/*初始化*/
	long    len = x.size();
	long    dim = x[0].size();
	long    elements = len*dim;

	//转换数据为libsvm格式
	prob.l = len;
	prob.y = Malloc(double, prob.l);
	prob.x = Malloc(struct svm_node *, prob.l);
	x_space = Malloc(struct svm_node, elements + len);
	int j = 0;
	for (int l = 0; l < len; l++)
	{
		prob.x[l] = &x_space[j];
		for (int d = 0; d < dim; d++)
		{
			x_space[j].index = d + 1;
			x_space[j].value = x[l][d];
			j++;
		}
		x_space[j++].index = -1;
		prob.y[l] = y[l];
	}

	int i;
	int total_correct = 0;
	double total_error = 0;
	double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
	double *target = Malloc(double, prob.l);

	svm_cross_validation(&prob, &param, nr_fold, target);
	if (param.svm_type == EPSILON_SVR ||
		param.svm_type == NU_SVR)
	{
		for (i = 0; i < prob.l; i++)
		{
			double y = prob.y[i];
			double v = target[i];
			total_error += (v - y)*(v - y);
			sumv += v;
			sumy += y;
			sumvv += v*v;
			sumyy += y*y;
			sumvy += v*y;
		}
		printf("Cross Validation Mean squared error = %g\n", total_error / prob.l);
		printf("Cross Validation Squared correlation coefficient = %g\n",
			((prob.l*sumvy - sumv*sumy)*(prob.l*sumvy - sumv*sumy)) /
			((prob.l*sumvv - sumv*sumv)*(prob.l*sumyy - sumy*sumy))
			);
	}
	else
	{
		for (i = 0; i < prob.l; i++)
			if (target[i] == prob.y[i])
				++total_correct;
		printf("Cross Validation Accuracy = %g%%\n", 100.0*total_correct / prob.l);
	}
	free(target);
}

int CxLibSVM::load_model(string model_path)
{
	//释放原来的模型
	free_model();
	//导入模型
	model_ = svm_load_model(model_path.c_str());
	if (model_ == NULL)return -1;
	return 0;
}

int CxLibSVM::save_model(string model_path)
{
	int flag = svm_save_model(model_path.c_str(), model_);
	return flag;
}

void CxLibSVM::free_model()
{
	if (model_ != NULL)
	{
		svm_free_and_destroy_model(&model_);
		svm_destroy_param(&param);

		if (prob.y != NULL)
		{
			free(prob.y);
			prob.y = NULL;
		}
		
		if (prob.x != NULL)
		{
			free(prob.x);
			prob.x = NULL;
		}
		
		if (x_space != NULL)
		{
			free(x_space);
			x_space = NULL;
		}
	}
}

main.cpp

#include "stdafx.h"
#include "CxLibSVM.h"
#include <time.h>
#include <iostream>
using namespace std;

void gen_train_sample(vector<vector<double>>& x, vector<double>& y, long sample_num, long dim, double scale);

void gen_test_sample(vector<double>& x, long sample_num, long dim, double scale);

int _tmain(int argc, _TCHAR* argv[])
{
	//初始化libsvm对象
	CxLibSVM    svm;
	svm.init_svm_param(svm.param);

	/*1、准备训练数据*/
	vector<vector<double>>    x;    //样本集
	vector<double>    y;            //样本类别标签集
	gen_train_sample(x, y, 200, 10, 1);

	/*1、交叉验证*/
	int fold = 10;
	svm.do_cross_validation(x, y, svm.param, fold);

	/*2、训练*/
	svm.train(x, y, svm.param);

	/*3、保存模型*/
	string model_path = "svm_model.txt";
	svm.save_model(model_path);

	/*4、导入模型*/
	svm.load_model(model_path);

	/*5、预测*/
	//生成随机测试数据
	vector<double> x_test;
	gen_test_sample(x_test, 200, 10, 1);
	double prob_est;
	//预测
	double value = svm.predict(x_test, prob_est);

	//打印预测类别和概率
	printf("label:%f, prob:%f", value, prob_est);

	return 0;
}

void gen_train_sample(vector<vector<double>>& x, vector<double>& y, long sample_num, long dim, double scale)
{
	srand((unsigned)time(NULL));//随机数
	//生成随机的正类样本
	for (int i = 0; i < sample_num; i++)
	{
		vector<double> rx;
		for (int j = 0; j < dim; j++)
		{
			rx.push_back(scale*(rand() % dim));
		}
		x.push_back(rx);
		y.push_back(1);
	}

	//生成随机的负类样本
	for (int i = 0; i < sample_num; i++)
	{
		vector<double> rx;
		for (int j = 0; j < dim; j++)
		{
			rx.push_back(-scale*(rand() % dim));
		}
		x.push_back(rx);
		y.push_back(2);
	}
}

void gen_test_sample(vector<double>& x, long sample_num, long dim, double scale)
{
	srand((unsigned)time(NULL));//随机数
	//生成随机的正类样本
	for (int j = 0; j < dim; j++)
	{
		x.push_back(-scale*(rand() % dim));
	}
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: libsvm是一个用于支持向量机(Support Vector Machine)的机器学习算法库,它提供了一系列用于解决分和回归问题的工具和函数。在安装libsvm之前,需要确保计算机已经安装了合适的编译环境,比如GCC编译器等。 首先,我们需要从libsvm的官方网站(https://www.csie.ntu.edu.tw/~cjlin/libsvm/)下载libsvm的压缩包。解压缩后,可以在终端中进入解压缩后的目录。 然后,在终端中输入以下命令编译libsvm: ``` cd python make ``` 这将编译libsvm所需的文件,并在python目录下生成一个名为`svm.so`的文件。 接下来,我们需要将编译生成的`svm.so`文件复制到相应的Python库目录中。在终端中输入以下命令: ``` sudo cp svm.so /usr/local/lib/python3.X/dist-packages ``` 其中,`python3.X`是你正在使用的Python版本。 最后,我们可以在Python中导入libsvm,并使用其提供的函数和: ```python from svmutil import * # 示例代码 prob = svm_problem([1, -1], [[1, 0, 1], [-1, 0, -1]]) param = svm_parameter('-c 4') model = svm_train(prob, param) ``` 通过以上步骤,我们成功安装了libsvm,并可以在Python中使用它进行支持向量机相关的机器学习任务。 ### 回答2: 安装libsvm c需要按照以下步骤进行。 第一步,下载libsvm c的源代码。可以在libsvm的官方网站上找到最新的源代码版本,也可以直接使用命令行下载。下载之后,将源代码保存到本地。 第二步,安装必要的软件依赖项。在Linux系统上,可以使用命令行工具包管理器(比如apt或者yum)来安装gcc编译器和make工具。在Windows系统上,需要安装MinGW编译器和MSYS工具。 第三步,解压源代码文件。将下载好的源代码文件解压到指定的目录下,比如/home/user/libsvm。 第四步,打开命令行终端,进入到解压好的源代码目录中。使用cd命令切换目录,比如cd /home/user/libsvm。 第五步,执行make命令来编译libsvm。在命令行中输入make,然后按下回车键。编译过程可能需要一些时间,耐心等待编译完成。 第六步,编译完成后,会生成一个可执行文件svm-train和一个动态链接库文件libsvm.so。可以通过运行svm-train来验证是否安装成功。在命令行中输入./svm-train,如果能够成功运行并显示帮助信息,则说明安装成功。 最后,将生成的libsvm.so文件复制到系统的库目录下(比如/usr/local/lib),以便在其他程序中引用libsvm库。 通过以上步骤,就可以成功安装libsvm c,并可以使用其提供的机器学习算法功能。 ### 回答3: libsvm是一个用于支持向量机(SVM)的机器学习库。在安装libsvm之前,我们需要确保已经安装了适当的编译器,如gcc。接下来,我们可以按照以下步骤进行安装: 1. 首先,下载libsvm的源代码文件。可以从libsvm官方网站(https://www.csie.ntu.edu.tw/~cjlin/libsvm/)上下载最新版本的libsvm。 2. 将下载的文件解压缩到一个目录中。 3. 打开终端,并进入到刚刚解压缩的目录。 4. 在终端中输入以下命令进行编译: ``` make ``` 这个命令会自动编译libsvm的源代码,并生成可执行文件svm-train和svm-predict。 5. 如果编译成功,我们可以将生成的可执行文件复制到我们希望使用的目录下,方便后续使用。 通过以上步骤,我们就成功地安装了libsvm。此时,我们可以通过运行svm-train和svm-predict来训练和预测SVM模型。同时,我们还可以在自己的代码中引入libsvm的头文件,使用其提供的函数和来训练和使用SVM模型。 需要注意的是,libsvm除了C语言版本外,还有其他语言的接口,如Python和Java。如果需要在其他编程语言中使用libsvm,我们可以按照相应语言的安装和使用方式进行操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值