用Python的Scikit-Learn实现SVM和Kernel SVM

用Python的Scikit-Learn实现SVM和Kernel SVM

介绍

本指南是有关支持向量机 (SVM) 的三个指南的第一部分。 在本系列中,我们将处理一个伪造的钞票用例,了解简单的 SVM,然后了解 SVM 超参数,最后学习一个称为 内核技巧 并探索其他类型的 SVM。

如果您想阅读所有指南或查看您最感兴趣的指南,请查看下表中每份指南涵盖的主题:

一、用Python的Scikit-Learn实现SVM和Kernel SVM

  • 用例:忘记钞票
  • SVM 的背景
  • 简单(线性)SVM 模型
    • 关于数据集
    • 导入数据集
    • 探索数据集
  • 使用 Scikit-Learn 实现 SVM
    • 将数据划分为训练/测试集
    • 训练模型
    • 做出预测
    • 评估模型
    • 解释结果

2. 了解 SVM 超参数 (快来了!)

  • C超参数
  • Gamma 超参数

3. 使用 Python 的 Scikit-Learn 实现其他 SVM 风格 (快来了!)

  • SVM 的总体思路(回顾)
  • 内核(技巧)SVM
  • 使用 Scikit-Learn 实现非线性核 SVM
  • 导入库
    • 导入数据集
    • 将数据分为特征(X)和目标(y)
    • 将数据划分为训练/测试集
    • 训练算法
  • 多项式内核
    • 做出预测
    • 评估算法
  • 高斯核
    • 预测与评估
  • Sigmoid 内核
    • 预测与评估
  • 非线性内核性能比较

用例:伪造的钞票

有时人们会想办法伪造钞票。 如果有人查看这些笔记并验证其有效性,则可能很难被它们欺骗。

但是,当没有人查看每张纸条时会发生什么? 有没有办法自动知道钞票是伪造的还是真实的?

有很多方法可以回答这些问题。 一个答案是对每张收到的纸币拍照,将其图像与伪造纸币的图像进行比较,然后将其分类为真纸币或伪造纸币。 一旦等待笔记的验证可能是乏味的或至关重要的,那么快速进行比较也会很有趣。

由于正在使用图像,它们可以被压缩、降低为灰度,并提取或量化它们的测量值。 这样,比较将在图像测量之间进行,而不是在每个图像的像素之间进行。

到目前为止,我们已经找到了一种处理和比较钞票的方法,但是它们将如何分类为真钞或伪钞呢? 我们可以使用机器学习来进行分类。 有一种分类算法叫做 支持向量机,主要以其缩写形式而闻名: 支持向量机.

SVM 的背景

SVM 最初于 1968 年由 Vladmir Vapnik 和 Alexey Chervonenkis 引入。 那时,他们的算法仅限于对仅用一条直线即可分离的数据进行分类,或者对数据进行分类。 线性可分. 我们可以看到这种分离的样子:

使用 Python 的 Scikit-Learn PlatoBlockchain 数据智能实现 SVM 和内核 SVM。垂直搜索。人工智能。

在上图中,我们在中间有一条线,一些点位于该线的左侧,而另一些点位于该线的右侧。 请注意,两组点完全分开,中间没有点,甚至没有靠近线的点。 相似点和它们的分界线之间似乎有一个边距,这个边距被称为 分离裕度. 分隔边距的作用是使相似点与分割它们的线之间的空间更大。 SVM 通过使用一些点并计算其垂直向量来支持线的边距决策来做到这一点。 那些是 支持向量 这是算法名称的一部分。 稍后我们将进一步了解它们。 我们在中间看到的直线是通过以下方法找到的 最大化 线和点之间的空间,或者最大化分隔边距的空间。 这些方法源于 最优化理论.

在我们刚刚看到的示例中,两组点都可以很容易地分开,因为每个单独的点都靠近其相似点,而这两组点彼此相距很远。

但是,如果没有办法使用一条直线来分隔数据,会发生什么情况? 如果有乱七八糟的点,或者是否需要曲线?

为了解决这个问题,SVM 后来在 1990 年代进行了改进,以便能够对具有远离其中心趋势的点的数据进行分类,例如异常值,或具有两个以上维度且不可线性分离的更复杂问题.

