文章目录
- 1. 分类
- 1.1. 多元分类
支持向量机(SVMs) 可用于以下监督学习算法: 分类、回归和异常检测。
支持向量机的优势在于:
- 在高维空间中非常高效
- 即使在数据维度比样本数量大的情况下仍然有效
- 在决策函数(称为支持向量)中使用训练集的子集,因此它也是高效利用内存的
- 通用性: 不同的核函数与特定的决策函数一一对应。常见的
kernel
已经提供,也可以指定定制的内核
支持向量机的缺点包括:
- 如果特征数量比样本数量大得多,在选择核函数时要避免过拟合,而且正则化项是非常重要的。
- 支持向量机不直接提供概率估计,这些都是使用五次交叉验算计算的(详情见 得分和概率)。
在 scikit-learn 中,支持向量机提供 dense
(numpy.ndarray
,可以通过 numpy.asarray
进行转换) 和 sparse
(任何 scipy.sparse
) 样例向量作为输出。然而,要使用支持向量机来对 sparse
数据作预测,它必须已经拟合这样的数据。使用行优先存储(C-order)的 numpy.ndarray
(dense) 或者带有 dtype=float64
的 scipy.sparse.csr_matrix
(sparse) 来优化性能。
1. 分类
SVC
、NuSVC
和 LinearSVC
能在数据集中实现多元分类。
SVC
和 NuSVC
是相似的方法,但是接受稍许不同的参数设置并且有不同的数学方程(在这部分看 数学公式)。另一方面,LinearSVC
是另一个实现线性核函数的支持向量分类。记住 LinearSVC
不接受关键词 kernel
, 因为它被假设为线性的。它也缺少一些 SVC
和 NuSVC
的成员(members) 比如 support_
.
和其他分类器一样,SVC
、NuSVC
和 LinearSVC
将两个数组作为输入: [n_samples, n_features]
大小的数组 X
作为训练样本,[n_samples]
大小的数组 y
作为类别标签(字符串或者整数):
>>> from sklearn import svm
>>> X = [[0, 0], [1, 1]]
>>> y = [0, 1]
>>> clf = svm.SVC(gamma='scale')
>>> clf.fit(X, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='scale', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
在拟合后,这个模型可以用来预测新的值:
>>> clf.predict([[2., 2.]])
array([1])
SVMs 决策函数取决于训练集的一些子集,称作支持向量。这些支持向量的部分特性可以在 support_vectors_
, support_
和 n_support
找到:
>>> # 获得支持向量
>>> clf.support_vectors_
array([[ 0., 0.],
[ 1., 1.]])
>>> # 获得支持向量的索引
>>> clf.support_
array([0, 1]...)
>>> # 为每一个类别获得支持向量的数量
>>> clf.n_support_
array([1, 1]...)
1.1. 多元分类
SVC
和 NuSVC
为多元分类实现了 one-against-one
的方法 (Knerr et al., 1990)。如果 n_class
是类别的数量,那么 n_class * (n_class - 1) / 2
分类器被重构,而且每一个从两个类别中训练数据。为了提供与其他分类器一致的接口,decision_function_shape
选项允许聚合 one-against-one
分类器的结果成 (n_samples, n_classes)
的大小到决策函数:
>>> X = [[0], [1], [2], [3]]
>>> Y = [0, 1, 2, 3]
>>> clf = svm.SVC(gamma='scale', decision_function_shape='ovo')
>>> clf.fit(X, Y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovo', degree=3, gamma='scale', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
>>> dec = clf.decision_function([[1]])
>>> dec.shape[1] # 4 classes: 4*3/2 = 6
6
>>> clf.decision_function_shape = "ovr"
>>> dec = clf.decision_function([[1]])
>>> dec.shape[1] # 4 classes
4
另一方面,LinearSVC
实现 one-vs-the-rest
多类别策略,从而训练 n
类别的模型。如果只有两类,只训练一个模型:
>>> lin_clf = svm.LinearSVC()
>>> lin_clf.fit(X, Y)
LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
intercept_scaling=1, loss='squared_hinge', max_iter=1000,
multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,
verbose=0)
>>> dec = lin_clf.decision_function([[1]])
>>> dec.shape[1]
4
参见 数学公式 查看决策函数的完整描述。
记住 LinearSVC
也实现了可选择的多类别策略,通过使用选项 multi_class='crammer_singer'
,所谓的多元 SVM
由 Crammer 和 Singer 明确表达。这个方法是一致的,对于 one-vs-rest
是不正确的。实际上,one-vs-rest
分类通常受到青睐,因为结果大多数是相似的,但是运行时间却显著减少。
对于 one-vs-rest
LinearSVC
,属性 coef_
和 intercept_
分别具有 [n_class, n_features]
和 [n_class]
尺寸。系数的每一行符合 n_class
的许多 one-vs-rest
分类器之一,并且就以这一类的顺序与拦截器(intercepts)相似。
至于 one-vs-one SVC,属性特征的布局(layout)有少多些复杂。考虑到有一种线性核函数,coef_
和 intercept_
的布局(layout)与上文描述成 LinearSVC
相似,除了 coef_
的形状 [n_class * (n_class - 1) / 2, n_features]
,与许多二元的分类器相似。0
到 n
的类别顺序是 “0 vs 1”, “0 vs 2” , … “0 vs n”, “1 vs 2”, “1 vs 3”, “1 vs n”, … “n-1 vs n”。
dual_coef_
的形状是 [n_class-1, n_SV]
,这个结构有些难以理解。对应于支持向量的列与 n_class * (n_class - 1) / 2
“one-vs-one” 分类器相关。每一个支持向量用于 n_class - 1
分类器中。对于这些分类器,每一行的 n_class - 1
条目对应于对偶系数(dual coefficients)。
通过这个例子更容易说明:
考虑一个三类的问题,类0有三个支持向量 ,而类 1
和 2
分别有 如下两个支持向量 和 。对于每个支持 向量 ,有两个对偶系数。在类别 和 中, 我们将支持向量的系数记录为 那么 dual_coef_
可以表示为: