根据菜菜的课程进行整理,方便记忆理解
代码位置如下:
使用SVC时的其他考虑
SVC处理多分类问题:重要参数decision_function_shape
之前所有的SVM内容,全部是基于二分类的情况来说明的,因为支持向量机是天生二分类的模型。不过,它也可以做多分类,但是SVC在多分类情况上的推广,属于恶魔级别的难度,要从数学角度去理解几乎是不可能的,因为要研究透彻多分类状况下的SVC,就必须研究透彻多分类时所需要的决策边界个数,每个决策边界所需要的支持向量的个数,以及这些支持向量如何组合起来计算我们的拉格朗日乘数,要求我们必须对SMO或者梯度下降求解SVC的拉格朗日乘数的过程十分熟悉。这些内容推广到多分类之后,即便在线性可分的二维数据上都已经复杂,要再推广到非线性可分的高维情况,就远远超出了想象。
sklearn中用了许多巧妙的方法来为我们呈现结果,在这里,这一小节会为大家简单介绍sklearn当中是如何SVC的多分类问题的。
支持向量机是天在生二分类的模型,所以支持向量机在处理多分类问题的时候,是把多分类问题转换成了二分类问题来解决。这种转换有两种模式,
- “一对一”模式(one vs one)
- “一对多”模式(one vs rest)
在ovo模式下,标签中的所有类别会被两两组合,每两个类别之间建一个SVC模型,每个模型生成一个决策边界,分别进行二分类。这种模式下,对于含有n_class个标签类别的数据来说,SVC会生成总共个模型,即会生成总共个超平面,其中:
比如说,来看ovo模式下,二维空间中的三分类情况。
首先让提出紫色点和红色点作为一组,然后求解出两个类之间的SVC和绿色决策边界。然后让绿色点和红色点作为一组,求解出两个类之间的SVC和灰色边界。最后让绿色和紫色组成一组,组成两个类之间的SVC和黄色边界。然后基于三个边界,分别对三个类别进行分类。
在ovr模式下,标签中所有的类别会分别与其他类别进行组合,建立n_class个模型,每个模型生成一个决策边界,分别进行二分类。同样的数据集,如果是ovr模式,则会生成如下的决策边界:
紫色类 vs 剩下的类,生成绿色的决策边界。红色类 vs 剩下的类,生成黄色的决策边界。绿色类 vs 剩下的类,生成灰色的决策边界,当类别更多的时候,如此类推下去,我们永远需要n_class个模型。
当类别更多的时候,无论是ovr还是ovo模式需要的决策边界都会越来越多,模型也会越来越复杂,不过ovo模式下的模型计算会更加复杂,因为ovo模式中的决策边界数量增加更快,但相对的,ovo模型也会更加精确。ovr模型计算更快,但是效果往往不是很好。在硬件可以支持的情况下,还是建议选择ovo模式。
一旦模型和超平面的数量变化了,SVC的很多计算过程,还有接口和属性都会发生变化:
- 在二分类中,所有的支持向量都服务于唯一的超平面,在多分类问题中,每个支持向量都会被用来服务于多个个超平面
- 在生成一个超平面的二分类过程中,我们计算一个超平面上的支持向量对应的拉格朗日乘数,现在,由于有多个超平面,所以需要的支持向量的个数增长了,因而求解拉格朗日乘数的需求也变得更多。在二分类问题中,每一个支持向量求解出一个拉格朗日乘数,因此拉格朗日乘数的数目和支持向量的数一致。但在多分类问题中,两个不同超平面的支持向量被用来决定一个拉格朗日乘数的取值,并且规定一个支持向量至少要被两个超平面使用。假设一个多分类问题中分别有三个超平面,超平面A上有3个支持向量,超平面B和C上分别有2个支持向量,则总共7个支持向量就需要求解14个对应的拉格朗日乘数。以这样的考虑来看,拉格朗日乘数的计算也会变得异常复杂。
- 在简单二分类中,decision_function只返回每个样本点到唯一的超平面的距离,而在多分类问题中这个接口将根据选择的多分类模式不同而返回不同的结构。
- 同理,在二分类中只生成一条直线,所以属性coef_和intercept_返回的结构都很单纯,但在多分类问题,尤其是ovo类型下,两个属性都受到不同程度的影响。
参数decision_function_shape决定我们究竟使用哪一种分类模式。
decision_function_shape 可输入“ovo","ovr",默认”ovr",对所有分类器,选择使用ovo或者ovr模式。
选择ovr模式,则返回的decision_function结构为(n_samples,n_class)。二分类时,尽管选用ovr模式,却会返回(n_samples,)的结构。
选择ovo模式,则使用libsvm中原始的,结构为(n_samples, )的decision_function接口。在ovo模式并且核函数为线性核的情况下,属性coef_和intercept\会分别返回( ,n_samples)和( ,)的结构,每行对应一个生成的二元分类器。 ovo模式只在多分类的状况下使用。
SVM的模型复杂度
支持向量机是强大的工具,但随着训练向量的数量的增大,它对的计算和存储的需求迅速增加。SVM的核心是二次规划问题(QP),将支持向量与其余训练数据分开。这个基于libsvm的实现使用的QP解算器可以在实践中实现到之间的复杂度,一切基于libsvm的缓存在实践中的效率有多高。这个效率由数据集确定。如果数据集非常稀疏,在应该将时间复杂度中的替换为样本向量中非零特征的平均个数。注意,如果数据是线性的,使用类LinearSVC比使用SVC中的核函数"linear"要更有效,而且LinearSVC可以几乎线性地拓展到数百万个样本或特征的数据集上。
SVM中的随机性:参数random_state
虽然不常用,但是SVC中包含参数random_state,这个参数受到probability参数的影响,仅在生辰高概率估计的时候才会生效。在概率估计中,SVC使用随机数生成器来混合数据。如果概率设置为False,则random_state对结果没有影响。如果不实现概率估计,SVM中不存在有随机性的过程。
SVC的重要属性补充
到目前为止,SVC的几乎所有重要参数,属性和接口我们都已经介绍完毕了。在这里,给大家做一个查缺补漏:
#属性n_support_:调用每个类别下的支持向量的数目
clf_proba.n_support_
#属性coef_:每个特征的重要性,这个系数仅仅适合于线性核
clf_proba.coef_
#属性intercept_:查看生成的决策边界的截距
clf_proba.intercept_
#属性dual_coef_:查看生成的拉格朗日乘数
clf_proba.dual_coef_
"""
array([[-1. , -1. , -1. , -1. , -1. ,
-1. , -1. , -1. , -1. , -1. ,
-1. , -1. , -1. , -1. , -1. ,
-1. , -1. , -1. , -1. , -1. ,
-1. , -1. , -1. , -1. , -0.50312301,
-1. , -1. , -1. , -1. , -1. ,
-1. , -1. , -1. , -1. , -1. ,
-1. , -1. , -1. , -1. , -1. ,
-1. , -0.25015141, 0.75327442, 1. , 1. ,
1. , 1. , 1. , 1. , 1. ,
1. , 1. , 1. , 1. , 1. ,
1. , 1. , 1. , 1. , 1. ,
1. , 1. , 1. , 1. , 1. ,
1. , 1. , 1. , 1. , 1. ,
1. , 1. , 1. , 1. , 1. ,
1. , 1. , 1. , 1. , 1. ,
1. , 1. , 1. ]])
"""
clf_proba.dual_coef_.shape
# (1, 83)
#注意到这个属性的结构了吗?来看看查看支持向量的属性
clf_proba.support_vectors_
clf_proba.support_vectors_.shape
# (83, 2)
#注意到dual_coef_中生成的拉格朗日乘数的数目和我们的支持向量的数目一致
#注意到KKT条件的条件中的第五条,所有非支持向量会让拉格朗日乘数为0
#所以拉格朗日乘数的数目和支持向量的数目是一致的
#注意,此情况仅仅在二分类中适用!
线性支持向量机类LinearSVC
到这里,我们基本上已经了解完毕了SVC在sklearn中的使用状况。当然,还有很多可以深入的东西,大家如果感兴趣可以自己深入研究。除了最常见的SVC类之外,还有一个重要的类可以使用:线性支持向量机linearSVC。
class sklearn.svm.LinearSVC (
penalty=’l2’,loss=’squared_hinge’, dual=True,tol=0.0001,C=1.0,multi_class=’ovr’,fit_intercept=True, intercept_scaling=1, class_weight=None, verbose=0, random_state=None, max_iter=1000)
线性支持向量机其实与SVC类中选择"linear"作为核函数的功能类似,但是其背后的实现库是liblinear而不是libsvm,这使得在线性数据上,linearSVC的运行速度比SVC中的“linear”核函数要快,不过两者的运行结果相似。在现实中,许多数据都是线性的,因此我们可以依赖计算得更快得LinearSVC类。除此之外,线性支持向量可以很容易地推广到大样本上,还可以支持稀疏矩阵,多分类中也支持ovr方案。线性支持向量机的许多参数看起来和逻辑回归非常类似,比如可以选择惩罚项,可以选择损失函数等等,这让它在线性数据上表现更加灵活。
| 参数 | 含义 |
|---|---|
| penalty | 在求解决策边界过程中使用的正则惩罚项,可以输入"l1"或者"l2",默认"l2" 和逻辑回归中地正则惩罚项非常类似,"l1"会让决策边界中部分特征的系数w被压缩到0, 而"l2"会让每个特征都被分配到一个不为0的系数 |
| loss | 在求解决策边界过程中使用的损失函数,可以输入"hinge"或者“squared_hinge”,默认 为“square_hinge” 当输入“hinge",表示默认使用和类SVC中一致的损失函数,使用”squared_hinge“表示使用SVC中 损失函数的平方作为损失函数。 |
| dual | 布尔值,默认为True 选择让算法直接求解原始的拉格朗日函数,或者求解对偶函数。当选择为True的时候,表示求解 对偶函数,如果样本量大于特征数目,建议求解原始拉格朗日函数,设定dual = False。 |
和SVC一样,LinearSVC也有C这个惩罚参数,但LinearSVC在C变大时对C不太敏感,并且在某个阈值之后就不能再改善结果了。同时,较大的C值将需要更多的时间进行训练,2008年时有人做过实验,LinearSVC在C很大的时候训练时间可以比原来长10倍。