奇怪的是,直到最近几年,SVM 才被广泛采用,主要是因为它们有时能够达到 90% 以上的正确答案或 , 对于困难的问题。

与其他机器学习算法相比,支持向量机以一种独特的方式实现,一旦它们基于对什么是学习的统计解释,或者 统计学习理论.

在本文中,我们将了解什么是支持向量机算法、支持向量机背后的简要理论,以及它们在 Python 的 Scikit-Learn 库中的实现。 然后我们将转向另一个 SVM 概念,称为 内核支持向量机内核技巧, 并且还将在 Scikit-Learn 的帮助下实现它。

简单(线性)SVM 模型

关于数据集

按照介绍中给出的示例,我们将使用具有真实和伪造钞票图像测量值的数据集。

在看两张纸条时,我们的眼睛通常会从左到右扫视它们,看看哪里可能有相似之处或不同之处。 我们寻找绿点之前的黑点,或插图上方的闪亮标记。 这意味着我们查看笔记是有顺序的。 如果我们知道有绿点和黑点,但不知道绿点先于黑点,或者黑点先于绿点,那么区分音符就更难了。

有一种与我们刚才描述的方法类似的方法可以应用于钞票图像。 一般而言,此方法包括将图像的像素转换为信号,然后通过将其转换为小波来考虑每个不同信号在图像中发生的顺序,或者 小波. 获得小波后,有一种方法可以知道某个信号在另一个信号之前发生的顺序,或者 ,但不完全是什么信号。 要知道这一点,需要获得图像的频率。 它们是通过对每个信号进行分解的方法获得的,称为 傅里叶法.

通过小波得到时间维度,通过傅立叶方法得到频率维度,将时间和频率叠加,看两者何时匹配,这就是 卷积 分析。 卷积获得匹配,将小波与图像的频率相匹配,并找出哪些频率更突出。

这种涉及找到小波及其频率,然后对它们进行拟合的方法称为 小波变换. 小波变换具有系数,这些系数用于获取我们在数据集中的测量值。

导入数据集

我们将在本节中使用的钞票数据集与分类部分中使用的相同 决策树教程.

请注意: 您可以下载数据集 相关信息.

让我们将数据导入熊猫 dataframe 结构,看看它的前五行 head() 方法。

请注意,数据保存在 txt (文本)文件格式,以逗号分隔,并且没有标题。 我们可以通过将其读取为表格来将其重建为表格 csv,指定 separator 作为逗号,并添加列名 names 论据。

让我们同时执行这三个步骤,然后查看数据的前五行:

import pandas as pd data_link = "https://archive.ics.uci.edu/ml/machine-learning-databases/00267/data_banknote_authentication.txt"
col_names = ["variance", "skewness", "curtosis", "entropy", "class"] bankdata = pd.read_csv(data_link, names=col_names, sep=",", header=None)
bankdata.head()

结果是:

	variance skewness curtosis entropy class
0 3.62160 8.6661 -2.8073 -0.44699 0
1 4.54590 8.1674 -2.4586 -1.46210 0
2 3.86600 -2.6383 1.9242 0.10645 0
3 3.45660 9.5228 -4.0112 -3.59440 0
4 0.32924 -4.4552 4.5718 -0.98880 0

请注意: 您也可以将数据保存在本地并替换 data_link data_path,并传入本地文件的路径。

我们可以看到我们的数据集中有五列,即 variance, skewness, curtosis, entropyclass. 在五行中,前四列用数字填充,例如 3.62160、8.6661、-2.8073 或 连续 价值观,最后 class 列的前五行用 0 填充,或者 离散的 计算值。

由于我们的目标是预测一张银行纸币的真伪,我们可以根据纸币的四个属性来做到这一点:

  • variance 小波变换图像。 通常,方差是一个连续值,用于衡量数据点接近或远离数据平均值的程度。 如果这些点更接近数据的平均值,则分布更接近正态分布,这通常意味着它的值分布更均匀并且更容易预测。 在当前图像上下文中,这是小波变换产生的系数的方差。 方差越小,系数越接近翻译实际图像。

  • skewness 小波变换图像。 偏度是一个连续值,表示分布的不对称性。 如果均值左侧有更多值,则分布为 负面偏斜,如果均值右侧有更多值,则分布为 正偏,如果均值、众数和中位数相同,则分布为 对称. 分布越对称,它越接近正态分布,其值分布也越均匀。 在当前上下文中,这是由小波变换产生的系数的偏度。 越对称,我们的系数越接近variance, skewness, curtosis, entropy重新翻译实际图像。

使用 Python 的 Scikit-Learn PlatoBlockchain 数据智能实现 SVM 和内核 SVM。垂直搜索。人工智能。

  • curtosis 小波变换图像的(或峰态)。 峰态是一个连续值,与偏度一样,也描述了分布的形状。 根据峰态系数 (k),分布(与正态分布相比可能或多或少平坦)或在其末端或尾部有或多或少的数据。 当分布更加分散和平坦时,它被称为 斜坡式的; 当它不那么分散而更集中在中间时, 中斜坡; 当分布几乎完全集中在中间时,称为 轻斜峰. 这与方差和偏度先验情况相同,分布越偏斜,系数越接近平移实际图像。

使用 Python 的 Scikit-Learn PlatoBlockchain 数据智能实现 SVM 和内核 SVM。垂直搜索。人工智能。

  • entropy 图像。 熵也是一个连续值,它通常衡量一个系统的随机性或无序性。 在图像的上下文中,熵测量像素与其相邻像素之间的差异。 对于我们的上下文,系数的熵越大,图像变换时的损失就越大——熵越小,信息损失越小。

使用 Python 的 Scikit-Learn PlatoBlockchain 数据智能实现 SVM 和内核 SVM。垂直搜索。人工智能。

第五个变量是 class 变量,可能有 0 和 1 值,表示纸币是真实的还是伪造的。

我们可以用 Pandas 检查第五列是否包含零和一 unique() 方法:

bankdata['class'].unique()

上述方法返回:

array([0, 1]) 

上面的方法返回一个包含 0 和 1 值的数组。 这意味着我们的类行中包含的唯一值是零和一。 它已准备好用作 目标 在我们的监督学习中。

  • class 图像。 这是一个整数值,图像为伪造时为0,图像为真实时为1。

由于我们有一列包含真实图像和遗忘图像的注释,这意味着我们的学习类型是 监督.

建议: 要了解有关钞票图像小波变换背后的推理和 SVM 的使用的更多信息,请阅读作者发表的论文。

我们还可以通过查看数据中的行数来查看我们有多少条记录或图像 shape 属性:

bankdata.shape

输出:

(1372, 5)

上一行表示转换后的纸币图像有 1,372 行和 5 列。 这是我们要分析的数据。

我们已经导入了我们的数据集并进行了一些检查。 现在我们可以探索我们的数据以更好地理解它。

探索数据集

我们刚刚看到类列中只有 XNUMX 和 XNUMX,但我们也可以知道它们的比例是多少——换句话说——如果 XNUMX 多于 XNUMX,XNUMX 多于 XNUMX,或者如果zeros 与 ones 的数量相同,这意味着它们是 均衡.

要知道我们可以计算数据中每个零值和一值的比例 value_counts() 方法:

bankdata['class'].value_counts()

输出:

0 762
1 610
Name: class, dtype: int64

在上面的结果中,我们可以看到有 762 个零和 610 个一,或者说零比一多 152 个。 这意味着我们伪造的图像比真实图像多一点,如果差异更大,例如 5500 个零和 610 个 XNUMX,它可能会对我们的结果产生负面影响。 一旦我们尝试在我们的模型中使用这些示例——示例越多,通常意味着模型必须在伪造或真实笔记之间做出决定的信息越多——如果真实笔记示例很少,则模型很容易试图认出他们时弄错了。

我们已经知道还有 152 张伪造的纸币,但我们能确定这些是模型学习的足够示例吗? 知道学习需要多少示例是一个很难回答的问题,相反,我们可以尝试以百分比来理解类之间的差异有多大。

第一步是使用熊猫 value_counts() 再次方法,但现在让我们通过包含参数来查看百分比 normalize=True:

bankdata['class'].value_counts(normalize=True)

normalize=True 计算每个类的数据百分比。 到目前为止,伪造数据(0)和真实数据(1)的百分比为:

0 0.555394
1 0.444606
Name: class, dtype: float64

这意味着大约 (~) 56% 的数据集是伪造的,其中 44% 是真实的。 这给了我们 56%-44% 的比率,这与 12% 的差异相同。 这在统计上被认为是一个很小的差异,因为它只是略高于 10%,所以数据被认为是平衡的。 如果不是 56:44 的比例,而是 80:20 或 70:30 的比例,那么我们的数据就会被认为是不平衡的,我们需要做一些不平衡的处理,但幸运的是,情况并非如此。

我们还可以直观地看到这种差异,通过使用 Pandas 注入直方图查看类或目标的分布,使用:

bankdata['class'].plot.hist();

这将直接使用数据帧结构绘制直方图,并结合 matplotlib 幕后的图书馆。

使用 Python 的 Scikit-Learn PlatoBlockchain 数据智能实现 SVM 和内核 SVM。垂直搜索。人工智能。

通过查看直方图,我们可以确定我们的目标值为 0 或 1,并且数据是平衡的。

这是对我们试图预测的列的分析,但如何分析我们数据的其他列呢?

我们可以看看统计测量结果 describe() 数据框方法。 我们也可以使用 .T of transpose – 反转列和行,使其更直接地比较值:

查看我们的 Git 学习实践指南,其中包含最佳实践、行业认可的标准以及随附的备忘单。 停止谷歌搜索 Git 命令,实际上 学习 它!

bankdata.describe().T

结果是:

 count mean std min 25% 50% 75% max
variance 1372.0 0.433735 2.842763 -7.0421 -1.773000 0.49618 2.821475 6.8248
skewness 1372.0 1.922353 5.869047 -13.7731 -1.708200 2.31965 6.814625 12.9516
curtosis 1372.0 1.397627 4.310030 -5.2861 -1.574975 0.61663 3.179250 17.9274
entropy 1372.0 -1.191657 2.101013 -8.5482 -2.413450 -0.58665 0.394810 2.4495
class 1372.0 0.444606 0.497103 0.0000 0.000000 0.00000 1.000000 1.0000

请注意,偏度和弯曲度列的平均值与标准差值相去甚远,这表明这些值离数据的集中趋势更远,或者具有更大的可变性。

我们还可以通过在 for 循环中绘制每个特征的直方图来直观地查看每个特征的分布。 除了查看分布之外,查看每个类的点如何根据每个特征分开也会很有趣。 为此,我们可以绘制一个散点图,将它们之间的特征组合起来,并根据其类别为每个点分配不同的颜色。

让我们从每个特征的分布开始,绘制每个数据列的直方图,除了 class 柱。 的 class 列在 bankdata 列数组中的位置不会被考虑在内。 除了最后一列外,所有列都将被选中 columns[:-1]:

import matplotlib.pyplot as plt for col in bankdata.columns[:-1]: plt.title(col) bankdata[col].plot.hist() plt.show();

运行上面的代码后,我们可以看到两者 skewnessentropy 数据分布呈负偏态 curtosis 是正偏的。 所有分布都是对称的,并且 variance 是唯一接近正态的分布。

我们现在可以继续第二部分,绘制每个变量的散点图。 为此,我们还可以选择除类别之外的所有列,使用 columns[:-1], 使用 Seaborn 的 scatterplot() 和两个 for 循环以获得每个特征的配对变化。 我们还可以通过测试第一个特征是否等于第二个特征来排除特征与自身的配对 if statement.

import seaborn as sns for feature_1 in bankdata.columns[:-1]: for feature_2 in bankdata.columns[:-1]: if feature_1 != feature_2: print(feature_1, feature_2) sns.scatterplot(x=feature_1, y=feature_2, data=bankdata, hue='class') plt.show();

请注意,所有图表都有真实和伪造的数据点,彼此之间没有明确区分,这意味着存在某种类的叠加。 由于 SVM 模型使用一条线来分隔类,是否可以仅使用一条线来分隔图中的任何组? 这似乎不太可能。 这就是大多数真实数据的样子。 我们最接近分离的组合是 skewnessvarianceentropyvariance 地块。 这可能是由于 variance 具有更接近正态分布形状的数据。

但是按顺序查看所有这些图表可能有点困难。 我们可以选择使用 Seaborn 的工具一起查看所有分布图和散点图 pairplot().

我们之前完成的两个 for 循环都可以用这一行代替:

sns.pairplot(bankdata, hue='class');

看着 pairplot,似乎,实际上, curtosisvariance 将是最简单的功能组合,因此不同的类可以用一条线分隔,或者 线性可分.

