支持向量机可能是最流行和最受关注的机器学习算法之一。
它们在 20 世纪 90 年代开发时非常流行,并且仍然是高性能算法的首选方法,只需少量调整。
在这篇文章中,您将了解支持向量机 (SVM) 机器学习算法。阅读本文后您将了解:
- 如何区分用于指代支持向量机的许多名称。
- 当模型实际存储在磁盘上时,SVM 使用的表示。
- 如何使用学习到的 SVM 模型表示来对新数据进行预测。
- 如何从训练数据中学习 SVM 模型。
- 如何为 SVM 算法最好地准备您的数据。
- 在哪里可以找到更多关于 SVM 的信息。
SVM 是一种令人兴奋的算法,其概念相对简单。这篇文章是为几乎没有统计和线性代数背景的开发人员编写的。
因此,我们将在此描述中保持高层次,并侧重于具体的实现问题。关于为什么使用特定方程或如何推导它们的问题未涵盖,您可能希望在进一步阅读部分深入研究。
通过我的新书《掌握机器学习算法》启动您的项目,其中包括所有示例的分步教程和Excel 电子表格文件。
让我们开始吧。

机器学习中的支持向量机
照片作者:Francisco Barberis,保留部分权利。
最大间隔分类器
最大间隔分类器是一个假设的分类器,它最能解释 SVM 在实践中是如何工作的。
数据中(列)的数字输入变量(x)形成一个 n 维空间。例如,如果您有两个输入变量,这将形成一个二维空间。
超平面是分割输入变量空间的直线。在 SVM 中,选择一个超平面以通过它们的类别(类别 0 或类别 1)最好地分离输入变量空间中的点。在二维中,您可以将其可视化为一条线,让我们假设所有输入点都可以被这条线完全分离。例如:
B0 + (B1 * X1) + (B2 * X2) = 0
其中系数(B1 和 B2)决定线的斜率,截距(B0)由学习算法找到,X1 和 X2 是两个输入变量。
您可以使用这条线进行分类。通过将输入值插入到线方程中,您可以计算新点是在线上方还是下方。
- 在线上方,方程返回一个大于 0 的值,该点属于第一类(类别 0)。
- 在线下方,方程返回一个小于 0 的值,该点属于第二类(类别 1)。
- 靠近线的值返回一个接近零的值,该点可能难以分类。
- 如果值的幅度很大,模型可能对预测更有信心。
线与最近数据点之间的距离称为间隔。能够分离两个类别的最佳或最优线是具有最大间隔的线。这称为最大间隔超平面。
间隔计算为从线到最近点的垂直距离。只有这些点与定义线和构建分类器相关。这些点称为支持向量。它们支持或定义了超平面。
超平面是通过最大化间隔的优化过程从训练数据中学习的。
获取您的免费算法思维导图

