支持向量机SVM
2.1 SVM介绍及基础理论
支持向量机SVM:support vector machine
支持向量机本质就是找出最佳分割线。
最佳分割线(间隔)的特点:使得间隔距离平均、最大化。
最佳分割线可以减小分类的误差,确保结果的准确性。
SVM首先保证分类正确,然后对间隔最大化。
SVM应该能够处理异常值。
2.2 SVM算法使用示例
>>> from sklearn import svm >>> X = [[0, 0], [1, 1]] >>> y = [0, 1] >>> clf = svm.SVC() >>> clf.fit(X, y) >>> clf.predict([[2., 2.]])
过程:导入、创建、拟合、预测。
from sklearn.svm import SVC clf = SVC(kernel="linear") clf.fit(features_train,labels_train) pred=clf.predict(features_test) sco=clf.score(features_test,labels_test) print sco
2.3 非线性SVM
当分割线为非线性决策面时,确定核函数显得尤为重要,SVC有各种各样的核函数。
核函数类型:核函数设置类型有四种(默认为rbf函数),可以是‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’
0 –线性:u'v
1 –多项式:(r*u'v + coef0)^degree
2 – RBF函数:exp(-gamma|u-v|^2)
3 –sigmoid:tanh(r*u'v + coef0)
2.4 SVM的参数
机器学习中的参数:参数是你在创建分类器时要传递的自变量,这发生在拟合之前,这些参数可以对算法所达到的决策边界产生巨大影响。
SVM主要参数有哪些:
- 核kernel:有linear、rbf等
- C:控制光滑决策边界(误差项:惩罚参数)
C参数越大,分界越光滑,正确率越高。
3.r(gamma):当核参数为‘rbf’,‘poly’ 和‘sigmoid’时,r参数可用
默认是’auto’,则会选择1/n_features
2.5 过拟合
过拟合:使决策边界变得过度复杂(本可以通过简单的决策边界进行分类)
机器学习过程中,一定要避免过度拟合。
综合控制“核kernel”、C、r这三个参数,可以控制过度拟合的参数。
2.6 SVM的优缺点
优点:SVM在复杂领域、有明显分隔边界的情况下,表现十分出色。
缺点:海量数据集时训练时间过多、噪音过多的情况下可能导致过度拟合。
可以考虑使用朴素贝叶斯更有效。
因此,需要我们队数据集和可用特征进行测试。
2.7 SVM练习一
练习介绍:
部分1:根据邮件文本使用的单词,辨别邮件的作者是谁
部分2:进一步研究SVM的参数,看看如何通过调节参数,缩短支持向量机的训练时间或预测时间,以及对准确度有什么影响?
转到 svm 目录,查找初始代码 (svm/svm_author_id.py)(此为附件)。
使用 sklearn SVC 分类器进行导入、创建、训练和预测。在创建分类器时使用线性内核(如果你忘记此步骤,你会发现分类器要花很长的时间来训练)。分类器的准确率是多少?运行时间如何?
from sklearn.svm import SVC clf=SVC(kernel="linear") clf.fit(features_train,labels_train) pred=clf.predict(features_test) sco=clf.score(features_test,labels_test) print sco
1.使用线性核函数
training time: 239.453 s
predicting time: 25.417 s
准确度为0.984072810011
可以看出,SVM准确度高于naive_bayes,但处理时长明显也多。
2.不使用linear核函数
不使用linear核函数,默认使用rbf
运行时间长到你怀疑人生,嗯,果断放弃了。
2.8 SVM练习二
加快算法速度的一种方式是在一个较小的训练数据集上训练它。这样做换来的是准确率几乎肯定会下降。让我们更具体地探讨这个问题:在训练分类器之前,立即加入以下两行。
features_train = features_train[:len(features_train)/100]
labels_train = labels_train[:len(labels_train)/100]
这两行有效地将训练数据集切割至原始大小的 1%,丢弃掉 99% 的训练数据。
training time: 0.137 s
predicting time: 1.475 s
0.884527872582
可以看出,我们用牺牲准确率的方式换取了算法运行速度。很多场景下,非常快速地运行的算法尤其重要:比如,标记信用卡欺诈,在欺诈发生之前阻止交易;Siri 之类的语音识别等。
依然在将训练数据集切割至原始大小的 1%,丢弃掉 99% 的训练数据。使用rbf内核函数,我们得到的准确率更低,但算法运行时间显著提高了(但仍比linear慢一点)。
training time: 0.154 s
predicting time: 1.667 s
0.616040955631
保持训练集大小不变,并且保留上一个测试题中的 rbf 内核,但是尝试多个 C 值(比如:10.0、100.、1000. 和 10000.)。
当 C=10:
training time: 0.158 s
predicting time: 1.69 s
0.616040955631
当 C=100:
training time: 0.153 s
predicting time: 1.666 s
0.616040955631
当 C=1000:
training time: 0.148 s
predicting time: 1.637 s
0.821387940842
当 C=10000:
training time: 0.149 s
predicting time: 1.354 s
0.892491467577
经试验可以看出,当核函数给定brf,数据集大小给定时,C参数设置越大,算法运行速度越快,准确度也越高。
恢复完整训练集后,此时的准确率有:
training time: 160.568 s
predicting time: 16.178 s
0.990898748578
此时,我们看到准确率很高,超过linear核函数、naive_bayes
2.9 SVM练习三
你的 SVM(0 或 1,分别对应 Sara 和 Chris)将测试集中的元素 10 预测为哪一类?元素 26 ?还是元素 50 ?
(使用 RBF 内核、C=10000 和 1% 的训练集。通常,使用完整的训练集能获得最好的结果,但是我们发现使用 1% 的完整训练集不仅大幅加快计算过程,而且不会改变我们的结果,因此你在这里可以随意使用该快捷算法。)
而且需要说明的是,我们这里给出的数据点数字 (10, 26, 50) 假设使用的是零索引列表。因此,使用类似于 answer=predictions[100] 的表达式可找到元素 # 100 的正确答案。
print clf.predict(features_test[10]) print clf.predict(features_test[26]) print clf.predict(features_test[50])
分别得到答案1,0,1
2.10 SVM练习四
预测有多少 Chris 的邮件?
测试事件的数量超过 1700——其中多少预测在“Chris” (1) 类中?(使用 RBF 内核、C=10000. 以及完整的训练集。)
print "no. of Chris predicting emails:", sum(clf.predict(features_test)) print "no. of Sara predicting emails:", len(clf.predict(features_test))-sum(clf.predict(features_test))
no. of Chris predicting emails: 877
no. of Sara predicting emails: 881
2.11 小节
朴素贝叶斯非常适合文本时,对于这一具体问题,朴素贝叶斯不仅更快,而且通常比 SVM 更出色。当然,SVM 更适合许多其他问题。你在第一次求解问题时就知道该尝试各个算法,这是机器学习艺术和科学性的一个体现。除了选择算法外,视你尝试的算法而定,你还需要考虑相应的参数调整以及过拟合的可能性(特别是在你没有大量训练数据的情况下)。调整参数的工作量很大,之后,将介绍 GridCV,一种几乎能自动查找最优参数调整的优秀 sklearn 工具。