SVM支持向量机

一、算法概述

支持向量机是一种分类器。之所以称为“机”是因为它会产生一个二值决策结果,即它是一种决策“机”。支持向量机的泛化错误率较低,也就是说它具有良好的学习能力,且学到的结果具有很好的推广性。这些优点使得支持向量机十分流行,有些人认为它是监督学习中最好的定式算法。

支持向量机的分类方法,是在一组分布中找出一个超平面作为决策边界,使模型在数据上的分类误差尽量接近于小,尤其是在未知数据集上的分类误差(泛化误差)尽量小。在几何中,超平面(hyperplane)是一个空间的子空间,它是维度比所在空间小一维的空间。 如果数据空间本身是三维的,则其超平面是二维平面,而如果数据空间本身是二维的,则其超平面是一维的直线。在二分类问题中,如果一个超平面能够将数据划分为两个集,其中每个集合中包含单独的一个类别,我们就说这个超平面是数据的“决策边界”。我们希望找到离分隔超平面最近的点,确保它们离分隔面的距离尽可能远。这里点到分隔面的距离被称为间隔(margin)。我们希望间隔尽可能地大,这是因为如果我们犯错或者在有限数据上训练分类器的话,我们希望分类器尽可能健壮。支持向量(support vector)就是离分隔超平面最近的那些点。

支持向量机优点:泛化错误率低,计算开销不大,结果易解释。缺点:对参数调节和核函数的选择敏感,原始分类器不加修改仅适用于处理二类问题。适用数据类型:数值型和标称型数据。

SVM的一般流程:(1) 收集数据:可以使用任意方法。(2) 准备数据:需要数值型数据。(3) 分析数据:有助于可视化分隔超平面。(4) 训练算法:SVM的大部分时间都源自训练,该过程主要实现两个参数的调优。(5) 测试算法:十分简单的计算过程就可以实现。(6) 使用算法:几乎所有分类问题都可以使用SVM,值得一提的是,SVM本身是一个二类分类器,对多类问题应用SVM需要对代码做一些修改。

二、实战:基于SVM的人脸识别引擎

1.收集、准备数据

使用sklearn中的人脸数据集。

from sklearn.datasets import fetch_lfw_people
faces = fetch_lfw_people(min_faces_per_person=60)
print(faces.target_names)
print(faces.images.shape)

2.分析数据

fig, ax = plt.subplots(3, 5)
for i, axi in enumerate(ax.flat):
    axi.imshow(faces.images[i], cmap='bone')
    axi.set(xticks=[], yticks=[],
            xlabel=faces.target_names[faces.target[i]])

每一幅图的尺寸为 [62×47] , 大约 3000 个像素值。我们可以将整个图像展平为一个长度为3000左右的一维向量,然后使用这个向量做为特征。通常更有效的方法是通过预处理提取图像最重要的特征。一个重要的特征提取方法是PCA(主成分分析), 可以将一副图像转换为一个长度为更短的(150)向量。

from sklearn.svm import SVC
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
pca = PCA(n_components=150, whiten=True, random_state=42)
svc = SVC(kernel='linear', class_weight='balanced')
model = make_pipeline(pca, svc)

Pipeline可以将许多算法模型串联起来,可以用于把多个estamitors级联成一个estamitor,比如将特征提取、归一化、分类组织在一起形成一个典型的机器学习问题工作流。Pipleline中最后一个之外的所有estimators都必须是变换器(transformers),最后一个estimator可以是任意类型(transformer,classifier,regresser),如果最后一个estimator是个分类器,则整个pipeline就可以作为分类器使用,如果最后一个estimator是个聚类器,则整个pipeline就可以作为聚类器使用。主要带来两点好处:(1)直接调用fit和predict方法来对pipeline中的所有算法模型进行训练和预测。(2)可以结合grid search对参数进行选择。

注意:(1)除了最后一个tansform,其余的transform必须实现fit_transform函数。(2)上一个transform类中fit_transform函数的返回值作为下一个transform类fit_transform函数的参数,所以在自己实现自定义的transform类的时候必须要实现fit_transform函数。(3)fit_transform 返回值为 numpy array。

可以通过make_pipeline函数实现:它是Pipeline类的简单实现,只需传入每个step的类实例即可,不需自己命名,自动将类的小写设为该step的名。

3.训练、测试算法

from sklearn.model_selection import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(faces.data, faces.target,
                                                random_state=42)

参数C:浮点数,默认1,必须大于等于0,可不填。松弛系数的惩罚项系数。如果C值设定比较大,那SVC可能会选择边际较小的,能够更好地分类所有训练点的决策边界,不过模型的训练时间也会更长。如果C的设定值较小,那SVC会尽量最大化边界,决策功能会更简单,但代价是训练的准确度。换句话说,C在SVM中的影响就像正则化参数对逻辑回归的影响。

