Python机器学习的练习六:支持向量机

在这个练习中,我们将使用支持向量机(SVMs)创建一个垃圾邮件分类器。在一些简单的2D数据集上使用SVMs去观察他们如何工作,接下来我们查看一组邮件数据集,并且在处理过的邮件上使用SVMs创建一个分类器,用于判断他们是否是垃圾邮件。

尽管在多类场景中有使用SVMs的方法,但它是一种默认的二进制分类工具。SVMs还可以使用 kernel trick 来处理非线性分类,在尝试找到超平面之前,将数据投射到高维空间中。SVMs是一种强大的算法类,经常用于实际的机器学习应用程序。

首先要做的就是研究简单的二维数据集,看看线性的SVM是如何在不同C值(类似于线性/逻辑回归中的正则化项)的数据集上工作的。

加载数据。

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt 
import seaborn as sb 
from scipy.ioimport loadmat 
%matplotlib inline

raw_data= loadmat('data/ex6data1.mat') 
raw_data
{'X': array([[1.9643  , 4.5957  ],
        [2.2753  , 3.8589  ],
        [2.9781  , 4.5651  ],
        ...,
        [0.9044  , 3.0198  ],
        [0.76615 , 2.5899  ],
        [0.086405, 4.1045  ]]),
 '__globals__': [],
 '__header__':'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Sun Nov 13 14:28:43 2011',
 '__version__':'1.0',
 'y': array([[1],
        [1],
        [1],
        ...,
        [0],
        [0],
        [1]], dtype=uint8)}

我们将它可视化为散点图,类标签由符号表示(‘ + ‘为 positive,’ o ‘为negative)。

data= pd.DataFrame(raw_data['X'], columns=['X1','X2']) 
data['y']= raw_data['y']

positive= data[data['y'].isin([1])] 
negative= data[data['y'].isin([0])]

fig, ax= plt.subplots(figsize=(12,8)) 
ax.scatter(positive['X1'], positive['X2'], s=50, marker='x', label='Positive') 
ax.scatter(negative['X1'], negative['X2'], s=50, marker='o', label='Negative') 
ax.legend()

注意,有一个比其他值更positive的离群值的例子。这些类仍然是线性可分的,但它是一个非常紧密的组合。我们将训练一个线性支持向量机来学习类边界。在这个练习中,我们不需要从头开始执行SVM,所以我将使用scikit- learn的内置工具。

from sklearnimport svm 
svc= svm.LinearSVC(C=1, loss='hinge', max_iter=1000) 
svc
LinearSVC(C=1, class_weight=None, dual=True, fit_intercept=True,
     intercept_scaling=1, loss='hinge', max_iter=1000, multi_class='ovr',
     penalty='l2', random_state=None, tol=0.0001, verbose=0)

第一次试验取值C=1,观察它怎样运行。

svc.fit(data[['X1','X2']], data['y']) 
svc.score(data[['X1','X2']], data['y'])
0.98039215686274506

看来它错误的分类了离散值。让我们看看当C值更大时会怎样。

svc2= svm.LinearSVC(C=100, loss='hinge', max_iter=1000) 
svc2.fit(data[['X1','X2']], data['y']) 
svc2.score(data[['X1','X2']], data['y'])
1.0

这次我们得到了更好的训练集的分类。然而随着C值的增加,我们创建了一个不再适合该数据的决策边界。我们可以通过每个等级预测的置信度来可视化它,这是点与超平面的距离的函数。

data['SVM 1 Confidence']= svc.decision_function(data[['X1','X2']])

fig, ax= plt.subplots(figsize=(12,8)) 
ax.scatter(data['X1'], data['X2'], s=50, c=data['SVM 1 Confidence'], cmap='seismic') 
ax.set_title('SVM (C=1) Decision Confidence')
data['SVM 2 Confidence']= svc2.decision_function(data[['X1','X2']])

fig, ax= plt.subplots(figsize=(12,8)) 
ax.scatter(data['X1'], data['X2'], s=50, c=data['SVM 2 Confidence'], cmap='seismic') 
ax.set_title('SVM (C=100) Decision Confidence')

