python svm包_支持向量机的开源包LIBSVM

前言

LIBSVM是台湾大学林智仁(Lin Chih-Jen)教授等开发设计的一个简单、易于使用和快速有效的SVM分类与回归的软件包。LIBSVM软件包拥有目前各种常用编程语言的版本,如Python、Java、Matlab等。

一、支持算法

LIBSVM支持下述算法,具体可以参考作者写的介绍文档

1.1 C-SVC

1.2 ν-SVC

1.3 ε-SVR

1.4 ν-SVR

二、LIBSVM入门使用

作者写了该软件包的入门使用文档

SVM使用流程:

转换数据格式;

缩放数据,例如将其变换到[0,1]或者[-1,1]的范围;

使用RBF核函数;

使用交叉验证寻找最优参数C和r;

使用最优参数训练整个数据集;

测试。

首选RBF核函数,原因是:

线性核是RBF的特例;

Sigmoid核在特定参数下的特性类似于RBF;

多项式核参数比RBF多,在阶数较高时且容易导致计算数值过大。

但是在特征数量很大时,RBF可能会不适用,使用线性核是一种更好的选择。

寻找最优参数:

使用网格搜索利用交叉验证寻找最优参数时,先使用粗网格,然后缩小寻找区域使用细网格。网格使用指数拉伸网格,例如:C=2-5,2-4,...,210 ,gamma=2-7,2-6,...,215。

特征数量:

特征过多时,先进行特征提取,选取一个合适的特征子集。

LIBSVM不适合特征数量过多且样本数量过多的情形,比如文档分类。

LIBLINEAR更加适合这类情况。

在样本数量很大时,LIBLINEAR速度会快很多倍。

三、Python接口

LIBSVM接口函数在svmutil.py文件中,按照源码顺序依次是:

svm_read_problem(data_file_name)

从文本文件中读取数据,数据的格式为:

label index1:value1 index2:value2 ...

返回训练所用的y和x,使用示例:

y, x = svm_read_problem('data.txt')

假定文件中数据如下:

1 1:1.1 2:1.2 3:1.3 4:1.4

-1 1:-1.1 2:-1.2 3:-1.3 4:-1.4

则y=[1.0, -1.0],

x=[{1: 1.1, 2: 1.2, 3: 1.3, 4: 1.4}, {1: -1.1, 2: -1.2, 3: -1.3, 4: -1.4}]。

svm_load_model(model_file_name)

从文件中读取SVM模型。

svm_save_model(model_file_name, model)

将SVM模型保存到文件中。

evaluations(ty, pv)

ty即训练的数据y,

pv即预测的y值。

返回(准确率, 均方误差, 均方相关系数)这样一个元组,使用示例:

ACC, MSE, SCC = evaluations(y, pred_labels)。

svm_train(arg1, arg2=None, arg3=None)

调用有以下几种形式:

svm_train(y, x [, options]) -> model | ACC | MSE

svm_train(prob [, options]) -> model | ACC | MSE

svm_train(prob, param) -> model | ACC | MSE

如果使用了交叉验证,epsilon-SVR和nu-SVR返回MSE,其他返回ACC;没有使用交叉验证就返回model。

后两种调用中出现的prob参数是对应svm.py文件中的svm_problem类型,

生成方法为:prob = svm_problem(y, x)。

最后一种调用方式中出现的param参数对应svm.py中的svm_parameter类型,

生成方法为:param = svm_parameter('-t 0 -c 1')。

options类似于linux命令中的参数输入方式,有以下选项:

-s SVM的类型,默认值为0

0 -- C-SVC

1 -- nu-SVC

2 -- one-class SVM

3 -- epsilon-SVR

4 -- nu-SVR

-t 核函数的类型,默认值为2

0 -- 线性: u'*v

1 -- 多项式: (gamma*u'*v + coef0)^degree

2 -- 径向基: exp(-gamma*|u-v|^2)

3 -- sigmoid: tanh(gamma*u'*v + coef0)

4 -- precomputed kernel,核函数值存储于training_set_file中

-d degree的值,默认为3;

-g gamma的值,默认1/num_features;

-r coef0的值,默认为0;

-c C-SVC, epsilon-SVR, and nu-SVR的cost,默认值为1;

-n nu-SVC, one-class SVM, and nu-SVR中的nu,默认值为0.5;

-p epsilon-SVR的loss function中的epsilon参数,默认值0.1;

-m 缓冲内存大小,单位MB,默认值100;

-e 终止判据的容忍值,默认值0.001;

-h 是否使用收缩启发式算法(shrinking heuristics),取值0或1,默认值为0;

-b 是否估算正确概率,取值0或1,默认值为0;

-wi C-SVC中第i个特征的Cost参数;

-v 交叉验证;

-q 静默方式,无输出。

svm_predict(y, x, m, options="")

y、x对应测试数据,m即训练好的model,options支持-b和-q。

调用语法:

p_labs, p_acc, p_vals = svm_predict(y, x, model [,'predicting_options'])

返回预测的标签,(准确率, 均方误差, 均方相关系数)元组,以及-b 1参数时返回判断系数。

Tips:

svm_train(y, x [, options])这种形式的调用,x除了字典形式以外,如:

x = [{1: 1.1, 2: 1.2, 3: 1.3, 4: 1.4}, {1: -1.1, 2: -1.2, 3: -1.3, 4: -1.4}]

也可以是如下形式,

x = [[1.1, 1.2, 1.3, 1.4], [-1.1, -1.2, -1.3, -1.4]]

svm_train会调用svm.py文件中svm_problem类对y和x进行包装,svm_problem类又会调用gen_svm_nodearray函数对x进行处理,该函数可以处理x两种情形的输入。

四、数值实验

这里使用SVR对创业板开盘指数历史曲线做一下回归,数据可以从网易财经下载

首先,使用get_stock_data函数从下载的数据中读取相关信息,并转换为相应的参数数组(用到工具函数代码见最后)。进行归一化之后,使用网格搜索得到最优参数。最后使用最优参数进行训练。

def get_stock_data(file_path):

"""

从文件中读取股票的数据信息。

:param file_path:

:return: X = [收盘指数、最高指数、最低指数、开盘指数、成交量、成交额]

y = [开盘指数]

"""

# 收盘价、最高价、最低价、开盘价、成交量、成交额

# 从0开始计数,对应表格的第4,5,6,7,11,12列

... ...

stock_data_array, target_array = get_stock_data(stock_file_path)

m_count = len(stock_data_array)

x_data = stock_data_array[:m_count-1]

y_data = target_array[1:]

# 归一化

x_data, x_map_inf = Utils.map_min_max_2D(x_data)

y_data, y_map_inf = Utils.map_min_max_1D(y_data)

# 寻找最优参数

mse_best, c_best, g_best = Utils.get_best_cg_for_SVR(y_data, x_data, -4, 4, -4, 4, c_step=0.25, g_step=0.25)

# 使用最优参数进行训练

model = svm_train(y_data, x_data, '-s 3 -c {} -g {} -p 0.0005'.format(str(c_best), str(g_best )))

py_data, p_acc, p_val = svm_predict(y_data, x_data, model)

# 从归一化数据变换回来

y_data, _ = Utils.map_min_max_1D(y_data, is_reverse=True, map_inf=y_map_inf)

py_data, _ = Utils.map_min_max_1D(py_data, is_reverse=True, map_inf=y_map_inf)

回归的结果如下:

“炒股这方面,接盘是不可能接盘的,这辈子不可能接盘的。做分析又不会做,就是关灯吃面、滴蜡复盘,才能维持的了生活这样子,进股市感觉像回家一样,在股市里的感觉比家里感觉好多了!上市公司个个都是精华,吹得又好听,我超喜欢股市的!”——接盘·格瓦拉

勇敢的生活下去还是要靠爱... ...

注:

Utils类包含几个工具函数,为方便阅读,此处省略了具体的代码。

import numpy as np

import math

from svmutil import *

class Utils:

@staticmethod

def output_tecplot_line(title="1D Data", file_name=".tmp.plt", var_dict=None):

"""

将数据输出成Tecplot曲线

:param title:

:param file_name:

:param var_dict:

:return:

"""

@staticmethod

def output_tecplot_2D(title="2D Data", file_name=".tmp.plt", var_dict=None):

"""

将数据输出成Tecplot二维数据

:param title:

:param file_name:

:param var_dict:

:return:

"""

@staticmethod

def map_min_max_2D(data, map_range=[0, 1], use='col', is_reverse=False, map_inf=[]):

'''

对二维data矩阵进行归一化

:param data: 二维矩阵,为list类型

:param map_range: 默认映射到[0,1]之间

:param use: 'row'按行归一化,'col'按列归一化,默认按行列一化

:param is_reverse: 还原

:param map_inf: 保存归一化的映射信息,即每一行的最小值、最大值两个参数

:return: 归一化的矩阵,(映射信息矩阵)。

'''

@staticmethod

def map_min_max_1D(data, map_range=[0, 1], is_reverse=False, map_inf=[]):

@staticmethod

def get_best_cg_for_SVR(train_label, train_data, c_min, c_max,

g_min, g_max, fold_counts=3, c_step=1, g_step=1):

'''

使用LIBSVM中SVR工具之时,获取最优参数-c和-g的值。

:param train_label:

:param train_data:

:param c_min:

:param c_max:

:param g_min:

:param g_max:

:param fold_counts: 交叉验证的折数

:param c_step:

:param g_step:

:return: 返回c、g的最优值。

'''

附录——我的其他博客

你可能感兴趣的:(python,svm包)