方便的机器学习算法思维导图样本。
我创建了一份方便的思维导图,其中包含60多种按类型组织的算法。
下载、打印并使用它。
还可以独家访问机器学习算法电子邮件迷你课程。
软间隔分类器
实际上,真实数据是混乱的,无法用超平面完美分离。
必须放宽最大化分离类别的线间隔的约束。这通常称为软间隔分类器。这种改变允许训练数据中的某些点违反分离线。
引入了额外的系数集,为每个维度的间隔提供了“摆动空间”。这些系数有时称为松弛变量。这增加了模型的复杂性,因为模型有更多的参数来拟合数据以提供这种复杂性。
引入了一个名为 C 的调整参数,它定义了所有维度上允许的摆动幅度。C 参数定义了允许违反间隔的程度。C=0 表示没有违反,我们回到了上面描述的刚性最大间隔分类器。C 的值越大,允许违反超平面的次数越多。
在从数据中学习超平面的过程中,所有位于间隔距离内的训练实例都会影响超平面的位置,并被称为支持向量。由于 C 影响允许落在间隔内的实例数量,因此 C 影响模型使用的支持向量数量。
- C 的值越小,算法对训练数据越敏感(方差越高,偏差越低)。
- C 的值越大,算法对训练数据越不敏感(方差越低,偏差越高)。
支持向量机(核函数)
SVM 算法在实践中是使用核函数实现的。
线性 SVM 中超平面的学习是通过使用一些线性代数来转换问题来完成的,这超出了本 SVM 介绍的范围。
一个强大的洞察是,线性 SVM 可以用任意两个给定观测值的内积来重新表述,而不是观测值本身。两个向量的内积是每对输入值乘积的总和。
例如,向量 [2, 3] 和 [5, 6] 的内积是 2*5 + 3*6 或 28。
使用输入 (x) 和每个支持向量 (xi) 之间的点积对新输入进行预测的方程计算如下:
f(x) = B0 + sum(ai * (x,xi))
这是一个涉及计算新输入向量 (x) 与训练数据中所有支持向量内积的方程。系数 B0 和 ai(对于每个输入)必须由学习算法从训练数据中估计出来。
线性核函数 SVM
点积被称为核函数,可以改写为
K(x, xi) = sum(x * xi)
核函数定义了新数据和支持向量之间的相似度或距离度量。点积是用于线性 SVM 或线性核函数的相似度度量,因为距离是输入的线性组合。
可以使用其他核函数将输入空间转换为更高维度,例如多项式核函数和径向核函数。这被称为核技巧。
使用更复杂的核函数是可取的,因为它允许线分离曲线甚至更复杂的类别。这反过来可以产生更准确的分类器。
多项式核函数 SVM
除了点积,我们还可以使用多项式核函数,例如
K(x,xi) = 1 + sum(x * xi)^d
其中多项式的次数必须手动指定给学习算法。当 d=1 时,这与线性核函数相同。多项式核函数允许输入空间中存在曲线。
径向核函数 SVM
最后,我们还可以有一个更复杂的径向核函数。例如
K(x,xi) = exp(-gamma * sum((x – xi)^2))
其中 gamma 是必须指定给学习算法的参数。gamma 的一个好的默认值是 0.1,其中 gamma 通常在 0 < gamma < 1 之间。径向核函数具有很强的局部性,可以在特征空间中创建复杂的区域,例如二维空间中的封闭多边形。
如何学习 SVM 模型
SVM 模型需要使用优化过程来求解。
您可以使用数值优化过程来搜索超平面的系数。这是低效的,并且不是 LIBSVM 等广泛使用的 SVM 实现中使用的方法。如果将算法作为练习来实现,您可以使用随机梯度下降。
存在将优化问题重新表述为二次规划问题的专用优化过程。拟合 SVM 最流行的方法是序贯最小优化 (SMO) 方法,它非常高效。它将问题分解为可以解析求解(通过计算)而不是数值求解(通过搜索或优化)的子问题。
SVM 的数据准备
本节列出了一些关于在学习 SVM 模型时如何最好地准备训练数据的建议。
- 数值输入:SVM 假设您的输入是数值型的。如果您有分类输入,您可能需要将它们转换为二进制虚拟变量(每个类别一个变量)。
- 二元分类:本文描述的基本 SVM 旨在解决二元(两类)分类问题。但是,已经开发了用于回归和多类分类的扩展。
进一步阅读
支持向量机是一个巨大的研究领域。关于这个主题有大量的书籍和论文。本节列出了一些如果您想深入了解该技术的背景和理论,最重要和最有用的成果。
Vladimir Vapnik 是这项技术的发明者之一,他有两本书被认为是该主题的开创性著作。它们非常数学化且严谨。
- 《统计学习理论的本质》,Vapnik,1995
- 《统计学习理论》,Vapnik,1998
任何好的机器学习书籍都会涵盖 SVM,下面是我最喜欢的一些。
- 《统计学习导论:R 语言应用》,第八章
- 《应用预测建模》,第十三章
- 《统计学习要素:数据挖掘、推断和预测》,第十二章
有无数关于 SVM 的教程和期刊文章。下面是 Cortes 和 Vapnik 关于 SVM 的一篇开创性论文的链接,以及另一篇优秀的入门教程。
- 支持向量网络 [PDF] Cortes 和 Vapnik 1995
- 模式识别的支持向量机教程 [PDF] 1998
维基百科提供了关于该主题的一些好的(尽管内容密集)信息
最后,问答网站上有很多帖子在寻求 SVM 的简单解释,下面是两个您可能会觉得有用的精选。
总结
在这篇文章中,您了解了机器学习中的支持向量机算法。您了解了
- 最大间隔分类器,它提供了一个简单的理论模型来理解 SVM。
- 软间隔分类器,它是最大间隔分类器的修改,用于放宽间隔以处理实际数据中嘈杂的类别边界。
- 支持向量机以及学习算法如何重新表述为点积核函数,以及如何使用多项式和径向等其他核函数。
- 如何使用数值优化来学习超平面,以及高效实现如何使用称为序贯最小优化的替代优化方案。
您对 SVM 或这篇文章有任何疑问吗?
请在评论中提问,我将尽力回答。
嗨,Jason,
一如既往地感谢您的出色教程。我有一个关于参数 C 的问题。
您提到较低的 C 会使模型对训练数据更敏感。我的理解是超平面会随着 C 的小值而摆动。
然而,在 scikit-learn 中,它指出“低 C 使决策面平滑,而高 C 旨在正确分类所有训练示例。” (https://scikit-learn.cn/stable/modules/svm.html#parameters-of-the-rbf-kernel)
我很困惑哪个是正确的。您能解释一下吗?
提前感谢。
谢谢 Qichang。
我也觉得 scikit-learn 的描述令人困惑。也许这是一个修改过的实现。
嗨,杰森。我的问题是关于另一个事情。我正在尝试使用 SVM 预测个体患癌症的可能性。在尝试拟合模型时出现了错误。错误提示无法将字符串转换为浮点数。我该如何处理?
或许确认您的 CSV 文件中的数据是数字格式的?
嗨,Jason,
我在 Andrew Ng 的机器学习课程中找到了 SVM 的笔记 (http://www.holehouse.org/mlclass/12_Support_Vector_Machines.html)
它指出
大 C 值导致低偏差高方差的假设 -> 过拟合
小 C 值导致高偏差低方差的假设 -> 欠拟合
这与 scikit-learn 的描述一致。C 的定义是 lambda 的倒数,这样讲得通。
很棒的发现,谢谢 Qichang。我会调查并修正我的解释。
我的理解基于《统计学习导论》第 347 页,其中指出
这与我上面写的一致。
我也有同样的问题,根据一些测试,我发现
随着成本降低,边距增加,这允许更多的违规,这意味着高偏差和低方差。
嗨,Jason,
恐怕情况恰恰相反
– C 参数值大表示窄间隔、高方差和低偏差。
– C 参数值小表示宽间隔、高偏差和低方差。
诚挚的问候,
雷达
谢谢,你根据什么得出这个结论?
嗨,Jason,
抱歉,您完全正确,我忘记提及我的来源。
关于 C 对偏差和方差的影响,
您可以查看 Andrew Ng 教授关于 SVM 的讲座
https://www.youtube.com/watch?v=XfyR_49hfi8 (大约 13:00)。
您还可以阅读《Python 机器学习、机器学习和深度学习与 Python、scikit-learn 和 Tensorflow》一书中的一些解释(第 79 和 80 页)。
关于 C 如何影响间隔,您可以使用 scikitlearn 的 LibSVM GUI 进行操作
例如,您可以测试线性可分数据 C=1 和 C=0.001,您会观察到对于较小的 C,间隔更大。
https://scikit-learn.cn/stable/auto_examples/applications/svm_gui.html
这里还有一些解释
https://scikit-learn.cn/stable/auto_examples/svm/plot_svm_margin.html
诚挚的问候,
雷达
谢谢,我会调查。
谢谢 Qichang。感谢您澄清 C 的变化。因为 C 是一个正则化参数,其大值会减少误分类,这可能导致过拟合,从而导致更高的方差。
相信我,C 和 Gamma 的变化在整个机器学习中让我最困惑。我仍然无法理解 gamma 的作用。
如果您能在这里解释 gamma 的作用及其变化(低和高),我将不胜感激 @Jason 和您。
感谢您的建议,我希望将来能更深入地研究 SVM。
Jason,谢谢你的精彩教程。阅读了一些关于 SVM 的文章后,我仍然不知道支持向量机和支持向量网络之间的区别。事实上,我只找到关于支持向量机的文章。似乎没有关于支持向量网络的论文。如果你知道区别,能解释一下吗?谢谢。
SVM 是主要方法。
抱歉,我没有听说过支持向量网络。
谢谢您的回复。没关系。我也很惊讶支持向量网络的存在。我只是从 Vladimir Vapnik 撰写的一篇名为《支持向量网络》的论文中得知它。
我是机器学习新手,因此需要您的帮助来理解一个问题,因为我正在缓慢地阅读、练习和理解。顺便说一下,抱歉我的英语不好。我有一些怀孕及其结果的数据(大约 200,000 条)。我拥有 ANC、资产和教育信息作为自变量,机构分娩作为因变量。我尝试了逻辑回归算法,但准确率(78%)不尽如人意。因为我知道它们之间应该有很强的关系。我的问题是,我应该尝试 SVM 还是其他算法?如果是其他算法,那么是哪一个?
这个过程将帮助你系统地解决你的预测建模问题
https://machinelearning.org.cn/start-here/#process
你好 Jason,
我对支持向量机有以下疑问
1. 当我阅读这个 (https://en.m.wikipedia.org/wiki/Support_vector_machine)
博客时,我发现了关于软间隔分类器的以下几点
为了将 SVM 扩展到数据不是线性可分的情况,我们引入了铰链损失函数。那么,这是否意味着软间隔分类器是非线性分类器?
2. 在上述维基百科博客的计算 SVM 分类器部分,我读到我们可以使用原始或对偶(支持 SMO 算法)方法?那么,为了使用 LibSVM 工具作为优化过程,是否必须将优化目标设置为对偶形式?
嗨,Jason,
我有一个包含“失败”或“通过”两种分类器的测试用例数据,对于这些数据,我能够分类它是“通过”还是“失败”,之后我获得了包含“失败”或“通过”以及“未知”测试用例状态的数据,我们不知道它是“通过”还是“失败”。
如何处理这种在数据集中未给出测试用例状态的情况,使用 SVM。
请在这种情况下提供帮助。
您不能在没有输入结果的数据上训练模型。
嘿,杰森!您的帖子真的很有帮助!我有一个关于分类和数值变量中缺失数据的问题。SVM 或任何其他分类或回归模型如何处理它?这些值应该被插补吗?如果是,我们如何插补它们?这是我们在实际问题中会遇到的问题,但似乎很少有人真正解释如何处理它。如果您能分享您的知识和经验,对我们所有机器学习初学者来说都非常有帮助。
请提供任何关于一类 SVM 的教程,我想使用网格搜索计算一类 SVM 的 gamma 值。
请为我的这个需求推荐任何教程。
感谢您的建议。
嘿,杰森,
您能提供多项式核函数和径向核函数方程所用的参考文献吗?非常感谢您
当然
https://en.wikipedia.org/wiki/Radial_basis_function_kernel
谢谢杰森!
我还有一个问题,杰森,我一直在想为什么在径向核函数公式中我们只对支持向量 xi 求平方,我认为这是两个变量 x 和 xi 的欧几里德距离,所以我们必须对它们分量的差值求平方,而不仅仅是支持向量?非常感谢。
哈喽,杰森先生
您愿意从头开始用 Python 构建 SVM 吗?这很难吗?
我的算法书里确实有一个例子,它很有挑战性,但如果你使用次梯度下降法,它会更容易。
嗨,杰森,哪本书???我搜索了一下,但没有在您的书中找到这个从零开始的 Python SVM...
非常感谢..
这本有 SVM:https://machinelearning.org.cn/master-machine-learning-algorithms/
使用 SVR 解决了一个回归问题,在测试数据上得到了不错的拟合,但在测试中表现不佳。超参数使用 Gridsearchcv 进行调优。可能的原因是什么?
手动更改了 C、gamma 和 epsilon,范围很广。Gamma 对 SVR 的影响很小吗?
也许尝试其他数据准备方法?
也许尝试其他模型?
嗨,Jason,
我遇到的情况是,我有 p 个变量,总共有 q 个变量,并且想对每个 p 变量预测 n 天:这是一个使用 SVR 的多元预测问题。一个解决方案是为每个 p 构建模型,使用 q 和 p 组合来预测 p 的 n 天。另一个解决方案是一次性构建和训练所有模型。我愿意选择后者。我在设置 X_train 和 y_train 时遇到了麻烦。对于单变量预测,您只需创建一个带有时移 n 天的新列。X 集将是 q 列,y 集将是新列。我不知道如何为多元预测设置 X、y 以及因此设置 X_train、y_train。
有什么关于如何处理这个问题的想法吗?
再次感谢!
好问题。
你可以用这个来准备建模数据
https://machinelearning.org.cn/convert-time-series-supervised-learning-problem-python/
我建议然后分割数据以保持时间一致性,例如,你只预测未来,只训练过去。
理想情况下,您将使用前向验证
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
这里还有另一个不错的教程,包含 Python 代码和从头开始的数学推导……
http://www.adeveloperdiary.com/data-science/machine-learning/support-vector-machines-for-beginners-linear-svm/
感谢分享。
嗨,Jason,
我看到一篇文章说,给定 n 个特征和 m 个观测值,如果 n >> m,我们应该使用逻辑回归;如果 n << m,我们应该使用 SVM。这是真的吗?如果是,为什么?提前感谢!
我以前没听说过,也许可以问问帖子作者是否有参考文献?
感谢您的精彩解释,文章写得非常好,对我的 SVM 学习帮助很大!!
来自巴西 😀
不客气!
亲爱的布朗利博士,
我非常感谢您的努力和高质量的成果。这些材料非常丰富。
我开始为我的问题使用一套机器学习工具,我有一个问题。我的数据集大小是 30 个样本 A 和 30 个样本 B。我想执行二元分类。对于这么小的数据集,使用 SVM 有意义吗?
我非常感谢您能提供的任何帮助。
谢谢!
是的,尽管我建议测试一系列不同的算法,以便找出最适合您的数据集的算法。
非常感谢您,Jason Brownlee。您的技术教程非常棒,我关注它们已经很久了。🙂
谢谢!
虽然这是一个非常好的总结,但对于像我这样的初学者来说,它缺乏直观、说明性的图表(就像您的许多帖子一样),这些图表有助于我理解。
谢谢。
亲爱的布朗利博士,
你有没有使用 Google net 训练 cifar10 数据集的例子?之后,使用 svm 打印决策边界
也许从这里开始
https://machinelearning.org.cn/how-to-develop-a-cnn-from-scratch-for-cifar-10-photo-classification/
你好,我目前正在按照您的书从头开始实现机器学习算法。我已经学到了 SVM 模型及其实现。
现在,先生,我有几个问题
1. 您展示的例子是在去除 B0(截距)之后解决 SVM 分类的,说我们的数据集很简单,为了简化解释我们将其去除。现在,如果我想添加 B0,我如何将其添加到这个 ↓ 公式中?
输出 = Y x (B1 x X1) + (B2 x X2)
我只是在那里添加 B0 吗?如果我把它添加到那里,那么后续函数在次梯度下降中更新 B0 的值会有什么变化?
2. 您讨论的例子似乎没有使用任何核函数,如果我们要使用径向核函数,那么我们将在哪个步骤使用核函数?
—
感谢您的精彩书籍和简单解释。阅读您的书后,我对机器学习算法更有信心了。如果可能的话,请解决我关于该主题的小疑问。
Aayush ∞ Shah,
印度
(1)我不确定你为什么那里有“Y x”,你的 Y 应该只是输出吗?
(2)核函数应用于 X,所以不是 B1 x X1,而是 B1 x f(X1),其中 f() 是核函数。
感谢您的回复,实际上“x”代表乘法。我用“x”而不是“*”,觉得会更清晰。但很抱歉造成歧义。
太好了,现在我得到了第二个问题的答案。您能尝试澄清我的第一个问题吗?
不,我明白那是乘法。我不明白的是为什么 Y 出现在输出方程中。
亲爱的团队,
非常感谢您的这篇文章。我有一个问题。SVR 中可以使用的最小特征数量有限制吗?我需要创建一个只有一个特征的非线性模型。我不能使用简单的回归(线性回归和多项式回归),因为我的输入特征和输出之间的关系是高度非线性的。在这种情况下我可以使用 SVR 吗?
使用适当的核函数,您可能会实现它。然而,只有一个特征且关系是非线性的情况下,为 SVM 找到这样的核函数可能不容易。您需要付出艰苦的努力和一些运气。
先生,多项式核函数和径向核函数是如何使用的?
请分享详细解释。
谢谢
先生,多项式核函数和径向核函数是如何使用的?
谢谢
嗨,Abel…以下资源可能会提供帮助
https://www.kdnuggets.com/2016/06/select-support-vector-machine-kernels.html
https://www.educba.com/what-is-kernel-in-machine-learning/