
1. 问题
支持向量机(Support Vector Machines)是当下最流行的机器学习算法之一,今天我们一起来了解下,并来个实战。
2. 分析
支持向量机属于有监督学习,主要有三个用途
- 分类(Classification);
- 回归(Regression);
- 异常检测(Outliers Detection);
功能强大实用,可以说集美貌与才华于一身。
相比其他模型,支持向量机的主要优势有
- 高维空间运算效率很高;
- 在 feature 数量大于 case 数量的时候依然有很高的效率;
- 只需计算训练集里面的部分数据(support vectors);
- 灵活,有多种核函数(Kernel functions)可选,甚至可以自定义核函数;
当然,它也有不足的地方,例如
- 如果 feature 的数量远大于样本数时,需要注意过度拟合(over-fitting);
- 支持向量机不直接计算概率,需要通过5倍交叉验证(five-fold cross-validation)来计算,运算成本很高;
作为经典算法,很多软件包已经继承了支持向量机,我们无需手动实现。以scikit learn 为例,SVC 和 LinearSVC 可以实现分类算法,SVR 和 LinearSVR 可以实现回归算法,OneClassSVM 可以实现异常检测算法。
使用支持向量机的时候需要注意一些细节
- 选择合适的
C。该参数是用来调节模型柔度的,默认为 1,如果数据噪音较大,可以尝试将其减小以避免过度拟合; - 提前标准化参数。支持向量机对数据大小敏感,所以训练之前应先将数据标准化。可以标准化为[0, 1]之间、[-1, 1]之间,或者均值为0、标准差为 1 的数据。需要注意的是,所有参数都应该用同一种方法标准化,这样结果才有意义;
3. 实现
经过前几次的学习,我们对 scikit learn 的基本操作已经比较熟悉了。今天我们在实现阶段做一个稍微有点挑战性的工作,从零设计一个支持向量机的垃圾邮件识别工具。
要实现垃圾邮件分类,首先需要把邮件处理成算法能识别的数据,也即 Tokenize 。而 Tokenize 之前,需要先把邮件预处理一下。
首先,加载相应的库
import numpy as np
import re
from sklearn import svm
from sklearn.model_selection import train_test_split
然后构造垃圾邮件语料库
vocablist = [line.strip().split('\t')[-1] for line in open('vocab.txt', 'r', encoding='UTF8')]
vocab = {}
for i in range(len(vocablist)):
vocab[vocablist[i]] = i
然后读入待处理邮件并进行相应预处理
with open('emailSample1.txt', 'r', encoding='UTF8') as email:
email = email.read()
email = email.lower()
email = re.sub('[0-9]+', 'number', email)
email = re.sub('(http|https)://[^\s]*', 'httpaddr', email)
email = re.sub('[^\s]+@[^\s]+', 'emailaddr', email)
email = re.sub('[$]+', 'dollar', email)
email = re.sub('<[^<>]+>', ' ', email)
email = re.sub('[^0-9a-z]', ' ', email)
email = re.sub('(\s+)', ' ', email).strip()
email = email.split()
email
这里用到了Python的正则表达式。正则表达式是文本处理的神兵利器,不可不用。
接下来,我们提取邮件的特征(feature)
wordidx = []
for i in range(len(email)):
if email[i] in vocablist:
wordidx.append(vocab[email[i]])
feature = [0 for i in range(len(vocab))]
for i in range(len(wordidx)):
feature[wordidx[i]] = 1
提取特征的意思是,将邮件处理后的单词一一映射到垃圾邮件语料库的索引里面。此处引用的语料库共1899个单词,就会组成一个1899大小的向量。
举例说,award 在语料库里面对应的数字是 144,那么如果邮件里面有 award 这个单词,就将向量 144 处赋值为 1;如果没有,就赋值为 0。
这样,我们就可以为每一封邮件建立一个对应语料库的特征向量。我们将其赋值给变量 X。
支持向量机是有监督学习,所以我们的训练集里面,会有很多不同的邮件,有些是垃圾邮件,将其 y标记为 1,有的不是垃圾邮件,标记 y 为 0。
这样,我们就形成了一个 Tokenize 后的邮件输入矩阵 X 和对应标及其是否是垃圾邮件的 y。我们可以数据分为 Training set 和 Test set,先用 Training set 训练模型,然后用 Test set 检查结果。
data = np.loadtxt('svmSpam.txt', delimiter=' ')
X = data[:, 0:-1]; y = data[:, -1]
X_train, X_test, y_train, y_test = train_test_split(X, y)
clf = svm.SVC()
clf.fit(X_train, y_train)
print("Training set score: {:.2f}".format(clf.score(X_train, y_train)))
print("Test set score: {:.2f}".format(clf.score(X_test, y_test)))
最后,结果输出为
Training set score: 0.99
Test set score: 0.96
吼吼,测试准确率高达0.96,Cool~
4. 总结
今天我们大致介绍了支持向量机的用法,并用其实现了一个简单的垃圾邮件处理工具。相关代码均已上传到Github(https://github.com/jetorz/Data2Science)。
从今天的例子中我们学到
- 技术重要,但更重要的是能用技术来实现什么。学完机器学习,不能就丢一边了,而是要想办法在生活中用起来;
- 数据很关键。学习模型需要数据,甚至大量数据。Kaggle 是个好地方,可以用起来;
- 编程是个厚积薄发的功夫。比如搞机器学习要处理文本,就不能不知道正则表达式。其他类似;
路漫漫其修远兮,继续上下求索吧。
5. 交流
独学而无友则孤陋寡闻。现有「数据与统计科学」微信交流群,内有数据行业资深从业人员、海外博士、硕士等,欢迎对数据科学、数据分析、机器学习、人工智能有兴趣的朋友加入,一起学习讨论。
大家可以扫描下面二维码,添加荔姐微信邀请加入,暗号:机器学习加群。

6. 扩展
6.1. 延伸阅读
6.2. 参考文献
- G. James, D. Witten, T. Hastie R. Tibshirani, An introduction to statistical learning: with applications in R. New York: Springer, 2013.
- T. Hastie, R. Tibshirani, J. H. Friedman, The elements of statistical learning: data mining, inference, and prediction, 2nd ed. New York, NY: Springer, 2009.
- W. Härdle, L. Simar, Applied multivariate statistical analysis, 3rd ed. Heidelberg ; New York: Springer, 2012.

本文使用 mdnice 排版