支持向量机 (SVM),SVM是一种分类回归算法。它的工作原理是识别一个超平面,该平面将数据中的类分隔开。超平面是一个几何实体,它的维数比周围的空间小1。
如果要求SVM对一个二维数据集进行分类,它会用一个一维的超空间(一条线)进行分类,三维数据中的类会用一个二维平面进行分类,第n维数据会用一个N-1维线进行分类。
SVM也称为边缘分类器,因为它在类之间绘制边缘。
如图所示,图像有一个线性可分的类。然而,有时类不能用当前维度中的直线分隔。支持向量机能够映射高维数据,使数据具有一定的可分离性。
支持向量机在特征数(列)大于样本数(行)的情况下非常强大。它在高维(如图像)中也很有效。它还具有内存效率,因为它使用数据集的子集来学习支持向量。
在本文中,我们将了解什么是支持向量机算法,支持向量机背后的简要理论以及它们在Python的Scikit-Learn库中的实现。然后,我们将向支持向量机的高级概念迈进,即内核支持向量机,并将在Scikit-Learn的帮助下实现它。
Simple SVM
在二维线性可分数据的情况下,如图1所示,典型的机器学习算法试图找到一个边界来划分数据,使错误分类误差最小化。如果您仔细查看图1,可能有几个边界可以正确划分数据点。两条虚线和一条实线对数据进行了正确的分类。
图1:多个决策边界
SVM与其他分类算法的不同之处在于,它选择的决策边界使所有类与最近数据点的距离最大。支持向量机不仅仅是找到一个决策边界;而且找到最优决策边界。
最优决策边界是所有类中距最近点距离最大的决策边界。距离决策边界最近且决策边界与决策点距离最大的点称为支持向量,如图2所示。支持向量机的决策边界称为最大边缘分类器,或最大边缘超平面。
图2:带支持向量的决策边界
在寻找支持向量、计算决策边界与支持向量之间的裕度并使其最大化的过程中,涉及到复杂的数学问题。在本教程中,我们将不深入讨论数学的细节,而是将了解支持向量机和内核支持向量机是如何通过Python Scikit-Learn库实现的。
用Scikit-Learn实现SVM
我们的任务是根据纸币的小波变换图像的偏斜度、图像的方差、图像的熵和图像的曲率四个属性来预测纸币的真伪。这是一个二分类问题,我们将使用SVM算法来解决这个问题。本节的其余部分由标准的机器学习步骤组成。
导入库
以下脚本导入所需的库:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
导入数据集
有关数据可于下列连结下载:
https://drive.google.com/file/d/13nw-uRXPY8XIZQxKRNZ3yYlho-CYm_Qt/view
有关数据的详细资料,请浏览以下连结:
https://archive.ics.uci.edu/ml/datasets/banknote+authentication
下载数据集并将其存储在您的机器上。在本例中,数据集的CSV文件存储在我的Windows计算机上D驱动器的“数据集”文件夹中。脚本从这个路径读取文件。您可以相应地更改计算机的文件路径。
要从CSV文件中读取数据,最简单的方法是使用panda库的read_csv方法。下面的代码将银行纸币数据读入panda 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的所有列都存储在X变量中,“Class”列除外,它是label列。drop()方法删除这一列。
在第二行中,只有class列存储在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)
训练算法
我们将数据分为训练集和测试集。现在是根据训练数据训练SVM的时候了。Scikit-Learn包含支持向量机库,其中包含用于不同支持向量机算法的内置类。由于我们要执行一个分类任务,我们将使用支持向量分类器类,它在Scikit-Learn的svm库中被写成SVC。该类接受一个参数,即内核类型。这非常重要。对于一个简单的SVM,由于简单的SVM只能对线性可分的数据进行分类,所以我们简单地将这个参数设置为“linear”。我们将在下一节中看到非线性内核。
调用SVC类的拟合方法对训练数据进行训练,并将训练数据作为参数传递给拟合方法。执行以下代码训练算法:
from sklearn.svm import SVC
svclassifier = SVC(kernel='linear')
svclassifier.fit(X_train, y_train)
做预测
采用SVC类的预测方法进行预测。请看下面的代码:
y_pred = svclassifier.predict(X_test)
评估算法
混淆矩阵、精度、回忆和F1度量是分类任务最常用的度量。Scikit-Learn的度量库包含classification_report和confusion_matrix方法,它们可以很容易地用于找出这些重要度量的值。
下面是找到这些度量的代码:
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test,y_pred))
print(classification_report(y_test,y_pred))
结果
评价结果如下:
结果表明,支持向量机的性能略优于决策树算法。SVM算法中只有一个分类错误,而决策树算法中有四个分类错误。
我们了解了如何使用简单的SVM算法来寻找线性可分数据的决策边界。然而,对于非线性可分数据,直线不能作为决策边界。对于非线性可分数据,不能使用简单的SVM算法。而是使用了一种改进的SVM,称为内核SVM。详细内容请参考支持向量机 (SVM)(二)-Kernel SVM。