如果大多数数据远非线性可分,我们可以尝试通过降低其维度对其进行预处理,并将其值归一化以尝试使分布更接近正态分布。

对于这种情况,让我们按原样使用数据,不做进一步的预处理,稍后,我们可以返回一步,加入数据预处理并比较结果。

建议: 在处理数据时,信息通常会在转换时丢失,因为我们是在进行近似,而不是收集更多数据。 如果可能的话,首先使用初始数据,在尝试其他预处理技术之前提供一个基线。 遵循此路径时,可以将使用原始数据的初始结果与对数据使用预处理技术的另一个结果进行比较。

请注意: 通常在统计学中,在构建模型时,通常会根据数据的种类(离散、连续、分类、数值)、分布和模型假设遵循一个过程。 在计算机科学 (CS) 中,有更多的空间用于试验、错误和新的迭代。 在 CS 中,通常有一个基准来进行比较。 在 Scikit-learn 中,有一个虚拟模型(或虚拟估计器)的实现,有些并不比掷硬币好,只是回答 (或 1)50% 的时间。 在比较结果时,使用虚拟模型作为实际模型的基线是很有趣的。 预计实际模型结果要好于随机猜测,否则就没有必要使用机器学习模型。

使用 Scikit-Learn 实现 SVM

在深入了解 SVM 工作原理之前,我们可以使用数据构建我们的第一个基线模型,以及 Scikit-Learn 的 支持向量分类器 or SVC 类。

我们的模型将接收小波系数并尝试根据类别对它们进行分类。 这个过程的第一步是分离系数或 功能 来自班级或 目标. 在那一步之后,第二步是将数据进一步划分为一组,用于模型的学习或 动车组 另一个将用于模型的评估或 测试集.

请注意: 测试和评估的命名可能有点混乱,因为您还可以在训练集、评估集和测试集之间拆分数据。 通过这种方式,您将拥有一个中间集,而不是拥有两个集,只是为了使用并查看您的模型的性能是否正在增强。 这意味着模型将使用训练集进行训练,使用评估集进行增强,并使用测试集获得最终指标。

有人说评估是那个中间集,也有人说测试集是中间集,评估集是最终集。 这是另一种尝试保证模型不会以任何方式看到相同示例的方法,或者某种 数据泄漏 没有发生,并且通过改进最后设置的指标存在模型泛化。 如果你想遵循这种方法,你可以进一步进一步划分数据一次,如 this 中所述 Scikit-Learn 的 train_test_split() – 训练、测试和验证集 指南。

将数据划分为训练/测试集

在上一节中,我们了解并探索了数据。 现在,我们可以将数据分成两个数组——一个用于四个特征,另一个用于第五个或目标特征。 由于我们想根据小波系数预测类别,我们的 y 将是 class 专栏和我们的 Xvariance, skewness, curtosisentropy 列。

为了分离目标和特征,我们可以只归因于 class 列至 y,稍后将其从数据框中删除以将剩余的列归因于 X .drop() 方法:

y = bankdata['class']
X = bankdata.drop('class', axis=1) 

一旦数据被划分为属性和标签,我们可以进一步将其划分为训练集和测试集。 这可以手动完成,但是 model_selection Scikit-Learn 库包含 train_test_split() 允许我们将数据随机划分为训练集和测试集的方法。

要使用它,我们可以导入库,调用 train_test_split() 方法,传入 Xy 数据,并定义一个 test_size 作为论据传递。 在这种情况下,我们将其定义为 0.20– 这意味着 20% 的数据将用于测试,另外 80% 用于训练。

此方法根据我们定义的百分比随机抽取样本,但尊重 Xy 对,以免抽样完全混淆关系。

由于采样过程本质上是随机的,因此在运行该方法时我们总会得到不同的结果。 为了能够获得相同的结果或可重现的结果,我们可以定义一个名为 SEED 的常量,其值为 42。

您可以执行以下脚本来执行此操作:

from sklearn.model_selection import train_test_split SEED = 42 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20, random_state = SEED)

注意, train_test_split() 方法已经返回 X_train, X_test, y_train, y_test 按此顺序设置。 我们可以通过获取第一个(0)元素来打印训练和测试分离的样本数 shape 属性返回的元组:

xtrain_samples = X_train.shape[0]
xtest_samples = X_test.shape[0] print(f'There are {xtrain_samples} samples for training and {xtest_samples} samples for testing.')

这表明有 1097 个样本用于训练,275 个样本用于测试。

训练模型

我们将数据分为训练集和测试集。 现在是时候在训练数据上创建和训练 SVM 模型了。 为此,我们可以导入 Scikit-Learn 的 svm 图书馆与 支持向量分类器 类,或 SVC 类。

导入类后,我们可以创建它的一个实例——因为我们正在创建一个简单的 SVM 模型,我们试图线性分离我们的数据,所以我们可以画一条线来划分我们的数据——这与使用一个相同 线性函数 – 通过定义 kernel='linear' 作为分类器的参数:

from sklearn.svm import SVC
svc = SVC(kernel='linear')

这样,分类器将尝试找到一个线性函数来分离我们的数据。 创建模型后,让我们训练它,或者 适合 它与火车数据一起使用 fit() 方法并给出 X_train 功能和 y_train 目标作为参数。

我们可以执行以下代码来训练模型:

svc.fit(X_train, y_train)

就这样,模型被训练好了。 到目前为止,我们已经理解了数据,对其进行了划分,创建了一个简单的 SVM 模型,并将该模型拟合到训练数据上。

下一步是了解拟合如何成功地描述我们的数据。 换句话说,回答线性 SVM 是否是一个合适的选择。

做出预测

回答模型是否成功描述数据的一种方法是计算和查看一些分类 度量.

考虑到学习是有监督的,我们可以用 X_test 并比较这些预测结果——我们可以称之为 y_pred – 与实际 y_test基本事实.

为了预测一些数据,模型的 predict() 可以采用方法。 此方法接收测试功能, X_test,作为参数并返回预测,0 或 1,对于每个 X_test的行。

预测后 X_test 数据,结果存储在一个 y_pred 多变的。 所以用简单线性 SVM 模型预测的每个类现在都在 y_pred 变量。

这是预测代码:

y_pred = svc.predict(X_test)

考虑到我们有预测,我们现在可以将它们与实际结果进行比较。

评估模型

有多种方法可以将预测与实际结果进行比较,它们可以衡量分类的不同方面。 一些最常用的分类指标是:

  1. 混淆矩阵:当我们需要知道我们正确或错误的样本数量时 每堂课. 正确且正确预测的值称为 真正的积极,那些被预测为阳性但不是阳性的被称为 误报. 相同的命名法 真正的负面假阴性 用于负值;

  2. 平台精度:当我们的目标是了解我们的分类器认为哪些正确的预测值是正确的。 Precision 会将那些真阳性值除以预测为阳性的样本;

$$
精度 = frac{文本{真阳性}}{文本{真阳性} + 文本{假阳性}}
$$

  1. 记得:通常与精度一起计算,以了解我们的分类器识别了多少真阳性。 召回率是通过将真阳性除以任何应该被预测为阳性的值来计算的。

$$
召回率 = frac{文本{真阳性}}{文本{真阳性} + 文本{假阴性}}
$$

  1. F1分数: 是平衡的还是 谐波均值 精度和召回率。 最小值为 0,最大值为 1。当 f1-score 等于 1,这意味着所有类都被正确预测了——这是一个很难用真实数据获得的分数(几乎总是存在例外)。

$$
文本{f1-分数} = 2* 压裂{文本{精度} * 文本{召回}}{文本{精度} + 文本{召回}}
$$

我们已经熟悉了混淆矩阵、精确率、召回率和 F1 分数度量。 为了计算它们,我们可以导入 Scikit-Learn 的 metrics 图书馆。 这个库包含 classification_reportconfusion_matrix 方法,分类报告方法返回精度、召回率和 f1 分数。 两个都 classification_reportconfusion_matrix 可以很容易地用于找出所有这些重要指标的值。

为了计算指标,我们导入方法,调用它们并将预测的分类作为参数传递, y_test和分类标签,或 y_true.

为了更好地可视化混淆矩阵,我们可以将其绘制在 Seaborn 的 heatmap 连同数量注释,对于分类报告,最好打印它的结果,所以它的结果是格式化的。 这是以下代码:

from sklearn.metrics import classification_report, confusion_matrix cm = confusion_matrix(y_test,y_pred)
sns.heatmap(cm, annot=True, fmt='d').set_title('Confusion matrix of linear SVM') print(classification_report(y_test,y_pred))

这显示:

 precision recall f1-score support 0 0.99 0.99 0.99 148 1 0.98 0.98 0.98 127 accuracy 0.99 275 macro avg 0.99 0.99 0.99 275
weighted avg 0.99 0.99 0.99 275

使用 Python 的 Scikit-Learn PlatoBlockchain 数据智能实现 SVM 和内核 SVM。垂直搜索。人工智能。

在分类报告中,我们知道伪造纸币的精度为 0.99,召回率为 0.99,f1 分数为 0.99,即 0 类。这些测量值是使用 148 个样本获得的,如支持栏中所示。 同时,对于 1 类或真实笔记,结果低于一个单位,精度为 0.98,召回率为 0.98,f1 分数相同。 这一次,使用了 127 个图像测量来获得这些结果。

如果我们查看混淆矩阵,我们还可以看到,在 148 个 0 类样本中,有 146 个被正确分类,有 2 个误报,而对于 127 个 1 类样本,有 2 个误报和 125 个真阳性。

我们可以阅读分类报告和混淆矩阵,但它们是什么意思?

解释结果

为找出其含义,让我们综合查看所有指标。

几乎所有类别 1 的样本都被正确分类,我们的模型在识别实际纸币时有 2 个错误。 这与 0.98 或 98% 的召回率相同。 类 0 也有类似的情况,只有 2 个样本被错误分类,而 148 个是真阴性,总计精度为 99%。

除了这些结果之外,所有其他人都标记为 0.99,几乎是 1,这是一个非常高的指标。 大多数时候,当现实生活中的数据出现如此高的指标时,这可能表明模型对数据进行了过度调整,或者 过拟合.

当出现过度拟合时,模型在预测已知数据时可能效果很好,但它失去了泛化到新数据的能力,这在现实世界场景中很重要。

快速测试以确定是否发生过拟合也可以使用训练数据。 如果模型稍微记住了火车数据,则指标将非常接近 1 或 100%。 请记住,训练数据大于测试数据——出于这个原因——尝试按比例查看它,样本越多,出错的机会就越大,除非出现过拟合。

要用训练数据进行预测,我们可以重复对测试数据所做的操作,但现在使用 X_train:

y_pred_train = svc.predict(X_train) cm_train = confusion_matrix(y_train,y_pred_train)
sns.heatmap(cm_train, annot=True, fmt='d').set_title('Confusion matrix of linear SVM with train data') print(classification_report(y_train,y_pred_train))

输出:

 precision recall f1-score support 0 0.99 0.99 0.99 614 1 0.98 0.99 0.99 483 accuracy 0.99 1097 macro avg 0.99 0.99 0.99 1097
weighted avg 0.99 0.99 0.99 1097

使用 Python 的 Scikit-Learn PlatoBlockchain 数据智能实现 SVM 和内核 SVM。垂直搜索。人工智能。

很容易看出似乎存在过度拟合,一旦训练指标在拥有 99 倍多的数据时达到 4%。 在这种情况下可以做什么?

为了恢复过拟合,我们可以添加更多的训练观察,使用一种对数据集的不同部分进行训练的方法,例如 交叉验证,并在创建我们的模型时更改训练之前已经存在的默认参数,或者 超参数. 大多数时候,Scikit-learn 将一些参数设置为默认值,如果没有太多时间专门用于阅读文档,这可能会悄悄发生。

您可以查看本指南的第二部分(即将推出!) 了解如何实施交叉验证和执行超参数调整。

结论

在本文中,我们研究了简单的线性核 SVM。 我们了解了 SVM 算法背后的直觉,使用了一个真实的数据集,探索了数据,并了解了如何通过使用 Python 的 Scikit-Learn 库实现这些数据来将其与 SVM 一起使用。

为了继续练习,您可以尝试使用其他真实世界的数据集,例如 Kaggle, 国际自盟, Big Query 公共数据集、大学和政府网站。

我还建议您探索 SVM 模型背后的实际数学原理。 虽然您不一定需要它来使用 SVM 算法,但在您的算法寻找决策边界时了解幕后实际发生的事情仍然非常方便。

时间戳记:

更多来自 堆栈滥用