边界附近点的颜色差别有点微妙。在第一个图像中,边界附近的点是强烈的红色或蓝色,表明它们在超平面的可靠范围内。在第二个图像中不是的,这样其中一些点几乎是白色的,表明它们与超平面直接相邻。

现在我们将从线性SVM转移到能够使用内核进行非线性分类的SVM。首先,我们需要实现一个高斯核函数。为了完全透明,尽管scikit- learn有一个高斯内核,我们仍然从头开始实现高斯核函数 。

def gaussian_kernel(x1, x2, sigma): 
    return np.exp(-(np.sum((x1- x2)** 2)/ (2 * (sigma** 2))))

x1= np.array([1.0,2.0,1.0]) 
x2= np.array([0.0,4.0,-1.0]) 
sigma= 2 
gaussian_kernel(x1, x2, sigma)
0.32465246735834974

这个结果与预期值相匹配。接下来,我们将检查另一个非线性决策边界的数据集。

raw_data= loadmat('data/ex6data2.mat')

data= pd.DataFrame(raw_data['X'], columns=['X1','X2']) 
data['y']= raw_data['y']

positive= data[data['y'].isin([1])] 
negative= data[data['y'].isin([0])]

fig, ax= plt.subplots(figsize=(12,8)) 
ax.scatter(positive['X1'], positive['X2'], s=30, marker='x', label='Positive') 
ax.scatter(negative['X1'], negative['X2'], s=30, marker='o', label='Negative') 
ax.legend()

对于这个数据集,我们将使用内置的RBF内核构建一个支持向量机分类器,并检查它在训练数据上的准确性。为了使决策边界可视化,这次我们将基于具有负类标签的实例预测概率来遮蔽点。我们从结果中看到大部分都是正确的。

svc= svm.SVC(C=100, gamma=10, probability=True) 
svc.fit(data[['X1','X2']], data['y']) 
data['Probability']= svc.predict_proba(data[['X1','X2']])[:,0]

fig, ax= plt.subplots(figsize=(12,8)) 
ax.scatter(data['X1'], data['X2'], s=30, c=data['Probability'], cmap='Reds')

对于第三个数据集,我们得到了训练和验证集,并基于验证集性能为SVM模型寻找最优超参数。尽管我们可以很容易地使用scikit- learn的内置网格搜索来实现这一点,但为了更多的练习,我们将从头开始实现一个简单的网格搜索。

raw_data= loadmat('data/ex6data3.mat')

X= raw_data['X'] 
Xval= raw_data['Xval'] 
y= raw_data['y'].ravel() 
yval= raw_data['yval'].ravel()

C_values= [0.01,0.03,0.1,0.3,1,3,10,30,100] 
gamma_values= [0.01,0.03,0.1,0.3,1,3,10,30,100]

best_score= 0 
best_params= {'C':None,'gamma':None}

for Cin C_values: 
    for gammain gamma_values:
        svc= svm.SVC(C=C, gamma=gamma)
        svc.fit(X, y)
        score= svc.score(Xval, yval)

        if score > best_score:
            best_score= score
            best_params['C']= C
            best_params['gamma']= gamma

best_score, best_params
(0.96499999999999997, {'C':0.3,'gamma':100})

现在我们继续练习的最后一部分。在这个部分,我们的目标是使用SVMs构建一个垃圾邮件过滤器。在练习文本中,有一个任务需要对一些文本进行预处理,以使获得适合SVM的数据格式,这个任务非常简单,而其他预处理步骤(例如HTML删除、词干、规范化等)都已经完成了。我不会重复这些步骤,而是跳过机器学习任务,其中包括从预处理的训练中创建分类器,以及由垃圾邮件和非垃圾邮件转换为单词发生向量的测试数据集。

spam_train= loadmat('data/spamTrain.mat') 
spam_test= loadmat('data/spamTest.mat')

spam_train
{'X': array([[0,0,0, ...,0,0,0],
        [0,0,0, ...,0,0,0],
        [0,0,0, ...,0,0,0],
        ...,
        [0,0,0, ...,0,0,0],
        [0,0,1, ...,0,0,0],
        [0,0,0, ...,0,0,0]], dtype=uint8),
 '__globals__': [],
 '__header__':'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Sun Nov 13 14:27:25 2011',
 '__version__':'1.0',
 'y': array([[1],
        [1],
        [0],
        ...,
        [1],
        [0],
        [0]], dtype=uint8)}
