supporter vector machines
支持向量机所做的是去寻找分割线/hyperplane(超平面),即介于两个类别的数据之间
支持向量机通过采用数据作为输入,然后输出一条线,来将数据分类
好的分隔线
将两个数据集的间隔最大化,这样的线不容易出现分类误差
a line that maximizes the distance to the nearest points in either class
the distance is often called margin
the margin is the distance between the line and the nearest point of either of the two classes.
the inside of support vector machine is to maxmize robustness of your result
对于支持向量机,必须尽力确保分类正确,在此条件下,对间隔进行最大化
对于支持向量机来说,有时可能无法正确完成工作
在上图中,显然不存在能将两个类进行分割的决策面,可以把下面的点看作异常值
如果SVM找不到决策面,那么it will do the best it can
直接把异常值的标在另一边,支持向量机找到使两个数据集间距最大化的决策边界,同时默许单个异常值
from sklearn import svm
X=[[0,0],[1,1]] #training features
y=[0,1] #training labels
clf = svm.SVC() #创建分类器
clf.fit(X,y)
clf.predict([[2,2]]) #让分类器进行预测
基本上所有的分类器都遵循这一模式,即
导入、创建、拟合、预测
相对朴素贝叶斯,SVMs的决策边界是直的
SVM编码
import sys
from class_vis import prettyPicture
from prep_terrain_data import makeTerrainData
import matplotlib.pyplot as plt
import copy
import numpy as np
import pylab as pl
features_train, labels_train, features_test, labels_test = makeTerrainData()
from sklearn.svm import SVC
clf = SVC(kernel="linear")
clf.fit(features_train,labels_train)
pred = clf.predict(features_test)
from sklearn.metrics import accuracy_score
acc = accuracy_score(pred, labels_test)
def submitAccuracy():
return acc
非线性SVM
SVM是基于线性分隔的分类器,但SVM分类器也可以形成一些形状非常复杂的决策边界
SVM中会进行特征转换,这会改变你对“线性可分”数据的看法。
如果我们的支持向量机学习了x²+y²的类,我们将该新特征称为z,即z=x²+y²,z代表数据点到原点的距离,我们尝试学习x,y,z之间的超平面,在新的x,z的坐标轴中显示完全相同的数据,舍弃y,我们把数据映射到带有z的新坐标中,那么我们发现所有红点的z值都很小,而所有蓝点的z值都很大。
在新坐标中,这些数据点是线性可分的,并且
xz坐标中的直线对应 xy坐标中的一个圆,其圆心为坐标原点
因此由于我们添加了一个新的特征,z=x²+y²,我们就能够使支持向量机以圆的形式学习非线性决策面
总结:添加一个新的非线性特征,可以使支持向量机以线性的方式将两类数据分隔开
kernel trick
kernel are functions that take a low dimensional input space or feature space,and map it to a very high dimensional space ,so that what's used to be not linear separable turned into a separable problem.
when you apply the kernal trick to change your input space from x,y to a much larger input space ,separate the data point using support vector machines,and then take the solution and go back to the original space,you now have a non linear separation,and this is the really cool thing about support vector machines
you can take a very simple idea of finding the best linear separator,or linear line between different classes,apply the kernel trick in a higher dimensional space,and what you effectively get is a very powerful system to set data sets apart where the division line might be nonlinear
different kernel functions can be specified for the decision function,so there is common kernels that i can use straight out of the box,and there is also the option for custom kernels.
support vector classifier:
sklearn.svm.SVC
kernel : string, optional (default=’rbf’)
Specifies the kernel type to be used in the algorithm. It must be one of ‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’ or a callable. If none is given, ‘rbf’ will be used. If a callable is given it is used to pre-compute the kernel matrix from data matrices; that matrix should be an array of shape (n_samples, n_samples).
参数
参数是你在创建分类器时要传递的自变量,it is before fitting 它们可以对你的算法所达到的决策边界产生巨大的影响
SVM的参数
1.kernel
2.C
controls of trade off between smooth decision boundary and classifying training points correctly
a larger C means you are going to get more training points correctly ,so what that means in practice is that you get the more intricate decision boundaries with the larger values of C ,where it can wiggle around individual data points to try to get everything correct
3.γ 伽马
over fitting 过度拟合
机器学习中的常见现象
如果处理数据太过直接,就会出现这样的现象
在机器学习中,我们要避免过度拟合
控制过度拟合的方法之一就是通过算法中的参数
1.kernel
2.C
3.γ 伽马
这三个参数均会影响SVM的过度拟合的可能性
当我们有测试集时,我们还可以学习自动检测
在拥有明显分割边界的复杂领域中,支持向量机表现得很好
但在海量数据中,表现得不好,因为在这种规模的数据集中,训练时间将是立方级别的
此外在噪音过多的情况下,效果也不好
如果类重重叠叠,你需要考虑independent evidence,这时候朴素贝叶斯更有效
因此最终我们根据我们拥有的数据和可用特征来选择算法
海量数据,很多可用特征→运行SVM会很慢
数据的噪音→导致过度拟合
所以我们会在测试机集上进行测试,看它们的表现
SVM迷你项目
1.根据邮件文本使用的单词辨认邮件的作者是谁
2.研究支持向量机的参数
使用参数来缩短支持向量机的训练时间和预测时间,以及参数对支持向量机的准确度有什么影响
SVM 作者 ID 准确率
转到 svm 目录,查找初始代码 (svm/svm_author_id.py)。
使用 sklearn SVC 分类器进行导入、创建、训练和预测。在创建分类器时使用线性内核(如果你忘记此步骤,你会发现分类器要花很长的时间来训练)。
分类器的准确率是多少?
#!/usr/bin/python
import sys
from time import time
sys.path.append("../tools/")
from email_preprocess import preprocess
### features_train and features_test are the features for the training
### and testing datasets, respectively
### labels_train and labels_test are the corresponding item labels
features_train, features_test, labels_train, labels_test = preprocess()
#########################################################
### your code goes here ###
from sklearn.svm import SVC
clf = SVC(kernel='linear')
t0 = time()
clf.fit(features_train,labels_train)
print 'training time',round(time()-t0,3),'s'
t0 = time()
pred = clf.predict(features_test)
print 'predicting time',round(time()-t0,3),'s'
from sklearn.metrics import accuracy_score
acc = accuracy_score(pred,labels_test)
print acc
#########################################################
SVM 作者 ID 时间
将计时代码用于拟合和预测函数。与朴素贝叶斯相比,训练和预测如何计时?
t0 = time()
clf.fit(features_train,labels_train)
print 'training time',round(time()-t0,3),'s'
t0 = time()
pred = clf.predict(features_test)
print 'predicting time',round(time()-t0,3),'s'
更小的训练集
加快算法速度的一种方式是在一个较小的训练数据集上训练它。这样做换来的是准确率几乎肯定会下降。让我们更具体地探讨这个问题:在训练分类器之前,立即加入以下两行。
features_train = features_train[:len(features_train)/100]
labels_train = labels_train[:len(labels_train)/100]
这两行有效地将训练数据集切割至原始大小的 1%,丢弃掉 99% 的训练数据。你可以使其他所有代码保持不变。
现在的准确率是多少?
权衡速度与准确率
如果速度是一个主要考虑因素(对于许多实时机器学习应用而言确实如此),并且如果牺牲一些准确率可加快你的训练/预测速度,则你可能会想这样做。
在以下哪些应用中,你可以想象非常快速地运行的算法尤其重要?
- 预测电子邮件作者
- 标记信用卡欺诈,在欺诈发生之前阻止交易
- Siri 之类的语音识别
Voice recognition and transaction blocking need to happen in real time, with almost no delay. There's no obvious need to predict an email author instantly.
部署rbf内核
保留上一个测试题中的训练集代码段,以便仍在 1% 的完整训练集上进行训练。将 SVM 的内核更改为“rbf”。
这个更复杂的内核给出的准确率是多少?
优化 C 参数
保持训练集大小不变,并且保留上一个测试题中的 rbf 内核,但是尝试多个 C 值(比如:10.0、100.、1000. 和 10000.)。
哪个给出的准确率最高?
clf = SVC(kernel='rbf',C=10000)
优化后的 RBF 与线性 SVM:准确率
你已经为 RBF 内核优化了 C,现在恢复为使用完整的训练集。较大的训练集往往能提高算法的性能,所以(通过在大数据集上调整 C 和进行训练)我们应得到相当优化的结果。
经过优化的 SVM 的准确率是多少?
从 SVM 提取预测
what class dose your SVM(0 or 1 corresponding to sara and chris respectively) predict for element 10 of the test set? the 26th? the 50th?
(使用 RBF 内核、C=10000 和 1% 的训练集。通常,使用完整的训练集能获得最好的结果,但是我们发现使用 1% 的完整训练集不仅大幅加快计算过程,而且不会改变我们的结果,因此你在这里可以随意使用该快捷算法。)
而且需要说明的是,我们这里给出的数据点数字 (10, 26, 50) 假设使用的是零索引列表。因此,使用类似于 answer=predictions[100] 的表达式可找到元素 # 100 的正确答案。
answer_one = pred[10]
print answer_one
answer_two = pred[26]
print answer_two
answer_three = pred[50]
print answer_three
预测有多少 Chris 的邮件?
There are over 1700 test events--how many are predicted to be in the “Chris” (1) class? (Use the RBF kernel, C=10000., and the full training set.)
pred支持[]操作,但pred不能像list那样使用count()函数,所以pred是一个类似于数组的类型,但不支持count()操作。使用print(type(pred))查看,发现pred属于numpy.ndarray类型。
所以应该将pred转换成一个list然后使用list的count()函数计算其中1的数量
方法一:
def count_chris(pred):
num=0
for item in pred :
if item==1:
num +=1
return num
print count_chris(pred)
方法二:
print pred.tolist().count(1)
方法三:
print list(pred).count(1)
方法四:
import numpy as np
print np.bincount(pred)[1]
部署 SVM 最后提醒
朴素贝叶斯非常适合文本。对于这一具体问题,朴素贝叶斯不仅更快,而且通常比 SVM 更出色。当然,SVM 更适合许多其他问题。你在第一次求解问题时就知道该尝试哪个算法,这是机器学习艺术和科学性的一个体现。除了选择算法外,视你尝试的算法而定,你还需要考虑相应的参数调整以及过拟合的可能性(特别是在你没有大量训练数据的情况下)。
我们通常建议你尝试一些不同的算法来求解每个问题。调整参数的工作量很大,但你现在只需要听完这堂课,我们将向你介绍 GridCV,一种几乎能自动查找最优参数调整的优秀 sklearn 工具。