[译] 用 Scikit-Learn 实现 SVM 和 Kernel SVM

支持向量机(SVM)是一种监督学习分类算法。支持向量机提出于 20 世纪 60 年代在 90 年代获得了进一步的发展。然而,因为能取得很好的效果,最近才开始变得特别受欢迎。与其余机器学习算法相比,SVM 有其独特之处。前端

本文先简明地介绍支持向量机背后的理论和如何使用 Python 中的 Scikit-Learn 库来实现。而后咱们将学习高级 SVM 理论如 Kernel SVM,一样会使用 Scikit-Learn 来实践。python

简单 SVM

考虑二维线性可分数据,如图 1,典型的机器学习算法但愿找到使得分类错误最小的分类边界。若是你仔细看图 1,会发现能把数据点正确分类的边界不惟一。两条虚线和一条实线都能正确分类全部点。android

Multiple Decision Boundaries

图 1:多决策边界ios

SVM 经过最大化全部类中的数据点到决策边界的最小距离的方法来肯定边界,这是 SVM 和其余算法的主要区别。SVM 不仅是找一个决策边界;它能找到最优决策边界。git

能使全部类到决策边界的最小距离最大的边界是最优决策边界。如图 2 所示,那些离决策边界最近的点被称做支持向量。在支持向量机中决策边界被称做最大间隔分类器,或者最大间隔超平面。github

Decision Boundary with Support Vectors

图 2:决策边界的支持向量算法

寻找支持向量、计算决策边界和支持向量之间的距离和最大化该距离涉及到很复杂的数学知识。本教程不打算深刻到数学的细节,咱们只会看到如何使用 Python 的 Scikit-Learn 库来实现 SVM 和 Kernel-SVM。后端

经过 Scikit-Learn 实现 SVM

咱们将使用和决策树教程同样的数据。bash

咱们的任务是经过四个属性来判断纸币是否是真的,四个属性是小波变换图像的偏度、图像的方差、图像的熵和图像的曲率。咱们将使用 SVM 解决这个二分类问题。剩下部分是标准的机器学习流程。机器学习

导入库

下面的代码导入全部须要的库:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
复制代码

导入数据

数据能够从下面的连接下载:

drive.google.com/file/d/13nw…

数据的详细信息能够参考下面的连接:

archive.ics.uci.edu/ml/datasets…

从 Google drive 连接下载数据并保存在你本地。这个例子中数据集保存在我 Windows 电脑的 D 盘 “Datasets” 文件夹下的 CSV 文件里。下面的代码从文件路径中读取数据。你能够根据文件在你本身电脑上的路径修改。

读取 CSV 文件的最简单方法是使用 pandas 库中的 read_csv 方法。下面的代码读取银行纸币数据记录到 pandas 的 dataframe:

bankdata = pd.read_csv("D:/Datasets/bill_authentication.csv")
复制代码

探索性数据分析

使用 Python 中各类各样的库几乎能够完成全部的数据分析。为了简单起见,咱们只检查数据的维数并查看最前面的几条记录。查看数据的行数和列数,执行下面的语句:

bankdata.shape
复制代码

你将看到输出为(1372, 5)。这意味着数据集有 1372 行和 5 列。

为了对数据长什么样有个直观感觉,能够执行下面的命令:

bankdata.head()
复制代码

输出下面以下:

你能够发现全部的属性都是数值型。类别标签也是数值型即 0 和 1。

数据预处理

数据预处理包括(1)把属性和类表标签分开和(2)划分训练数据集和测试数据集。

把属性和类别标签分开,执行下面的代码:

X = bankdata.drop('Class', axis=1)
y = bankdata['Class']
复制代码

上面代码第一行从 bankdata dataframe 中移除了类别标签列 “Class” 并把结果赋值给变量 X。函数 drop() 删除指定列。

第二行,只将类别列存储在变量 y 里。如今变量 X 包含全部的属性变量 y 包含对应的类别标签。

