Sklearn 支持向量机库介绍

本文最后更新于:2022年10月10日 下午

之前我们进行过 SVM 原理的推导,本文记录 Sklearn 支持向量机库相关内容。

Sklearn 支持向量机库概述

  • 我们知道SVM相对感知器而言,它可以解决线性不可分的问题,那么它是如何解决的呢?其思想很简单就是对原始数据的维度变换,一般是扩维变换,使得原样本空间中的样本点线性不可分,但是在变维之后的空间中样本点是线性可分的,然后再变换后的高维空间中进行分类。

  • sklearn中SVM的算法库分为两类

    • 分类的算法库,主要包含 LinearSVC,NuSVC 和 SVC 三个类
    • 回归算法库,包含SVR,NuSVR 和 LinearSVR 三个类,相关模块都包裹在 sklearn.svm 模块中。
  • 对于SVC,NuSVC 和 LinearSVC 三个分类的库,SVC 和 NuSVC 差不多,区别仅仅在于对损失的度量方式不同,而LinearSVC从名字就可以看出,他是线性分类,也就是不支持各种低维到高维的核函数,仅仅支持线性核函数,对线性不可分的数据不能使用。

  • 同样的对于SVR,NuSVR 和 LinearSVR 三个回归的类,SVR 和 NuSVR 差不多,区别也仅仅在于对损失的度量方式不同。LinearSVR 是线性回归,只能使用线性核函数。

  • 我们使用这些类的时候,如果有经验知道数据是线性可以拟合的,那么使用 LinearSVC 去分类或者 LinearSVR 去回归,他们不需要我们去慢慢的调参选择各种核函数以及对应的参数,速度也快。如果我们对数据分布没有什么经验,一般使用 SVC 去分类或者 SVR 去回归,这就需要我们选择核函数以及对核函数调参了。

回顾SVM分类算法和回归算法

  • 对SVM算法进行回顾,首先对于SVM分类算法,其原始形式如下:
$$ \begin{array}{c} \min \frac{1}{2}\|w\|^{2}+C \sum_{i=1}^{n} \xi_{i} \\ s.t., y_{i}\left(w^{T} x_{i}+b\right) \geq 1-\xi_{i}, i=1, \ldots, n \\ \xi_{i} \geq 0, i=1, \ldots, n \end{array} $$
  • 其中 $n$ 为样本个数,我们的样本为$[(x_1, y_1),(x_2,y_2),…,(x_n, y_n)]$, $w,b$是我们的分离超平面的 $w^T \bf {x} + b = 0$ 的系数,$ξ_i$ 为第 $i$ 个样本的松弛系数,$C$ 为惩罚系数,$x_i$ (也有时候写为 $Φ(x_i) $ 为低维到高维的映射函数) 为样本数。
  • 通过拉格朗日以及对偶化后的形式为:
$$ \begin{aligned} \max _{\alpha} & \sum_{i=1}^{n} \alpha_{i}-\frac{1}{2} \sum_{i, j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j}\left\langle x_{i}, x_{j}\right\rangle \\ \text { s.t. }, & 0 \leq \alpha_{i} \leq C, i=1, \ldots, n \\ & \sum_{i=1}^{n} \alpha_{i} y_{i}=0 \end{aligned} $$
  • 其中和原始形式不同的 $α$ 为拉格朗日系数向量,$<x_i, x_j>$ 为我们要使用的核函数。
  • 对于SVM回归算法,(借用刘建平老师的博客),其原始形式如下:
$$ \begin{array}{c} \min \frac{1}{2}\|w\|_{2}^{2}+C \sum_{i=1}^{m}\left(\xi_{i}^{\vee}+\xi_{i}^{\wedge}\right)\\ s.t. \quad-\epsilon-\xi_{i}^{\vee} \leq y_{i}-w \bullet \phi\left(x_{i}\right)-b \leq \epsilon+\xi_{i}^{\wedge} \\ \xi_{i}^{\vee} \geq 0, \quad \xi_{i}^{\wedge} \geq 0(i=1,2, \ldots, m) \end{array} $$
  • 其中 $m$ 为样本个数,我们的样本为 $[(x_1, y_1),(x_2,y_2),…,(x_m, y_m)]$, $w,b$ 是我们回归超平面 $w^Tx_i + b = 0$ 的系数,$ξ_v$, $ξ^\vee$ 为第 $i$ 个样本的松弛系数, $C$ 为惩罚系数,$ε$ 为损失边界,到超平面距离小于 $ε$ 的训练集的点没有损失,$Φ(x_i)$ 为低维到高维的映射函数
  • 通过拉格朗日函数以及对偶后的形式为:
$$ \begin{array}{c} \underbrace{\min }_{\alpha^{\vee}, \alpha^{\wedge}} \frac{1}{2} \sum_{i=1, j=1}^{m}\left(\alpha_{i}^{\wedge}-\alpha_{i}^{\vee}\right)\left(\alpha_{j}^{\wedge}-\alpha_{j}^{\vee}\right) K\left(x_{i}, x_{j}\right)-\sum_{i=1}^{m}\left(\epsilon-y_{i}\right) \alpha_{i}^{\wedge}+\left(\epsilon+y_{i}\right) \alpha_{i}^{\vee}\\ s.t. \sum_{i=1} ^ {m} (\alpha_{i}^{\wedge}-\alpha_{i} ^ { \vee})=0 \\ 0< \alpha_{i} ^ {\vee} < C(i=1,2, \ldots, m), 0< \alpha_{i} ^ {\wedge} < C(i=1,2, \ldots, m) \end{array} $$
  • 其中和原始形式不同的 $α^{\vee}$, $α^{\vee}$ 为拉格朗日系数向量,$K(x_i, x_j)$ 为我们要使用的核函数。

SVM核函数概述

  • 我在第二篇SVM中学习了核函数,有好几种,最常用的就是线性核函数,多项式核函数,高斯核函数和Sigmoid核函数,在scikit-learn中,内置的核函数也刚好有这四种。

线性核函数(Linear Kernel)

  • 线性核函数表达式为:

$$
\kappa\left(x_{1}, x_{2}\right)=\left\langle x_{1}, x_{2}\right\rangle
$$

  • 就是普通的内积,LinearSVC 和 LinearSVR 只能使用它。

多项式核函数(Polynomial Kernel)

  • 多项式核函数是线性不可分SVM常用的核函数之一,表达式为:

$$
k\left(x_{i}, x_{j}\right)=\left(x_{i}^{t} x_{j}\right)^{d}, d \geqslant 1
$$

  • 参数都需要自己调参定义,比较麻烦。

高斯核函数(Gaussian Kernel)

  • 高斯核函数,在 SVM 中也称为 径向基核函数(Radial Basisi Function,RBF),它是 libsvm 默认的核函数,当然也是 sklearn 默认的核函数,表达式为:

$$
k(x, y)=\exp \left(-\gamma|x-y|^{2}\right)
$$

  • 其中 $\gamma$ 大于 0,需要自己调参定义,不过一般情况,我们都使用高斯核函数。

Sigmoid核函数(Sigmoid Kernel)

  • Sigmoid核函数也是线性不可分SVM常用的核函数之一,表示为:

$$
k\left(x_{i}, x_{j}\right)=\tanh \left(\beta x_{i}^{t} x_{j}+\theta\right), \beta>0
$$

  • 其中 $\beta, \theta$ 都需要自己调参定义。

  • 一般情况下,对于非线性数据使用默认的高斯核函数会有比较好的效果,如果你不是 SVM 调参高手的话,建议使用高斯核来做数据分析。

SVM分类算法库

  • 下面我们将具体介绍这三种分类方法都有那些参数值以及不同参数值的含义。

LinearSVC

  • 其函数原型如下:
1
2
3
4
5
class sklearn.svm.LinearSVC(self, 
penalty='l2', loss='squared_hinge', dual=True, tol=1e-4,
C=1.0, multi_class='ovr', fit_intercept=True,
intercept_scaling=1, class_weight=None, verbose=0,
random_state=None, max_iter=1000)
参数说明
参数 含义
penalty 正则化参数,L1 和 L2 两种参数可选,仅 LinearSVC 有。默认是 L2 正则化,如果我们需要产生稀疏的话,可以选择 L1 正则化,这和线性回归里面的 Lasso 回归类似
loss 损失函数,有 hingesquared_hinge 两种可选,前者又称为 L1 损失,后者称为 L2 损失,默认是 squared_hinge,其中 hinge 是SVM的标准损失,squared_hingehinge的平方
dual 是否转化为对偶问题求解,默认是 True。这是一个布尔变量,控制是否使用对偶形式来优化算法
tol 残差收敛条件,默认是0.0001,与 LR 中的一致
C 惩罚系数,用来控制损失函数的惩罚系数,类似于LR中的正则化系数。默认为1,一般需要通过交叉验证来选择一个合适的C,一般来说,噪点比较多的时候,C需要小一些
multi_class 负责多分类问题中分类策略制定,有 ovrcrammer_singer 两种参数值可选,默认值是ovrovr的分类原则是将待分类中的某一类当作正类,其他全部归为负类,通过这样求取得到每个类别作为正类时的正确率,取正确率最高的那个类别为正类;crammer_singer 是直接针对目标函数设置多个参数值,最后进行优化,得到不同类别的参数值大小
fit_intercept 是否计算截距,与LR模型中的意思一致
class_weight 与其他模型中参数含义一样,也是用来处理不平衡样本数据的,可以直接以字典的形式指定不同类别的权重,也可以使用balanced参数值。如果使用 balanced,则算法会自己计算权重,样本量少的类别所对应的样本权重会高,当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个系数,选择默认的None
verbose 是否冗余,默认为False
random_state 随机种子的大小
max_iter 最大迭代次数,默认为1000