参数C用于权衡”训练样本的正确分类“与”决策函数的边际最大化“两个不可同时完成的目标,希望找出一个平衡点来让模型的效果最佳。在实际使用中,C和核函数的相关参数(gamma,degree等等)们搭配,往往是SVM调参的重点。与gamma不同,C没有在对偶函数中出现,并且是明确了调参目标的,所以我们可以明确我们究竟是否需要训练集上的高精确度来调整C的方向。默认情况下C为1,通常来说这都是一个合理的参数。 如果我们的数据很嘈杂,那我们往往减小C。当然,我们也可以使用网格搜索或者学习曲线来调整C的值。

from sklearn.model_selection import GridSearchCV

param_grid = {'svc__C': [1, 5, 10, 50]}
grid = GridSearchCV(model, param_grid)

%time grid.fit(Xtrain, ytrain)
print(grid.best_params_)
model = grid.best_estimator_
yfit = model.predict(Xtest)
fig, ax = plt.subplots(4, 6)
for i, axi in enumerate(ax.flat):
    axi.imshow(Xtest[i].reshape(62, 47), cmap='bone')
    axi.set(xticks=[], yticks=[])
    axi.set_ylabel(faces.target_names[yfit[i]].split()[-1],
                   color='black' if yfit[i] == ytest[i] else 'red')
fig.suptitle('Predicted Names; Incorrect Labels in Red', size=14);
from sklearn.metrics import classification_report
print(classification_report(ytest, yfit,
                            target_names=faces.target_names))
   precision    recall  f1-score   support

     Ariel Sharon       0.62      0.67      0.65        15
     Colin Powell       0.74      0.84      0.79        68
  Donald Rumsfeld       0.74      0.81      0.77        31
    George W Bush       0.85      0.79      0.82       126
Gerhard Schroeder       0.75      0.78      0.77        23
      Hugo Chavez       0.93      0.70      0.80        20
Junichiro Koizumi       0.92      0.92      0.92        12
       Tony Blair       0.81      0.83      0.82        42

         accuracy                           0.80       337
        macro avg       0.80      0.79      0.79       337
     weighted avg       0.80      0.80      0.80       337
from sklearn.metrics import confusion_matrix
mat = confusion_matrix(ytest, yfit)
sns.heatmap(mat.T, square=True, annot=True, fmt='d', cbar=False,
            xticklabels=faces.target_names,
            yticklabels=faces.target_names)
plt.xlabel('true label')
plt.ylabel('predicted label');

4.SVM总结

优点:模型只需要保存支持向量,模型占用内存少,预测快。分类只取决于支持向量, 适合数据的维度高的情况,例如DNA数据。缺点:训练的时间复杂度为 O[n3]或者至少 O[N2] ,当数据量巨大时候不合适使用。需要做调参C当数据量大时非常耗时间。

三、作业:使用SVM检测蘑菇是否有毒

使用的数据集来自UCI机器学习库:https://archive.ics.uci.edu/ml/datasets/mushroom

数据集中每一条数据包含对蘑菇形状、质地、色彩等特征的描述,详细介绍见上述网址。我们需要以此判断蘑菇是否有毒(p)或者可以吃(e),为两个类别的分类问题。

1.建立寻pipeline

累积可解释方差贡献率曲线是一条以降维后保留的特征个数为横坐标,降维后新特征矩阵捕捉到的可解释方差贡献
率为纵坐标的曲线,能够帮助我们决定n_components最好的取值。

import matplotlib.pyplot as plt
from sklearn.decomposition import PCA

pca_line = PCA().fit(X_mush)

plt.figure(figsize=(20, 8))
plt.plot(list(range(117)),np.cumsum(pca_line.explained_variance_ratio_))
plt.xticks(list(range(117))) #这是为了限制坐标轴显示为整数
plt.xlabel("number of components after dimension reduction")
plt.ylabel("cumulative explained variance ratio")
plt.show()
from sklearn.svm import SVC
from sklearn.pipeline import make_pipeline

# TODO
pca = PCA(n_components=40, whiten=True, random_state=41)
svc = SVC(kernel='rbf', class_weight='balanced')
model = make_pipeline(pca, svc)

2.调参:通过交叉验证寻找最佳的C (控制间隔的大小)

from sklearn.model_selection import GridSearchCV

#TODO
param_grid = {'svc__C': [0.5, 1, 5, 20, 50]}
grid = GridSearchCV(model, param_grid)

%time grid.fit(Xtrain, ytrain)
print(grid.best_params_)
Wall time: 19.2 s
{'svc__C': 1}

3.使用训练好的SVM做预测

# TODO
model = grid.best_estimator_
yfit = model.predict(Xtest)
from sklearn.metrics import classification_report
print(classification_report(ytest, yfit))
              precision    recall  f1-score   support

           0       1.00      1.00      1.00      1047
           1       1.00      1.00      1.00       984

    accuracy                           1.00      2031
   macro avg       1.00      1.00      1.00      2031
weighted avg       1.00      1.00      1.00      2031
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值