如今数据集已经将属性和类别标签分开,最后一步预处理是划分出训练集和测试集。幸运的是 Scikit-Learn 中 model_selection 模块提供了函数 train_test_split 容许咱们优雅地把数据分红训练和测试两部分。

执行下面的代码完成划分:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)
复制代码

算法训练

咱们已经把数据分红了训练集和测试集。如今咱们使用训练集来训练。Scikit-Learn 库中的 svm 模块实现了各类不一样的 SVM 算法。因为咱们要完成一个分类任务,咱们将使用由 Scikit-Learn 中 svm 模块下的 SVC 类实现的支持向量分类器。这个类须要一个参数指定核函数的类型。这参数很重要。这里考虑最简单的 SVM 把类型参数设为 linear 线性支持向量机只适用于线性可分数据。咱们在下一部分介绍非线性核。

把训练数据传给 SVC 类 fit 方法来训练算法。执行下面的代码完成算法训练:

from sklearn.svm import SVC
svclassifier = SVC(kernel='linear')
svclassifier.fit(X_train, y_train)
复制代码

作预测

SVC 类的 predict 方法能够用来预测新的数据的类别。代码以下:

y_pred = svclassifier.predict(X_test)
复制代码

算法评价

混淆矩阵、精度、召回率和 F1 是分类任务最经常使用的一些评价指标。Scikit-Learn 的 metrics 模块中提供了 classification_reportconfusion_matrix 等方法,这些方法能够快速的计算这些评价指标。

下面是计算评价指标的代码:

from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test,y_pred))
print(classification_report(y_test,y_pred))
复制代码

结果

下面是评价结果:

[[152    0]
 [  1  122]]
              precision   recall   f1-score   support

           0       0.99     1.00       1.00       152
           1       1.00     0.99       1.00       123

avg / total        1.00     1.00       1.00       275
复制代码

从上面的评价结果中咱们能够发现 SVM 比决策树稍微的要好。SVM 只有 1% 的错分类而决策树有 4%。

Kernel SVM

在上面的章节咱们看到了如何使用简单 SVM 算法在线性可分数据上找到决策边界。然而,当数据不是线性可分的时候如图 3,直线就不能再做为决策边界了。

Non-linearly Separable Data

Fig 3: 非线性可分数据

对非线性可分的数据集,简单的 SVM 算法就再也不适用。一种改进的 SVM 叫作 Kernel SVM 能够用来解决非线性可分数据的分类问题。

从根本上说,kernel SVM 把在低维空间中线性不可分数据映射成在高维空间中线性可分的数据, 这样不一样类别的数据点就分布在了不一样的维度上。一样,这里涉及到复杂的数学,可是若是你只是使用 SVM 彻底不用担忧。咱们能够很简单的使用 Python 的 Scikit-Learn 库来实现和使用 kernel SVM。

使用 Scikit-Learn 实现 Kernel SVM

和实现简单的 SVM 同样。在这部分咱们使用有名的鸢尾花数据集,依照植物下面的四个属性去预测它属于哪一个分类:萼片宽度,萼片长度,花瓣宽度和花瓣长度。

数据能够从下面的连接下:

archive.ics.uci.edu/ml/datasets…

剩下的步骤就是典型的机器学习步骤在训练 Kernel SVM 以前咱们须要一些简单说明。

导入库

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
复制代码

导入数据

url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"

# Assign colum names to the dataset
colnames = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'Class']

# Read dataset to pandas dataframe
irisdata = pd.read_csv(url, names=colnames)
复制代码

预处理

X = irisdata.drop('Class', axis=1)
y = irisdata['Class']
复制代码

训练和测试集划分

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)
复制代码

算法训练

一样使用 Scikit-Learn 的 svm 模块中的 SVC 类。区别在于类 SVC 的核函数类型参数的值不同。在简单 SVM 中咱们使用的核函数类型是 “linear”。然而,kernel SVM 你可使用 高斯、多项式、sigmoid或者其余可计算的核。咱们将实现多项式、高斯和 sigmoid 核并检验哪个表现更好。