X= spam_train['X'] 
Xtest= spam_test['Xtest'] 
y= spam_train['y'].ravel() 
ytest= spam_test['ytest'].ravel()

X.shape, y.shape, Xtest.shape, ytest.shape
((4000L,1899L), (4000L,), (1000L,1899L), (1000L,))

每个文档都被转换成一个向量,其中1,899个维度对应于词汇表中的1,899个字。二进制的值用来表示文档中的单词是否存在。训练和评估只是考验分类器的一个问题。

svc= svm.SVC() 
svc.fit(X, y) 
print('Test accuracy = {0}%'.format(np.round(svc.score(Xtest, ytest)* 100,2)))
Test accuracy= 95.3%

这个结果与默认参数有关。我们可能会使用一些参数调优来提高它的精度,但是95%的精度仍然不差。

本文为编译作品,作者John Wittenauer,原网址

http://www.johnwittenauer.net/machine-learning-exercises-in-python-part-6/

原文发布于微信公众号 - ATYUN订阅号(atyun_com)

原文发表时间:2017-08-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏人工智能

随机森林的简单实现

随机森林(RandomForest):顾名思义,是用随机的方式建立一个森林,森林里面:由很多的决策树组成,随机森林的每一棵决策树之间是没有关联的。在得到森林之后...

43270
来自专栏腾讯移动品质中心TMQ的专栏

机器学习之一:聚类实战

可预见的未来数据分析和机器学习将成为工作中必备技能,也许已经在某个项目中讨论怎么调参优化,就像过去讨论如何优雅的写python、如何避免C++内存泄露一样常见。

28560
来自专栏AI科技大本营的专栏

如何通过机器学习还原图像色彩

作者 | Klevis Ramo 译者 | Teixeira10 在本文中,作者提出了使用k-means算法来对图像进行色彩还原,介绍算法的步骤,同时应用在图...

366120
来自专栏机器之心

开源 | 谷歌大脑提出TensorFuzz,用机器学习debug神经网络

神经网络正逐渐影响人类生活环境,包括医学诊断、自动驾驶、企业和司法决策过程、空中交通管制、以及电网控制。这些人类可以做到的事,神经网络也有可能做到。它可以拯救生...

13920
来自专栏FreeBuf

通过预测API窃取机器学习模型

由于机器学习可能涉及到训练数据的隐私敏感信息、机器学习模型的商业价值及其安全中的应用,所以机器学习模型在一定程度上是可以认为是机密的。但是越来越对机器学习服务提...

62050
来自专栏计算机视觉战队

深度学习——感受野

最近在组会讲解框架时,在感受野这个小知识点,大家开始产生歧义,今天我就简单的给大家讲解下这个小知识点,也给初学者带来一个对Receptive Field崭新的认...

48170
来自专栏AI科技评论

大会 | DiracNets:无需跳层连接的ResNet

AI 科技评论按:本文作者 David 9,首发于作者的个人博客,AI 科技评论获其授权转载。 虚拟化技术牺牲硬件开销和性能,换来软件功能的灵活性;深度模型也类...

40760
来自专栏磐创AI技术团队的专栏

FaceRank-人脸打分基于 TensorFlow 的 CNN 模型,这个妹子颜值几分?

FaceRank-人脸打分基于 TensorFlow 的 CNN 模型 机器学习是不是很无聊,用来用去都是识别字体。能不能帮我找到颜值高的妹子,顺便提高一下姿势...

46240
来自专栏大数据

具有mxnetR的前馈神经网络

mxnetR是一个深度学习软件包,可与所有深度学习类型一起使用,包括前馈神经网络(FNN)。FNN具有隐藏层的简单处理单元。

44910
来自专栏AI研习社

语义分割和转置卷积

分割对图像分析是必不可少的。语义分割描述了每个像素与类别标记的关联过程,(例如:花朵、人物、道路、天空、海洋、或者汽车)。

16520

扫码关注云+社区

领取腾讯云代金券