lzx1413's blog

1-4-Support-Vector-Machines

SVMs是一系列用于分类、回归和异常检测的监督学习学习方法的集合。

SVMs的优点如下:

  • 对高维数据空间比较有效
  • 当数据维度多余数据数目的时候仍然有效
  • 在决策函数中仅使用训练数据的一个子集,因此比较节省内存
  • 通用性,决策函数中可以添加不同的核函数,除了提供一些通用的核函数,也可以自己定义核函数。
    SVMs的缺点如下:
  • 如果数据的维度远远多于数据数目,这种方法的效果会可能会很差。
  • SVMs不直接提供概率估计,而是通过复杂的5重交叉验证来进行计算。

sklearn提供支持向量机的稠密和稀疏向量在作为输入,然而,如果使用SVM去对稀疏的数据进行预测,必须首先用稀疏的数据进行训练。

1.4.1 分类

SVC,NuSVCLinearSVC是进行多类别分类的类。

其中SVC和NuSVC的算法相似,但是参数有稍许不同并且使用不同的数学表达式,另外,LinearSVC是线性核函数的支持向量机的另外一种实现,需要注意的是LiearSVC不接受kernel这个参数,因为这个方法默认为线性,同时也缺失一些SVC核NuSVC的参数,例如support_

和其他分类器一样,SVC,NuSVC和LinearSVC的输入参数为两个向量:X[n_samples,n_features]作为训练数据,和一个标签向量,y[n_samples]:

1
2
3
4
5
6
7
8
9
>>> from sklearn import svm
>>> X = [[0, 0], [1, 1]]
>>> y = [0, 1]
>>> clf = svm.SVC()
>>> clf.fit(X, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)

经过训练之后,模型便可以根据输入进行输出预测了:

1
2
>>> clf.predict([[2., 2.]])
array([1])

SVMs 的决策函数使用了训练数据的子集,被称为支持向量。这些支持向量的属性可以在support_vectors_,support_,n_support中查看.

1
2
3
4
5
6
7
8
9
10
>>> # get support vectors
>>> clf.support_vectors_
array([[ 0., 0.],
[ 1., 1.]])
>>> # get indices of support vectors
>>> clf.support_
array([0, 1]...)
>>> # get number of support vectors for each class
>>> clf.n_support_
array([1, 1]...)

1.4.1.1 多类别分类

SVC 和NuSVC 采用 “一对一”的方法来实现多类别分类,如果n_class是类别数目,那么将会生成n_class*(n_class-1)/2个分类器,为了提供一个稳定的接口,可以通过参数decision_function_shape设置这种方式,例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> X = [[0], [1], [2], [3]]
>>> Y = [0, 1, 2, 3]
>>> clf = svm.SVC(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='auto', 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使用“一对多”的多类别分类策略,所以只需要训练n_class个模型,如果只有两个类别,那么只会训练一个模型:

1
2
3
4
5
6
7
8
9
>>> 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

需要注意的是Linear SVM也实现了另外一种可选的多类别分类的策略通过使用multi_class='crammer_dinger'。这是一种稳定的方法,但是不适用于“一对多”的分类方式,在实际应用中,一对多在时间上更加高效,而效果和其他方式差不多。
对于”one-vs-rest”Linear SVC,参数coef_intercept_的大小分别为[n_class,n_features]和[n_class],coefficients的每一行代表每一类相对于其他类的分类器,intercepts的与此相同。

1.4.1.2 得分和概率

SVC 的decision_function对于每条数据一个各类别的得分,如果参数probability设置为True,则会进行概率估计,在二分类例子中,概率将会采用Platt scaling的方式计算:对SVM的结果进行逻辑回归,通过对另外的交叉验证进行参数调整,在多类别分类中,这种方法被拓展为per Wu。

有一点需要注意,Platt scaling中的交叉验证在进行数据量较大的训练时成本很高。另外,概率估计可能随着分数的变化而变化,在这种情况下得分最高的类别概率不一定时最大的。Platt的方法在理论上也有缺陷。如果确实需要置信度而又不必须要得到概率,使用decision_function而不是predict_proba是更好的选择。
参考文献

  • Wu, Lin and Weng, “Probability estimates for multi-class classification by pairwise coupling”. JMLR 5:975-1005, 2004.

1.4.1.3 数据不均衡问题

在这种情况下,我们需要给特定的类别以更大的权重,此时class_weightsample_weight这两个关键词可以使用。
SVC(非NuSVC)在fit函数中又class_weight参数,这是一个字典格式为{class_label:value},value是一个正实数,将会把class_label的参数C变成C*value

SVC,NuSVC,SVR,NuSVR 和OneClassSVM也在fit中实现了对于每个数据的权重参数sample_weight,和class_weight相似,这将会似的第i个数据的参数C变成C*sample_weight[i].

Examplse:

原文地址 http://scikit-learn.org/stable/modules/svm.html