libsvm是基于支持向量机(support vector machine, SVM)实现的开源库,由台湾大学林智仁(Chih-Jen Lin)教授等开发,它主要用于分类(支持二分类和多分类)和回归。它的License是BSD-3-Clause,最新发布版本是v322。libsvm具有操作简单、易于使用、快速有效、且对SVM所涉及的参数调节相对较少的特点。Code地址: https://github.com/cjlin1/libsvm

libsvm直接支持的开发语言包括:C++、java、matlab、python。C++主要包括两个文件,一个是头文件svm.h,一个是实现文件svm.cpp,将这两个文件加入到工程中就可以使用libsvm了。

在windows平台下,可以直接使用libsvm/windows目录下已经编译好的执行文件。

关于支持向量机的基础介绍可以参考: http://blog.csdn.net/fengbingchun/article/details/78326704

libsvm中支持的svm类型包括:C-SVC(multi-class classification)、nu-SVC(multi-class classification)、one-class SVM、epsilon-SVR(regression)、nu-SVR(regression);支持的kernel类型包括:linear(u’*v)、polynomial((gamma*u’*v+coef0)^degree)、radial basis function(径向基, exp(-gamma*|u-v|^2))、sigmoid(tanh(gamma*u’*v+coef0))、precomputed kernel(kernel values in training_set_file)。libsvm中需要的参数虽然较多,但是绝大多数都有其默认值。

libsvm中对数据集进行缩放的目的在于:避免一些特征值范围过大而另一些特征值范围过小;避免在训练时为了计算核函数而计算内积的时候引起数值计算的困难。通常将数据缩放到[-1, 1]或[0, 1]之间。

libsvm使用一般步骤:

(1)、按照libsvm所要求的格式准备数据集;

(2)、对数据进行简单的缩放操作;

(3)、考虑选用RBF(radial basis function)核参数;

(4)、如果选用RBF,通过libsvm/tools/grid.py采用交叉验证获取最佳参数C与gamma;

(5)、采用最佳参数C与g对整个训练集进行训练获取支持向量机模型;

(6)、利用获取的模型进行测试与预测。

测试代码执行步骤:

(1)、训练和测试数据采用UCI/Liver-disorders( https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary.html#liver-disorders ):二分类、训练样本为145、测试样本为200、特征长度为5,分别保存为liver-disorders_train.txt、liver-disorders_predict.txt;

(2)、通过libsvm/tools/checkdata.py来验证liver-disorders数据集是否满足libsvm所要求的数据格式(注:在windows下,此两个.txt文件编码格式要由utf-8改为ansi,否则执行checkdata.py会有errror),执行结果如下:

(3)、调用test_libsvm_scale函数对liver-disorders_train.txt进行缩放操作,并保存scale后的数据liver-disorders_train_scale.txt,并通过checkdata.py验证数据格式;

(4)、通过liver-disorders_train_scale.txt文件调用libsvm/tools/grid.py生成最优参数C和gamma,执行结果如下:

(5)、train,生成svm.model文件,执行结果如下,与libsvm/windows/svm-train.exe执行结果完全一致:

(6)、predict,执行结果如下,与libsvm/windows/svm-predict.exe执行结果完全一致:

以下二分类测试代码是参考libsvm中的svm-scale.c、svm-train.c、svm-predict.c:

#include "libsvm.hpp"
#include <iostream>
#include <limits>
#include <algorithm>
#include <fstream>
#include "svm.h"
#include "common.hpp"#define Malloc(type,n) (type *)malloc((n)*sizeof(type))static char* readline(FILE* input, int& max_line_len, char** line)
{if (fgets(*line, max_line_len, input) == nullptr) return nullptr;int len{ 0 };while (strrchr(*line, '\n') == nullptr) {max_line_len *= 2;*line = (char *)realloc(*line, max_line_len);len = (int)strlen(*line);if (fgets(*line + len, max_line_len - len, input) == nullptr) break;}return *line;
}static void output(const double* feature_max, const double* feature_min, double lower, double upper, long int& new_num_nonzeros, int index, double value, std::ofstream& out_file)
{/* skip single-valued attribute */if (feature_max[index] == feature_min[index]) return;if (value == feature_min[index]) value = lower;else if (value == feature_max[index]) value = upper;else value = lower + (upper - lower) * (value - feature_min[index]) / (feature_max[index] - feature_min[index]);if (value != 0) {//fprintf(stdout, "%d:%g ", index, value);out_file << index << ":" << value<<" ";new_num_nonzeros++;}
}int test_libsvm_scale(const char* input_file_name, const char* output_file_name)
{// reference: libsvm/svm-scale.cconst double lower{ -1. }, upper{ 1. }; // lower: x scaling lower limit(default -1); upper: x scaling upper limit(default +1)const double y_lower{ 0. }, y_upper{ 1. }, y_scaling{ 0. }; // y scaling limits (default: no y scaling)double y_max{ std::numeric_limits<double>::max() };double y_min{ std::numeric_limits<double>::lowest() };char* line{ nullptr };int max_line_len{ 1024 };double* feature_max{ nullptr };double* feature_min{ nullptr };int max_index{ 0 }, min_index{ 0 }, index{ 0 };long int num_nonzeros{ 0 }, new_num_nonzeros{ 0 };FILE* fp = fopen(input_file_name, "r");CHECK(nullptr != fp);line = (char *)malloc(max_line_len * sizeof(char));#define SKIP_TARGET \while (isspace(*p)) ++p; \while (!isspace(*p)) ++p;#define SKIP_ELEMENT \while (*p != ':') ++p; \++p; \while (isspace(*p)) ++p; \while (*p && !isspace(*p)) ++p;// pass 1: find out max index of attributesmax_index = 0;min_index = 1;while (readline(fp, max_line_len, &line) != nullptr) {char* p = line;SKIP_TARGETwhile (sscanf(p, "%d:%*f", &index) == 1) {max_index = std::max(max_index, index);min_index = std::min(min_index, index);SKIP_ELEMENTnum_nonzeros++;}}CHECK(min_index >= 1);rewind(fp);feature_max = (double *)malloc((max_index + 1)* sizeof(double));feature_min = (double *)malloc((max_index + 1)* sizeof(double));CHECK(feature_max != nullptr && feature_min != nullptr);for (int i = 0; i <= max_index; ++i) {feature_max[i] = std::numeric_limits<double>::lowest();feature_min[i] = std::numeric_limits<double>::max();}// pass 2: find out min/max valuewhile (readline(fp, max_line_len, &line) != nullptr) {char *p = line;int next_index = 1;double target;double value;CHECK(sscanf(p, "%lf", &target) == 1);y_max = std::max(y_max, target);y_min = std::min(y_min, target);SKIP_TARGETwhile (sscanf(p, "%d:%lf", &index, &value) == 2) {for (int i = next_index; i<index; ++i) {feature_max[i] = std::max(feature_max[i], 0.);feature_min[i] = std::min(feature_min[i], 0.);}feature_max[index] = std::max(feature_max[index], value);feature_min[index] = std::min(feature_min[index], value);SKIP_ELEMENTnext_index = index + 1;}for (int i = next_index; i <= max_index; ++i) {feature_max[i] = std::max(feature_max[i], 0.);feature_min[i] = std::min(feature_min[i], 0.);}}rewind(fp);std::ofstream out_file(output_file_name);CHECK(out_file);// pass 3: scalewhile (readline(fp, max_line_len, &line) != nullptr) {char *p = line;int next_index = 1;double target;double value;CHECK(sscanf(p, "%lf", &target) == 1);//fprintf(stdout, "%g ", target);out_file << target << " ";SKIP_TARGETwhile (sscanf(p, "%d:%lf", &index, &value) == 2) {for (int i = next_index; i<index; ++i)output(feature_max, feature_min, lower, upper, new_num_nonzeros, i, 0, out_file);output(feature_max, feature_min, lower, upper, new_num_nonzeros, index, value, out_file);SKIP_ELEMENTnext_index = index + 1;}for (int i = next_index; i <= max_index; ++i)output(feature_max, feature_min, lower, upper, new_num_nonzeros, i, 0, out_file);//fprintf(stdout, "\n");out_file << std::endl;}CHECK(new_num_nonzeros <= num_nonzeros);free(line);free(feature_max);free(feature_min);fclose(fp);out_file.close();return 0;
}static int read_problem(const char* input_file_name, svm_problem& prob, int& max_line_len, svm_parameter& param, char** line, svm_node** x_space)
{int max_index, inst_max_index;size_t elements, j;char* endptr;char *idx, *val, *label;FILE* fp = fopen(input_file_name, "r");CHECK(fp != nullptr);prob.l = 0;elements = 0;max_line_len = 1024;*line = Malloc(char, max_line_len);while (readline(fp, max_line_len, line) != nullptr) {char *p = strtok(*line, " \t"); // label// featureswhile (1) {p = strtok(nullptr, " \t");if (p == nullptr || *p == '\n') // check '\n' as ' ' may be after the last featurebreak;++elements;}++elements;++prob.l;}rewind(fp);prob.y = Malloc(double, prob.l);prob.x = Malloc(struct svm_node *, prob.l);*x_space = Malloc(struct svm_node, elements);max_index = 0;j = 0;for (int i = 0; i<prob.l; i++) {inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has <index> start from 0readline(fp, max_line_len, line);prob.x[i] = &(*x_space)[j];label = strtok(*line, " \t\n");CHECK(label != nullptr); // empty lineprob.y[i] = strtod(label, &endptr);CHECK(!(endptr == label || *endptr != '\0'));while (1) {idx = strtok(nullptr, ":");val = strtok(nullptr, " \t");if (val == nullptr) break;errno = 0;(*x_space)[j].index = (int)strtol(idx, &endptr, 10);if (endptr == idx || errno != 0 || *endptr != '\0' || (*x_space)[j].index <= inst_max_index) {CHECK(0);} else {inst_max_index = (*x_space)[j].index;}errno = 0;(*x_space)[j].value = strtod(val, &endptr);if (endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr))) CHECK(0);++j;}if (inst_max_index > max_index) max_index = inst_max_index;(*x_space)[j++].index = -1;}if (param.gamma == 0 && max_index > 0) param.gamma = 1.0 / max_index;if (param.kernel_type == PRECOMPUTED) {for (int i = 0; i<prob.l; i++) {CHECK(prob.x[i][0].index == 0);if ((int)prob.x[i][0].value <= 0 || (int)prob.x[i][0].value > max_index) {CHECK(0);}}}fclose(fp);return 0;
}int test_libsvm_two_classification_train()
{// reference: libsvm/svm-train.cconst std::string input_file_name{ "E:/GitCode/NN_Test/data/database/liver-disorders/liver-disorders_train.txt" },output_file_name{ "E:/GitCode/NN_Test/data/database/liver-disorders/liver-disorders_train_scale.txt" },svm_model{"E:/GitCode/NN_Test/data/svm.model"};CHECK(0 == test_libsvm_scale(input_file_name.c_str(), output_file_name.c_str())); // data scalestruct svm_parameter param = {};struct svm_problem prob = {};struct svm_model* model = nullptr;struct svm_node* x_space = nullptr;int cross_validation{ 0 };int nr_fold{0};char* line = nullptr;int max_line_len{0};param = { C_SVC, RBF, 3, 0.0078125, 0., 100, 1e-3, 512., 0, nullptr, nullptr, 0.5, 0.1, 1, 0 };CHECK(read_problem(output_file_name.c_str(), prob, max_line_len, param, &line, &x_space) == 0);CHECK(svm_check_parameter(&prob, ¶m) == nullptr);model = svm_train(&prob, ¶m);CHECK(svm_save_model(svm_model.c_str(), model) == 0);svm_free_and_destroy_model(&model);svm_destroy_param(¶m);free(prob.y);free(prob.x);free(x_space);free(line);return 0;
}static int predict(FILE* input, FILE* output, const svm_model* model, int& max_line_len, char** line, int& max_nr_attr, svm_node** x)
{int correct = 0;int total = 0;double error = 0;double sump = 0, sumt = 0, sumpp = 0, sumtt = 0, sumpt = 0;int svm_type = svm_get_svm_type(model);int nr_class = svm_get_nr_class(model);double *prob_estimates = nullptr;int j;max_line_len = 1024;*line = (char *)malloc(max_line_len*sizeof(char));while (readline(input, max_line_len, line) != nullptr) {int i = 0;double target_label, predict_label;char *idx, *val, *label, *endptr;int inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has <index> start from 0label = strtok(*line, " \t\n");CHECK(label != nullptr); // empty linetarget_label = strtod(label, &endptr);CHECK(!(endptr == label || *endptr != '\0'));while (1) {if (i >= max_nr_attr - 1) { // need one more for index = -1max_nr_attr *= 2;*x = (struct svm_node *) realloc(*x, max_nr_attr*sizeof(struct svm_node));}idx = strtok(nullptr, ":");val = strtok(nullptr, " \t");if (val == nullptr) break;errno = 0;(*x)[i].index = (int)strtol(idx, &endptr, 10);CHECK(!(endptr == idx || errno != 0 || *endptr != '\0' || (*x)[i].index <= inst_max_index));inst_max_index = (*x)[i].index;errno = 0;(*x)[i].value = strtod(val, &endptr);CHECK(!(endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr))));++i;}(*x)[i].index = -1;predict_label = svm_predict(model, *x);fprintf(output, "%g\n", predict_label);if (predict_label == target_label) ++correct;error += (predict_label - target_label)*(predict_label - target_label);sump += predict_label;sumt += target_label;sumpp += predict_label*predict_label;sumtt += target_label*target_label;sumpt += predict_label*target_label;++total;}fprintf(stdout, "Accuracy = %g%% (%d/%d) (classification)\n", (double)correct / total * 100, correct, total);return 0;
}int test_libsvm_two_classification_predict()
{// reference: libsvm/svm-predict.cconst std::string input_file_name{ "E:/GitCode/NN_Test/data/database/liver-disorders/liver-disorders_predict.txt" },scale_file_name{ "E:/GitCode/NN_Test/data/database/liver-disorders/liver-disorders_predict_scale.txt" },svm_model{ "E:/GitCode/NN_Test/data/svm.model" },predict_result_file_name{ "E:/GitCode/NN_Test/data/svm_predict_result.txt" };CHECK(0 == test_libsvm_scale(input_file_name.c_str(), scale_file_name.c_str())); // data scalestruct svm_node* x = nullptr;int max_nr_attr = 64;struct svm_model* model = nullptr;int predict_probability = 0;char* line = nullptr;int max_line_len = 0;FILE* input = fopen(scale_file_name.c_str(), "r");CHECK(input != nullptr);FILE* output = fopen(predict_result_file_name.c_str(), "w");CHECK(output != nullptr);CHECK((model = svm_load_model(svm_model.c_str())) != nullptr);x = (struct svm_node *) malloc(max_nr_attr*sizeof(struct svm_node));CHECK(svm_check_probability_model(model) == 0);predict(input, output, model, max_line_len, &line, max_nr_attr, &x);svm_free_and_destroy_model(&model);free(x);free(line);fclose(input);fclose(output);return 0;
}

GitHub: https://github.com/fengbingchun/NN_Test

libsvm库简介及使用相关推荐

  1. 【C 语言】动态库封装与设计 ( Windows 动态库简介 | Visual Studio 调用动态库 )

    文章目录 一.Windows 动态库简介 二.Visual Studio 调用动态库 一.Windows 动态库简介 在 C:\Windows\System32 目录中 , 存放着 Windows 中 ...

  2. Py之Pandas:Python的pandas库简介、安装、使用方法详细攻略

    Py之Pandas:Python的pandas库简介.安装.使用方法详细攻略 目录 pandas库简介 pandas库安装 pandas库使用方法 1.函数使用方法 2.使用经验总结 3.绘图相关操作 ...

  3. c++中algorithm头文件、STL库简介及使用说明

    c++中algorithm头文件.STL库简介及使用说明 c++中algorithm头文件是STL的算法部分,里边定义了各种算法,比如sort之类的.加上algorithm就可以使用stl库里的各种算 ...

  4. SVM学习——在matlab上安装libsvm库(一)

    环境搭建 平台: Windows PC MATLAB 软件 libsvm库(SVM工具箱) 安装步骤 准备工作 安装对应的编译器,在网站上查看当前matlab版本支持的编译器版本.本文使用的matla ...

  5. 网络编程知识预备(5) ——libcurl库简介及其编程访问百度首页

    本文为学习笔记,整合课程内容以及下列文章: 其中,libcurl函数库常用字段解读部分: 参考博文:原文地址 作者:冬冬他哥哥 目录 Libcurl库简介 Libcurl等三方库的通用编译方法 三方库 ...

  6. OpenGL 库 简介

    OpenGL 库 简介 OpenGL库函数的命名方式为:<库前缀><根命令><可选的参数个数><可选的参数类型>. 库前缀有gl.glu.aux.glu ...

  7. python函数库_10. 标准库简介

    10.标准库简介¶ 10.1.操作系统接口¶ os 模块提供了许多与操作系统交互的函数: >>>import os >>>os.getcwd() # Return ...

  8. JSP→JSTL标准标签库简介与环境搭建、JSTL助手EL表达式EL隐式对象、标签→out、set、if、多选择配合、foreach、redirect、格式化、JSTL函数标签、自定义标签、标签类架构

    JSTL标准标签库简介与环境搭建 EL表达式与EL隐式对象 out标签 set标签 remove标签 catch标签 if标签 choose.when.otherwise配合标签 foreach标签 ...

  9. 无人机飞控 ardupilot Copter-4.0.7 库简介

    无人机飞控 ardupilot Copter-4.0.7 库简介 官方文档-库说明 核心库: 库名称 作用 AP_AHRS 使用 DCM 或 EKF 进行姿态估计 AP_Common 所有草图和库所需 ...

最新文章

  1. Python中的GIL(全局解释器锁)
  2. 自定义类在PropertyGrid上的展示方法
  3. java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä'
  4. 偏振模色散及保偏光纤的正确理解
  5. 机器学习实践中的 7 种常见错误
  6. python打开chrome浏览器登录用户名密码_[工具]Python获取Chrome浏览器已保存的所有账号密码...
  7. 3.1等待和通知API(Wait-and-Notify API Tour)
  8. 北京大学肖臻老师《区块链技术与应用》公开课笔记:以太坊原理(三):智能合约
  9. thingjs这个3D js库怎么样?
  10. 《Rework》摘录及感想
  11. 功能测试Ⅲ——缺陷及缺陷管理
  12. 关于电子计算机的热点,计算机如何成为热点? 8台计算机wifi热点软件推荐
  13. java的像素与dpi_DPI与像素的关系
  14. idea程序参数program arguments,vm arguments,Environment variable
  15. 【2018慢性病与信息大会】周脉耕:信息化助力基层慢病管理
  16. C语言从键盘上输入年份和月份,计算并输出这一年的这一月共有多少天。
  17. 1月第2周业务风控关注 | 微信打击盗用他人的身份恶意注册,去年处理300多万例
  18. Docker构建Shipyard
  19. STM32F407控制 无刷直流电机和永磁同步电机
  20. php设计模式自我理解

热门文章

  1. 数据结构--搜索BFS
  2. Cost Function
  3. TensorFlow(3)张量与变量
  4. laravel carbon 格式化日期_Laravel 编码实践分享
  5. 在CentOS 6.3 64bit上安装FTP服务器vsftpd 2.2.2
  6. 在CentOS 6.3 64bit上安装Nginx 1.8.0
  7. UML类图符号 各种关系说明以及举例
  8. 二分法:二分查找(递归+非递归)实现
  9. 戏说 .NET GDI+系列学习教程(三、Graphics类的应用_验证码)
  10. Powerdesigner逆向工程64位Oracle数据库