机器学习训练营——机器学习爱好者的自由交流空间(qq 群号:696721295)
支持向量机(Support Vector Machines, 简称SVM)是一套有监督学习的方法集,经常用于分类、回归和异常点检测。SVM的优势主要体现在:
在高维空间很有效;
在特征数超过样本数的情况下仍然是有效的;
在决策函数里使用了一个训练点子集,因此存储也是有效的;
在决策函数里可以使用不同的核函数。
SVM的劣势包括:
如果特征数远超样本数,为了避免过度拟合(over-fitting), 核函数和正则项的选择至关重要;
SVM不直接提供概率估计,而是使用5倍交叉验证来计算它们。
在scikit-learn里,SVM支持稠密的样本(numpy.ndarray, numpy.asarray)和稀疏的样本(scipy.sparse)作为输入向量。然而,为了使用SVM预测稀疏数据,必须在稀疏数据上作拟合。这样,为了最佳的表现,使用numpy.ndarray模块(稠密样本)、或者scipy.sparse.csr_matrix、参数dtype=float64模块(稀疏样本)。
分类
类SVC
, NuSVC
, LinearSVC
能够在一个数据集上作多类别的分类问题。
支持向量分类执行类。请注意,LinearSVC不接受关键词kernel, 因为它被假设是线性的。LinearSVC也没有像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()
clf.fit(X, y)
拟合后的模型可以用来预测新值。
clf.predict([[2., 2.]])
SVM决策函数依赖于训练数据的子集,这个子集称支持向量。这些支持向量的属性能在成员函数support_vectors_, support_ and n_support里找到。
# get support vectors
clf.support_vectors_
# get indices of support vectors
clf.support_
# get number of support vectors for each class
clf.n_support_
多类别分类
对于多类别的分类问题,类SVC, NuSVC执行一个one-against-one
方法。如果参数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(decision_function_shape='ovo')
clf.fit(X, Y)
```{python}
dec = clf.decision_function([[1]])
dec.shape[1] # 4 classes: 4*3/2 = 6
clf.decision_function_shape = "ovr"
dec = clf.decision_function([[1]])
dec.shape[1] # 4 classes
另一方面,LinearSVC
执行“one-vs-the-rest”多类别策略,这样训练n_class模型。如果仅有两个类,那么只有一个模型被训练。
lin_clf = svm.LinearSVC()
lin_clf.fit(X, Y)
dec = lin_clf.decision_function([[1]])
dec.shape[1]
注意到LinearSVC也能执行多类策略,通过设置参数multi_class='crammer_singer'
.在实际应用中,one-vs-rest分类通常是首选,虽然结果近似,但运行时间要快得多。
对于“one-vs-rest”, LinearSVC属性coef_
, intercept_
各自有形状[n_class, n_features]
, [n_class]
. 系数的每一行对应很多“one-vs-rest”分类器n_class之一,而常数项相似。
在“one-vs-one” SVC
的例子里,属性的表示方式有点复杂。在有一个线性核的情况下,coef_, intercept_与上述的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项对应这些分类器的双重系数。举个例子说明:
考虑一个三类的分类问题。类0有3个支持向量
, 类1, 类2各有2个支持向量
,
. 对于每一个支持向量
, 都有两个双重系数。在分类器里,我们记在类
,
之间的支持向量
的系数为
, 那么dual_coef_
看起来像下面这样:
SVC方法decision_function
对每个样本给出属于每个类的分数(per-class scores). 当构造器参数probability
的值设置为True
时,能够得到类成员的概率估计(来自方法predict_proba
, predict_log_proba
)。在二值分类的情况下,概率进一步由Platt scaling校正。Platt scaling校正,是在SVM分数上使用logistic回归,经训练集上的交叉验证拟合。对于大数据集,我们知道交叉验证是很费时的,可以用置信分数代替,建议设置probability=False
, 使用decision_function
代替predict_proba
.
不平衡问题
在有的分类问题里,如果想要重视某些特殊的类,或者是样本,可以使用关键词class_weight
, sample_weight
. SVC在fit方法里执行class_weight, 它是一个{class_label : value}形式的字典,其中的value是一个大于0的浮点数,设置类class_label的参数C为C * value. 分类结果如下图所示:
SVC, NuSVC, SVR, NuSVR and OneClassSVM也在fit方法里通过关键词sample_weight对样本加权。类似class_weight, 它们设置第i个例子的参数C为C * sample_weight[i].
阅读更多精彩内容,请关注微信公众号:统计学习与大数据