惩罚系数

  • 错误项的惩罚系数。C越大,即对分错样本的惩罚程度越大,因此在训练样本中准确率越高,但是泛化能力降低,也就是对测试数据的分类准确率降低。相反,减少C的话,容许训练样本中有一些误分类错误样本,泛化能力强。对于训练样本带有噪音的情况,一般采用后者,把训练样本集中错误分类的样本作为噪音。

NuSVC

  • 其函数原型如下:
1
2
3
4
class sklearn.svm.NuSVC(self, nu=0.5, kernel='rbf', degree=3, gamma='auto_deprecated',
coef0=0.0, shrinking=True, probability=False, tol=1e-3,
cache_size=200, class_weight=None, verbose=False, max_iter=-1,
decision_function_shape='ovr', random_state=None)
参数说明
参数 含义
nu 训练误差部分的上限和支持向量部分的下限,取值在 $(0,1)$ 之间,默认是 0.5,它和惩罚系数 $C$ 类似,都可以控制惩罚的力度
degree 当核函数是多项式核函数(poly)的时候,用来控制函数的最高次数。(多项式核函数是将低维的输入空间映射到高维的特征空间),这个参数只对多项式核函数有用,是指多项式核函数的阶数 $n$。如果给的核函数参数是其他核函数,则会自动忽略该参数
gamma 核函数系数,默认是 auto,即特征维度的倒数。核函数系数,只对rbf poly sigmoid 有效
coef0 核函数常数值 ($y = kx + b$ 的 b 值),只有 polysigmoid 函数有,默认值是0
max_iter 最大迭代次数,默认值是 -1 ,即没有限制
probability 是否使用概率估计,默认是 False
decision_function_shape multi_class 参数含义类似,可以选择 ovo 或者 ovr(0.18版本默认是 ovo,0.19版本为 ovr) OvR(one vs rest)的思想很简单,无论你是多少元分类,我们都可以看做二元分类,具体的做法是,对于第K类的分类决策,我们把所有第K类的样本作为正例,除第K类样本以外的所有样本作为负类,然后在上面做二元分类,得到第K类的分类模型。
OvO(one vs one)则是每次在所有的T类样本里面选择两类样本出来,不妨记为T1类和T2类,把所有的输出为 T1 和 T2 的样本放在一起,把 T1作为正例,T2 作为负例,进行二元分类,得到模型参数,我们一共需要 T(T-1)/2 次分类。从上面描述可以看出,OvR 相对简单,但是分类效果略差(这里是指大多数样本分布情况,某些样本分布下OvR 可能更好),而 OvO 分类相对精确,但是分类速度没有 OvR 快,一般建议使用 OvO 以达到较好的分类效果
chache_size 缓冲大小,用来限制计算量大小,默认是200M,如果机器内存大,推荐使用500MB甚至1000MB
kernel 核函数,核函数是用来将非线性问题转化为线性问题的一种方法,默认是 rbf 核函数
  • 常用的核函数有以下几种:

    函数 含义
    linear 线性核函数
    poly 多项式核涵数
    rbf 高斯核函数
    sigmod sigmod 核函数
    precomputed 自定义核函数

SVC

  • 其函数原型如下:
1
2
3
4
5
class sklearn.svm.SVC(self, C=1.0, kernel='rbf', degree=3, gamma='auto_deprecated',
coef0=0.0, shrinking=True, probability=False,
tol=1e-3, cache_size=200, class_weight=None,
verbose=False, max_iter=-1, decision_function_shape='ovr',
random_state=None)
参数说明
  • C:惩罚系数

  • SVC 和 NuSVC 方法基本一致,唯一区别就是损失函数的度量方式不同(NuSVC中的nu参数和SVC中的C参数)即SVC使用惩罚系数C来控制惩罚力度,而NuSVC使用nu来控制惩罚力度。

SVM回归算法库

  • 下面我们将具体介绍这三种分类方法都有那些参数值以及不同参数值的含义。

LinearSVR

  • 其函数原型如下:
1
2
3
4
class sklearn.svm.LinearSVR(self, epsilon=0.0, tol=1e-4, C=1.0,
loss='epsilon_insensitive', fit_intercept=True,
intercept_scaling=1., dual=True, verbose=0,
random_state=None, max_iter=1000)
参数说明
参数 含义
epsilon 距离误差epsilon,即回归模型中的 epsilon,训练集中的样本需要满足:
$-\epsilon-\xi_{i}^{\vee} \leq y_{i}-w \bullet \phi\left(x_{i}\right)-b \leq \epsilon+\xi_{i}^{\wedge}$
loss 损失函数,有 hingesquared_hinge 两种可选,前者又称为 L1 损失,后者称为 L2 损失,默认是 squared_hinge,其中 hinge 是 SVM 的标准损失,squared_hingehinge 的平方
dual 是否转化为对偶问题求解,默认是True。这是一个布尔变量,控制是否使用对偶形式来优化算法
tol 残差收敛条件,默认是0.0001,与LR中的一致
C 惩罚系数,用来控制损失函数的惩罚系数,类似于LR中的正则化系数。默认为1,一般需要通过交叉验证来选择一个合适的C,一般来说,噪点比较多的时候,C需要小一些
fit_intercept 是否计算截距,与LR模型中的意思一致
verbose 是否冗余,默认为False
random_state 随机种子的大小
max_iter 最大迭代次数,默认为1000

NuSVR

  • 其函数原型如下:
1
2
3
class sklearn.svm.NuSVR(self, nu=0.5, C=1.0, kernel='rbf', degree=3,
gamma='auto_deprecated', coef0=0.0, shrinking=True,
tol=1e-3, cache_size=200, verbose=False, max_iter=-1)
参数说明
参数 含义
nu 训练误差部分的上限和支持向量部分的下限,取值在 (0,1) 之间,默认是 0.5,它和惩罚系数 $C$ 类似,都可以控制惩罚的力度
degree 当核函数是多项式核函数(poly)的时候,用来控制函数的最高次数。(多项式核函数是将低维的输入空间映射到高维的特征空间),这个参数只对多项式核函数有用,是指多项式核函数的阶数 n。如果给的核函数参数是其他核函数,则会自动忽略该参数
gamma 核函数系数,默认是 auto,即特征维度的倒数。核函数系数,只对 rbf poly sigmoid 有效
coef0 核函数常数值( $y = kx + b$ 的b值),只有 polysigmoid 函数有,默认值是0
chache_size 缓冲大小,用来限制计算量大小,默认是200M,如果机器内存大,推荐使用500MB甚至1000MB
kernel 核函数,核函数是用来将非线性问题转化为线性问题的一种方法,默认是“rbf”核函数
  • 常用的核函数有以下几种:

    函数 含义
    linear 线性核函数
    poly 多项式核涵数
    rbf 高斯核函数
    sigmod sigmod 核函数
    precomputed 自定义核函数

SVR

  • 其函数原型如下:
1
2
3
class sklearn.svm.SVC(self, kernel='rbf', degree=3, gamma='auto_deprecated',
coef0=0.0, tol=1e-3, C=1.0, epsilon=0.1, shrinking=True,
cache_size=200, verbose=False, max_iter=-1)
参数说明
  • SVR 和 NuSVR 方法基本一致,唯一区别就是损失函数的度量方式不同(NuSVR 中的 nu 参数和 SVR 中的 C 参数)即 SVR 使用惩罚系数 C 来控制惩罚力度,而 NuSVR 使用 nu 来控制惩罚力度。

SVM的方法与对象

方法

  • 三种分类的方法基本一致:
函数 含义
decision_function(x) 获取数据集X到分离超平面的距离
fit(X , y) 在数据集 $(X,y)$上使用 SVM 模型
get_params([deep]) 获取模型的参数
predict(X) 预测数值型X的标签
score(X,y) 返回给定测试集合对应标签的平均准确率

对象

函数 含义
support_ 以数组的形式返回支持向量的索引
support_vectors_ 返回支持向量
n_support_ 每个类别支持向量的个数
dual_coef 支持向量系数
coef_ 每个特征系数(重要性),只有核函数是 LinearSVC 的是可用,叫权重参数,即 $w$
intercept_ 截距值 (常数值),称为偏置参数,即 $b$

示例代码

  • 示例简单的 svm 训练、测试 demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# import svm
from sklearn import svm

# train data: Feature List
train_data = ...
# test data: Feature List
test_data = ...
# label data: Label List
train_label = ...

# build classifier
predictor = svm.SVC(gamma='scale', C=1.0, decision_function_shape='ovr', kernel='poly',degree=4)

# train
predictor.fit(train_data, train_label)

# test
test_results = predictor.predict(test_data)

参考资料


Sklearn 支持向量机库介绍
https://www.zywvvd.com/notes/study/machine-learning/about-svm/sklearn-svm/python-svm/
作者
Yiwei Zhang
发布于
2022年10月10日
许可协议