1. 多项式核

多项式核的状况下,你开须要传递一个叫degree 的参数给SVC 类。这个参数是多项式的次数。看下面的代码如何实现多项式核实现 kernel SVM:

from sklearn.svm import SVC
svclassifier = SVC(kernel='poly', degree=8)
svclassifier.fit(X_train, y_train)
复制代码

作预测

如今咱们已经训练好了算法,下一步是在测试集上作预测。

运行下面的代码来实现:

y_pred = svclassifier.predict(X_test)
复制代码

算法评价

一般机器学习算法的最后一步是评价多项式核。运行下面的代码。

from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
复制代码

使用多项式核的 kernel SVM 的输出以下:

[[11  0  0]
 [ 0 12  1]
 [ 0  0  6]]
                 precision   recall   f1-score   support

    Iris-setosa       1.00     1.00       1.00        11
Iris-versicolor       1.00     0.92       0.96        13  
 Iris-virginica       0.86     1.00       0.92         6

    avg / total       0.97     0.97       0.97        30
复制代码

如今让咱们使用高斯和 sigmoid 核来重复上面的步骤。

2. 高斯核

看一眼咱们是如何使用高斯核实现 kernel SVM 的:

from sklearn.svm import SVC
svclassifier = SVC(kernel='rbf')
svclassifier.fit(X_train, y_train)
复制代码

使用高斯核,你必须指定类 SVC 的核参数额值为 “rbf”。

预测和评价

y_pred = svclassifier.predict(X_test)
复制代码
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
复制代码

使用高斯核的输出:

[[11  0  0]
 [ 0 13  0]
 [ 0  0  6]]
                 precision   recall   f1-score   support

    Iris-setosa       1.00     1.00       1.00        11
Iris-versicolor       1.00     1.00       1.00        13  
 Iris-virginica       1.00     1.00       1.00         6

    avg / total       1.00     1.00       1.00        30
复制代码

3. Sigmoid 核

最后,让咱们使用 sigmoid 核实现 Kernel SVM。看下面的代码:

from sklearn.svm import SVC
svclassifier = SVC(kernel='sigmoid')
svclassifier.fit(X_train, y_train)
复制代码

使用 sigmoid 核须要指定 SVC 类的参数 kernel 的值为 “sigmoid”。

预测和评价

y_pred = svclassifier.predict(X_test)
复制代码
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
复制代码

使用 Sigmoid 核的输出以下:

[[ 0  0 11]
 [ 0  0 13]
 [ 0  0  6]]
                 precision   recall   f1-score   support

    Iris-setosa       0.00     0.00       0.00        11
Iris-versicolor       0.00     0.00       0.00        13  
 Iris-virginica       0.20     1.00       0.33         6

    avg / total       0.04     0.20       0.07        30
复制代码

对比核的表现

对比发现 sigmoid 核是最差的。由于 sigmoid 返回 0 和 1 两个值,sigmoid 核更适合二分类问题。而咱们的例子中有三个类别。

高斯核与多项式核有差很少的表现。高斯核预测准确率 100% 多项式核也只有 1% 的偏差。高斯核表现稍好。然而没有硬性的规则来评价哪一种核函数在任何场景下都更好。只能经过在测试集上的测试结果来选择哪个核在你的数据集上表现更好。

资源

是否想学习更多的 Scikit-Learn 和的机器学习算法相关知识?我推荐你查看更多的资料,如在线课程:

总结

本文咱们学习了基本的 SVM 和 kernel SVMs。还了解了 SVM 算法背后的直觉以及如何使用 Python 库 Scikit-Learn 来实现。咱们也学习了使用不一样类型的核来实现 SVM。我猜你已经想把这些算法应用到真实的数据上了好比 kaggle.com

最后我仍是建议你去详细了解下 SVM 背后的数学。虽然若是只使用 SVM 算法并不须要了解那些数学,但要理解算法是如何找到决策边界的数学会颇有帮助。

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索