机器学习笔记8-支持向量机(3/3)
- scikit-learn中的SVM函数
机器学习库scikit-learn中也集成了SVM的函数,可以方便的进行调用,可用来分类、回归和异常点检测。
支持向量机的优点有:
i)在高维空间效果很好
ii)当维度数大于样本点数时,效果仍然不错
iii)决策函数只取决于数据集中的支持向量,能够减轻内存压力
iv)决策函数中可以选不同的核函数从而实现多种功能。可以使用现有的核函数,也可以自定义核函数。
支持向量机的缺点有:
i)如果特征数量比样本数量多很多,为了避免过拟合,需要谨慎选择核函数和正则化项
ii)SVM不支持概率估计。如果需要概率估计的话,需要通过5折交叉验证的方法。
(1)分类
SVC、NuSVC和LinearSVC都可以用来进行多分类。SVC和NuSVC是类似的方法,只是数学形式不一样,参数设置不一样而已。LinearSVC是专门用来线性分类的,所以没有kernel这个参数。对于这三个分类器,如果想查看支持向量,可查看属性support_vectors_。
对于多分类,SVC和NuSVC默认实行的是“one-against-one”的方法。假设有n个类,就需要有n*(n-1)/2个分类器。其中每一个分类器只会训练两个类的数据。最后用decision_function_shape参数来汇总结果。还有另一种多分类方法:“one-vs-the-rest”方法,这种方法只需要n个分类器。每个分类器会训练一个类+其余类的数据。如果只有两个类,则只需要一个分类器。LinearSVC使用的就是这个方法。from sklearn import svm X = [[0, 0], [1, 1]] y = [0, 1] clf = svm.SVC(gamma='scale') clf.fit(X, y) clf.predict([[2., 2.]]) clf.support_vectors_
(2)回归>>> X = [[0], [1], [2], [3]] >>> Y = [0, 1, 2, 3] >>> clf = svm.SVC(gamma='scale', decision_function_shape='ovo')#decision_function_shape采用的是“1vs1”模式 >>> 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) #kernel是'rbf',因此这个是非线性分类器 >>> dec = clf.decision_function([[1]]) >>> dec.shape[1] # 有四个类,因此需要4*(4-1)/2=6个分类器 6 >>> clf.decision_function_shape = "ovr" #将decision_function_shape改为“1vsR”模式 >>> dec = clf.decision_function([[1]]) >>> dec.shape[1] # 此时四个类就只需要四个分类器 4
支持向量分类可以用来解决回归问题,称为支持向量回归。与支持向量分类类似,支持向量回归也只跟训练数据的一小部分子集有关。不同的地方是分类的输入 y y y是个整数,而回归的输入 y y y是个浮点数。支持向量回归总共包括三个函数:SVR,NuSVR和LinearSVR。
(3)复杂度
SVM的时间复杂度和空间复杂度会随着训练数据的容量增加而迅速增加。SVM的核心是将支持向量从训练数据中分离,这是一个二次规划问题。它的求解利用了libsvm,复杂度在 O ( n f e a t u r e s × n s a m p l e s 2 ) O(n_{features}\times n_{samples}^2) O(nfeatures×nsamples2)和 O ( n f e a t u r e s × n s a m p l e s 3 ) O(n_{features}\times n_{samples}^3) O(nfeatures×nsamples3)之间。但如果是线性的SVM,它的复杂度是 O ( n f e a t u r e s × n s a m p l e s ) O(n_{features}\times n_{samples}) O(nfeatures×nsamples)。
(4)Tips
i)核函数的大小:对于SVC、SVR等,核函数的大小会极大地影响大型数据问题的运行时间。默认的cache_size是200MB,如果内存足够,可以提升到500MB或者1000MB
ii)惩罚参数C:C值的意义可以参看上一节的线性支持向量机。C默认为1。如果数据的噪声很大,应该减小C值。当C值很大时,LinearSVC和LinearSVR会对C值变得不敏感(预测结果也不会再改善)。而且较大的C值会增加训练的时间。
iii)SVM算法不是尺度不变的。所以在用SVM之前,强烈建议将输入数据的每一个特征变换到[0,1]或[-1,1]之间,或将其标准化为均值为零方差为1。对于测试数据也需用到同样的尺度变换。
iv)如果数据是不平衡的(比如很多的正实例点和极少的负实例点),建议设置class_weight=‘balanced’,并尝试设置不同的惩罚参数C值。
v)如果有经验知道数据是线性可以拟合的,那么使用LinearSVC去分类 或者LinearSVR去回归,它们不需要我们去慢慢的调参去选择各种核函数以及对应参数, 速度也快。如果我们对数据分布没有什么经验,一般使用SVC去分类或者SVR去回归,这就需要我们选择核函数以及对核函数调参了。对于分类或回归中,函数其它参数的设置,包括核函数参数degree、核函数参数gamma、核函数参数coef0、 这篇博客有详尽的解释。
以下是利用SVC实现的一小段代码,数据集是sklearn中的内置数据集:
from sklearn.datasets import fetch_olivetti_faces
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.svm import SVC
faces=fetch_olivetti_faces()
x_train,x_test,y_train,y_test=train_test_split(faces['data'],faces['target'],test_size=0.25,random_state=17)
scaler=preprocessing.StandardScaler()
x_train=scaler.fit_transform(x_train)
x_test=scaler.fit_transform(x_test)
svc_linear=SVC(C=0.2,kernel='linear')
svc_linear.fit(x_train,y_train)
y_predict_train=svc_linear.predict(x_train)
y_predict_test=svc_linear.predict(x_test)
from sklearn import metrics
print(metrics.accuracy_score(y_train,y_predict_train))
print(metrics.accuracy_score(y_test,y_predict_test))
参考:
李航《统计学习方法》
https://scikit-learn.org/dev/modules/svm.html
https://www.cnblogs.com/pinard/p/6117515.html