SVM核技巧核心原理图
1.定义
支持向量机(Support Vector Machine, SVM)是一种广泛应用于模式识别、分类以及回归问题的监督学习算法。它属于一种监督学习模型,其基本思想是在特征空间中寻找一个最优的分割超平面,以此来区分不同的类别。
SVM的主要特点包括:
-
最大间隔原则:SVM 试图找到一个分割超平面,使得距离这个超平面最近的来自不同类别的数据点(支持向量)之间的距离(即间隔)最大化。这样做的目的是为了提高模型的泛化能力。
-
支持向量:对于最优分割超平面,最近的数据点被称为支持向量。这些点是唯一影响最终决策边界的点,因为它们决定了超平面的位置和方向。
-
核技巧:SVM 通过所谓的“核技巧”能够
处理非线性可分问题。核函数可以将原始特征空间映射到一个更高维的空间,使得数据在这个新空间里线性可分。 -
正则化:SVM 通过引入正则化项控制模型的复杂度,以避免过拟合。
-
软间隔与硬间隔:在处理线性可分问题时,SVM 可以采用硬间隔,这意味着所有的训练数据都被正确分类。而在更一般的情况下,SVM 采用软间隔,允许一些数据点违反最大间隔原则,通过引入松弛变量来控制这些错误。(通俗一点解释,硬间隔就是当我们出现一个误差较大,偏离平均值的数据点的时候,硬间隔会将其直接考虑进去,分界的超平面也因此会受影响并可能导致增大算法模型的误差,而软间隔则是会将该偏差数据点按照一定的比例进行泛化吸收,减少了受该误差点的影响而导致模型偏离的结果,适当地增大了模型的容错率和泛化能力,所以一般我们都采用的是软间隔)
SVM的数学表述:
对于一个二分类问题,SVM 试图找到一个超平面,可以用如下的线性方程表示:
决策函数
决策函数 用于判断一个新的样本 属于正类还是负类。它的数学表达式是:
其中:
- 是超平面的法向量。
- 是特征空间中的点。
- 是偏置项(也称为截距或偏置)。
如果 ,样本 被分类为正类;如果 ,样本 被分类为负类。
目标函数
SVM的目标函数是优化问题的一部分,目的是找到一个超平面(其实就是为了找到最佳的值代入上述决策函数后使分类效果更准确),使得两个类别之间的间隔最大化。目标函数通常表示为:
其中:
- 是正则化项,用于避免过拟合(控制模型复杂度), 是法向量 的欧几里得范数。
- 是正则化参数,控制模型对误分类的惩罚力度。
- 是松弛变量,允许一些样本点违反间隔规则,以处理数据中的噪声和非线性可分性。
约束条件
约束条件确保了模型的间隔最大化原则,并且所有的样本点都满足以下条件:
其中:
- 是第 个样本的真实类别标签。
- 是第 个样本的特征向量。
- 是第 个样本的松弛变量。
这些约束条件保证了所有的样本点要么正确分类,要么至少在间隔边界内,或者通过松弛变量 允许一些误分类,但会在目标函数中受到惩罚。
总之:线性二分类SVM通过优化目标函数,同时满足约束条件,来找到最佳的决策边界(超平面)。决策函数 用于对新的样本进行分类。目标函数和约束条件共同定义了SVM模型的训练过程。通过求解这个优化问题,我们可以得到模型参数 和 ,进而得到决策函数。
由于SVM的数学推理过程极其复杂,所以在这里笔者决定省略掉大部分繁琐的数学公式推算转而用人话来描述数学原理和公式作用。(相关数学推理视频极力推荐B站数之道的系列视频)
支持向量机的工作原理:
SVM是一种监督学习算法,用于分类和回归问题。在分类问题中,SVM的目标是找到一个超平面,可以最优地将不同类别的样本分开。这个超平面的选择基于以下原则:
- 最大间隔:选择一个超平面,使得样本间的间隔最大化。
- 软间隔(一般采用):在处理非线性可分数据时,SVM允许一些样本违反最大间隔原则,这些样本称为“违规点”,SVM通过引入松弛变量来控制这些违规点的数量。
在优化过程中,SVM算法会找到一组系数,这些系数与支持向量相关联。最终的决策函数只依赖于这些系数和相应的支持向量,而与其他样本无关。
SVM的应用:
SVM 在许多领域都有应用,包括但不限于:
- 图像分类和识别
- 手写数字识别
- 文本分类和情感分析
- 生物信息学中的蛋白质结构预测
- 金融市场分析
SVM核函数的选择:
核函数的选择对SVM的性能有很大影响。一些常用的核函数包括:
- 线性核:适用于线性可分的数据。
- 多项式核:可以处理更复杂的数据关系。
- 径向基函数(RBF)核:也称为高斯核,适用于非线性数据。
- Sigmoid核:类似于神经网络中的激活函数。
选择哪种核函数通常需要根据具体问题和数据的特性来决定。
SVM是一种强大的分类算法,由于其在许多任务中表现出的优异性能,它已成为机器学习领域的一个标准工具。
2.算法组成
以下是SVM算法的组成部分:
-
数据点:SVM处理的是数据点,每个数据点通常由一组特征和一个标签组成。数据点可以是二维的,也可以是多维的。
-
特征空间:数据点所在的空间称为特征空间,其维度由数据点的特征数量决定。
-
超平面:SVM的目标是找到一个超平面,这个超平面能够将不同类别的数据点分开,并且使得两个类别之间的间隔最大化。(上图中中间的就是)
-
间隔:间隔是指数据点到超平面的距离。SVM试图最大化这个间隔,以提高模型的泛化能力。
-
支持向量:支持向量是距离超平面最近的那些数据点。它们决定了超平面的位置和方向。(上图中红色的边界点就是)
-
损失函数:SVM使用Hinge损失函数来计算损失,以确保模型能够正确分类数据点,并且间隔最大化。
-
核技巧:为了处理非线性可分的数据,SVM引入了核技巧。核函数可以将原始特征空间映射到更高维的空间,使得数据在新空间中线性可分。
-
正则化参数:SVM中的正则化参数(通常表示为C)控制着模型对误分类的惩罚程度。较大的C值意味着模型更关注于正确分类所有数据点,而较小的C值意味着模型更倾向于找到一个间隔更大的超平面。
-
优化算法:SVM的训练过程涉及到求解一个凸二次规划问题,这通常通过优化算法如SMO(Sequential Minimal Optimization)来完成。
-
模型参数:SVM模型的参数包括权重向量(w)、偏置项(b)以及核函数的参数(如径向基核函数的γ)。
-
决策函数:SVM的决策函数用于预测新数据点的类别,它是基于训练得到的权重向量和偏置项构建的。
1.支持向量:
在支持向量机(Support Vector Machine, SVM)中,支持向量是指那些位于决策边界上或者刚好触碰到决策边界的样本点。这些点对于确定模型的决策边界至关重要,因为SVM模型的决策边界是在这些支持向量的约束下形成的(例如下面这张图上红色的数据点)。
支持向量的特点:
-
位于决策边界上:支持向量是那些位于决策边界上的点,或者对于软间隔SVM,是那些刚好触碰到最大间隔边界的点。
-
影响决策边界:SVM的决策边界完全由支持向量决定。如果从数据集中移除了支持向量,决策边界将会改变。
-
最大间隔原则:SVM试图找到最优的决策边界,使得样本间的间隔(即样本到决策边界的最短距离)最大化。支持向量是这个间隔最大化过程中的关键点。
-
少数关键点:在许多情况下,支持向量只是数据集中的一小部分,但它们对模型的性能至关重要。
-
不同类别:对于分类问题,支持向量可以来自任一类。在二分类问题中,每个类别的支持向量都有助于定义决策边界。
-
计算复杂度:在SVM中,只需要考虑支持向量而不是整个数据集,这可以显著降低计算复杂度,尤其是在处理大规模数据集时。
2.Hinge损失函数:
Hinge损失函数,也称为合页损失,是SVM(支持向量机)中用于分类问题的一种损失函数。它用于衡量分类的正确性,特别是在二元分类中。它的目标是最大化决策边界的间隔,同时最小化分类误差。
Hinge损失函数的定义
对于一个二元分类问题,Hinge损失函数可以定义为:
其中:
- 是真实标签,通常取值为或。
- 是模型预测的分数,即决策函数的输出,。
- 是超平面的法向量。
- 是偏置项。
损失函数的解释
- 当 时,表示样本 被正确分类,并且其与决策边界的距离至少为1,此时Hinge损失为0。
- 当 时,表示样本 被错误分类或位于间隔内,此时Hinge损失为 ,损失的大小表示样本 与决策边界的距离。
SVM中的Hinge损失
在SVM中,目标是最小化所有样本的Hinge损失之和,同时正则化以防止过拟合。因此,SVM的目标函数可以写为:
其中:
- 是样本数量。
- 是正则化参数,控制模型复杂度和对误分类的容忍度。
- 是法向量 (w) 的欧几里得范数的平方。
优化问题
在实际应用中,SVM的训练过程涉及到求解一个凸二次规划问题,以找到最优的 和 。这个过程通常通过拉格朗日乘子法和对偶问题的求解来完成。
总之:Hinge损失函数是SVM中的核心组成部分,它鼓励模型不仅正确分类样本,而且要最大化间隔。这使得SVM成为一种强大的分类器,特别适用于具有清晰边界和高维特征空间的问题。
3.决策函数(线性和非线性):
在支持向量机(SVM)中,决策函数用于确定数据点的分类。对于线性可分和线性不可分的数据集,决策函数的形式有所不同。
线性可分情况下的决策函数:
对于线性可分的数据集,决策函数是线性的,可以表示为:
其中:
- 是超平面的法向量。
- 是特征空间中的点。
- 是偏置项(也称为截距或偏置)。
如果 ,样本 被分类为正类;如果 ,样本 被分类为负类。
线性不可分情况下的决策函数:
当面对线性不可分的数据集时,支持向量机(SVM)采用核技巧来处理这一挑战。核技巧通过将数据映射到更高维度的空间,使得数据在这个新空间中可能实现线性可分。在这种情况下,SVM的决策函数更新为:
其中:
- 是一个映射函数,它将原始的特征向量 映射到更高维的空间。
- 是权重向量,决定了决策边界在高维空间中的方向。
- 是偏置项,决定了决策边界在高维空间中的位置。
由于直接计算 在高维空间中可能非常复杂,SVM利用核函数 来计算映射后的向量之间的点积,而无需显式地知道映射函数 。因此,决策函数可以改写为:
这里:
- 是拉格朗日乘子,它们通过优化过程确定。
- 是第 个训练样本的真实类别标签。
- 是核函数,用于计算映射后的向量 和 之间的点积。
- 是支持向量的数量。
核函数 允许计算映射后的向量和 之间的点积,而无需直接知道映射函数 。
一些常用的核函数包括:
- 线性核:(这实际上退化为线性可分的情况)
- 多项式核:,其中 是多项式的度数。
- 径向基函数(RBF)核,也称为高斯核:,其中 是一个参数。
- Sigmoid核:,其中 和 是参数。
决策函数的输出决定了数据点的分类:
- 如果 ,则数据点被分类为正类。
- 如果 ,则数据点被分类为负类。
核函数的选择和参数设置对于模型的性能至关重要,需要根据具体问题和数据集的特性来决定。通过核技巧,SVM能够有效地处理非线性问题,并找到合适的决策边界。
3.数学过程推理和算法搭建
一.线性SVM:
线性svm中最大的特点就是无需借助应用核技巧就能够找到分类问题的最大超平面
线性可分SVM的数学过程涉及几个关键部分:原始问题、拉格朗日函数、对偶问题和决策函数。下面是对这些部分的数学公式的补充和完整描述:
原始问题(Primal Problem)
线性可分SVM的原始问题是一个二次规划问题,目的是最大化间隔。数学上可以表示为:
约束条件为:
其中:
- 是权重向量。
- 是偏置项。
- 是第 个训练样本的特征向量。
- 是第 个训练样本的标签。
- 是训练样本的总数。
至于这里的主函数为什么是(1/2)*w^2则是支持向量所在函数计算转换后得到的结果,如果想完全搞清楚建议去看数之道的svm数学推导视频。yi(W^t+b)>=1则是该原始问题函数的限制条件,只有当这个条件满足时我们才能将原本复杂的式子转换成(1/2)*W^2这个简单的数学公式。
拉格朗日函数(Lagrangian)
为了解决原始问题中的约束,引入拉格朗日乘数 并构造拉格朗日函数:
其中:
- 是拉格朗日乘数向量。
为什么要引入拉格朗日乘子?
为了将约束条件整合到优化问题中。每个数据点对应一个拉格朗日乘数,它们在优化过程中被用来平衡目标函数和约束条件。
为什么要构建拉格朗日函数?
为了将原始的优化问题转化为拉格朗日对偶问题。总之,拉格朗日乘数和拉格朗日函数在SVM中用于将一个复杂的非凸优化问题转化为一个更易于解决的凸优化问题,从而找到最优的决策边界。(你可以简单地将其理解成优化函数,构造极值点以简便运算)
对偶问题(Dual Problem)
通过对偶变换,原始问题转化为对偶问题,其目标函数为:
约束条件为:
那么问题来了,为什么我们还要对拉格朗日函数进行对偶化处理呢?
主要有几个原因:
- 简化优化问题:原始的SVM优化问题涉及到变量w(超平面的法向量)和偏置项b,它们可能构成一个高维空间。对偶问题则只涉及到拉格朗日乘数α,这通常可以简化优化过程。
- 避免局部最小值:原始问题可能是非凸的,这意味着它可能有多个局部最小值。而对偶问题通常是凸的,这意味着找到的解是全局最优解。
- 数值稳定性:对偶问题在数值计算上通常更稳定。由于对偶问题涉及的是二次规划,而原始问题可能涉及更复杂的优化,对偶问题更容易找到稳定的解。
- 计算效率:在某些情况下,对偶问题的求解可以更高效。特别是当数据集很大时,对偶问题的求解可能更加高效,因为它只依赖于支持向量而不是整个数据集。
- 自然地引入核技巧:对偶形式的SVM自然地允许引入核函数。核函数可以将原始特征空间映射到更高维的特征空间,以便于在高维空间中找到更好的分离超平面。对偶问题的解不直接依赖于w,而是依赖于数据点之间的内积,这可以通过核函数来计算。
- 解的解释性:对偶问题的解(即拉格朗日乘数α)可以直接告诉我们哪些数据点是支持向量,即那些决定了最终决策边界的数据点。这有助于理解模型是如何工作的。
- 正则化参数的直观理解:在对偶问题中,正则化参数C直接控制了优化问题的约束条件,即允许的误差水平。这使得正则化参数的选择更加直观。
- 并行计算:对偶问题的求解过程可以更容易地并行化,因为每个数据点的拉格朗日乘数可以独立地进行优化。
因此,对偶处理在SVM中是一种强大的技术,它不仅简化了优化问题,还提高了计算效率和稳定性,同时使得模型更易于理解和解释。
当然,对偶问题也是有一定条件的,一是要求满足KKT条件,二是要求该问题是一个凸优化问题,凸优化较容易理解,也就是要求我们的函数存在一个全局最小值,方便我们寻找合适的极值点,而KKT条件则是下面该式子:
KKT条件
KKT(Karush-Kuhn-Tucker)条件是一组必要条件,用于确定凸优化问题的局部最优解是否也是全局最优解。在线性SVM中,KKT条件确保了原始问题和对偶问题解的等价性。KKT条件包括:
- 原始问题的约束条件:对所有 成立。
- 对偶问题的约束条件: 且 对所有成立。
- 互补松弛条件: 对所有 成立,意味着 的样本点必须位于间隔边界上(即)。
这些数学公式和条件共同构成了线性可分SVM的理论基础,使得SVM能够有效地解决线性分类问题。
决策函数(Decision Function)
求解出最优的拉格朗日乘子 后,可以计算权重向量 和偏置项:
偏置项 可以通过以下方式计算,通常选择一个支持向量 来计算:
最终的决策函数为:
这个决策函数用于分类新的样本 ,如果,则 被分类为正类;如果 ,则 被分类为负类。
以上就是线性可分SVM的数学描述。对于非线性可分的情况,SVM会引入核技巧来处理数据,但上述公式是线性SVM的核心。
二.非线性SVM:
非线性支持向量机(SVM)通过使用核函数将原始特征空间映射到高维特征空间,使得非线性问题在这个新空间中线性可分。非线性问题其实与线性问题大致相同,核心就是多了一个核技巧来帮助我们处理解决一些更复杂的原始函数,以下是非线性SVM的数学公式,包括原始问题和对偶问题。
原始问题(Primal Problem)
在高维特征空间中,非线性SVM的原始问题可以表示为最大化间隔问题,但与线性SVM不同的是,这里引入了映射函数 :
约束条件为:
核函数(Kernel Function)
核函数 用于计算映射后的向量 和 之间的点积,而无需显式地知道映射函数 。数学上表示为:
常用的核函数包括:
- 线性核:
- 多项式核:
- 径向基函数(RBF)核:
- Sigmoid核:
之所以要用核技巧是因为我们在处理非线性问题时,该维度无法找到一个能够将数据点分类的很好的超平面,所以我们需要将相应数据点利用核函数映射到更高的维度上去来方便我们找到一个合适的超平面,但当我们将样本数据进行升维后求其矩阵乘积时需要涉及到大量运算,速度效率大打折扣(有些时候数据的维度极大),因此边引入了核函数这个数学技巧还可以来帮助我们跳过矩阵乘积这个过程而直接得到其结果,大大减少了计算量和计算时间并甚至将问题的限制扩大到无限维问题,很好地减小了分类受维度限制这个难题。
对偶问题(Dual Problem)
通过拉格朗日乘数法,原始问题可以转化为对偶问题。对偶问题的目标函数和约束条件如下:
约束条件为:
决策函数(Decision Function)
一旦求解出对偶问题,我们可以得到最优的拉格朗日乘子,然后可以计算决策函数:
权重向量 可以表示为:
偏置项 可以通过以下方式计算,通常选择一个支持向量 来计算 :
这就是非线性SVM的数学描述,它通过核技巧有效地处理非线性问题,而无需直接在高维空间中操作。核技巧不仅减少了计算量和时间,还允许SVM处理更高维度甚至无限维的问题,从而为解决复杂的非线性分类问题提供了强大的工具。
4.算法步骤
支持向量机(SVM)算法的步骤可以概括如下:
-
准备数据:对数据进行预处理,包括特征缩放、标准化等,以确保算法的稳定性和效率。
-
选择核函数:确定使用哪种核函数来处理数据。常用的核函数包括线性核、多项式核、径向基函数(RBF)核等。
-
选择正则化参数(C):确定正则化参数C的值,这个参数控制着模型对误分类的惩罚程度。较大的C值意味着模型更关注于正确分类所有数据点,而较小的C值意味着模型更倾向于找到一个间隔更大的超平面。
-
选择误差容忍度(部分方案和模型):在某些实现中,可以设置一个容忍度参数,以允许模型在间隔内容忍一些误分类。
-
构建优化问题:构建一个凸二次规划问题,目标是最大化数据点到决策边界的间隔,同时最小化分类误差。
-
求解优化问题:使用优化算法(如SMO、内点法等)求解上述优化问题。这个过程涉及到寻找支持向量,即那些位于间隔边界上的数据点。
-
确定模型参数:通过优化过程确定权重向量(w)、偏置项(b)以及核函数的参数。
-
构建决策函数:使用得到的模型参数构建决策函数,该函数用于预测新数据点的类别。
-
模型评估:使用交叉验证或保留的测试集来评估模型的性能,常用的评估指标包括准确率、召回率、F1分数等。
-
模型调优:根据模型评估的结果,可能需要返回到前面的步骤调整参数,如核函数、正则化参数等,以优化模型性能。
-
模型部署:将训练好的模型部署到实际应用中,对新的数据进行分类预测。
SVM算法的关键在于找到最优的超平面,这个超平面不仅能够正确分类训练数据,而且具有最大的间隔,从而提高模型的泛化能力。通过核技巧,SVM能够处理非线性可分的数据,使其在许多实际问题中表现出色。
以上部分的算法基础是为了大家先对SVM有个整体知识和结构的了解,那么接下来我们就将进行逐步剖析和尽量完整的代码复现。
5.线性SVM代码复现
一,线性可分SVM的详细代码复现(实例演示,看不懂没关系,可以跳过):
import numpy as np
class LinearSVM:
def __init__(self, C=1.0, learning_rate=0.0001, n_iters=1000):
self.C = C
self.learning_rate = learning_rate
self.n_iters = n_iters
self.w = None
self.b = None
def fit(self, X, y):
n_samples, n_features = X.shape
y_ = np.where(y <= 0, -1, 1)
self.w = np.zeros(n_features)
self.b = 0
for _ in range(self.n_iters):
for idx, x_i in enumerate(X):
condition = y_ * (np.dot(x_i, self.w) - self.b) >= 1
if condition:
self.w -= self.learning_rate * (2 * self.C * y_ * condition - 1) * x_i
self.b -= self.learning_rate * (2 * self.C * y_ * condition - 1)
else:
self.w -= self.learning_rate * (2 * self.C * y_ - 1) * x_i
self.b -= self.learning_rate * (2 * self.C * y_ - 1)
def predict(self, X):
linear_output = np.dot(X, self.w) - self.b
return np.sign(linear_output)
# 示例数据
X = np.array([[1, 2], [2, 3], [3, 3], [6, 2], [7, 3], [8, 2]])
y = np.array([-1, -1, -1, 1, 1, 1])
# 创建并训练模型
svm = LinearSVM(C=0.1, learning_rate=0.01, n_iters=1000)
svm.fit(X, y)
# 预测
predictions = svm.predict(X)
print("Predictions:", predictions)
以上代码是一个svm算法的基础模型结构,但在现实学习和企业商用的场景中,我们通常通过直接应用外部的库来实现svm算法,因此接下来的svm算法部分我会直接引用sklearn这里面的SVM算法库来实现。
二.经典线性可分SVM算法复现过程
代码(引自网络,鸢尾花线性可分问题):
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
# 加载鸢尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建支持向量机分类器
svm = SVC(kernel='linear', C=1.0, random_state=42)
# 训练模型
svm.fit(X_train, y_train)
# 预测测试集
y_pred = svm.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print('Accuracy:', accuracy)
代码讲解:
这段代码使用Python的sklearn库来训练和评估一个支持向量机(SVM)模型:
-
from sklearn import datasets这行代码导入了sklearn库中的datasets模块,该模块包含用于加载各种标准数据集的工具。 -
from sklearn.model_selection import train_test_split导入train_test_split函数,该函数用于将数据集分割为训练集和测试集。 -
from sklearn.svm import SVC导入SVC类,这是sklearn库中实现支持向量机分类器的类。 -
from sklearn.metrics import accuracy_score导入accuracy_score函数,用于计算分类模型的准确率。 -
iris = datasets.load_iris()使用load_iris函数加载鸢尾花数据集,该数据集包含150个样本,每个样本有4个特征,以及3个类别。 -
X = iris.data将数据集中的特征数据赋值给变量X。 -
y = iris.target将数据集中的目标变量(类别标签)赋值给变量y。 -
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)使用train_test_split函数将数据集划分为训练集和测试集。test_size=0.2表示测试集占总数据集的20%,random_state=42确保每次划分的结果相同。 -
svm = SVC(kernel='linear', C=1.0, random_state=42)创建一个SVC实例,即SVM分类器。kernel='linear'指定使用线性核函数,C=1.0设置正则化参数,random_state=42用于确保结果的可重复性。 -
svm.fit(X_train, y_train)使用训练集数据调用fit方法训练SVM模型。 -
y_pred = svm.predict(X_test)使用训练好的SVM模型对测试集进行预测,并将预测结果存储在变量y_pred中。 -
accuracy = accuracy_score(y_test, y_pred)使用accuracy_score函数计算模型在测试集上的准确率。 -
print('Accuracy:', accuracy)打印出模型的准确率。
这段代码展示了如何使用sklearn库来加载数据集、划分数据集、创建SVM模型、训练模型、进行预测以及评估模型性能的完整流程。
线性可分SVM过程详解:
线性支持向量机(SVM)是用于线性可分问题的一种监督学习算法。在这个问题中,数据点可以被一个超平面完全分开。SVM的目标是找到一个超平面,使得样本的间隔最大化,从而实现良好的泛化能力。
对于线性可分问题,SVM的优化问题可以表示为以下形式:
其中:
- 是超平面的法向量(权重向量)。
- 是超平面的偏置项。
- 是松弛变量,用于处理那些不能完美分类的点。
- 是正则化参数,控制着对误分类的惩罚强度。
- 是训练样本的总数。
约束条件确保了分类的正确性和间隔的最大化:
并且松弛变量 必须非负:
≥0,
这里的 是每个训练样本的标签, 是对应的特征向量。如果 大于或等于 1,那么样本 被正确分类并且位于间隔边界内或者间隔的正确一侧。如果它小于 1 但大于 ,样本被错误分类,但错误分类的惩罚由松弛变量 控制。
SVM 的目标是最小化一个包含权重向量 的范数(通常是 范数,即)的正则项和对误分类的惩罚项。权重向量的 范数有助于控制模型的复杂度,从而减少过拟合的风险。而 参数的调整则允许在偏差和方差之间进行权衡,即在模型的拟合程度和复杂度之间找到平衡。
在实际应用中,通过求解上述优化问题,我们可以得到最优的权重向量 和偏置项,它们定义了最优的超平面。只有那些满足的样本(即支持向量)决定了超平面的位置,这也是支持向量机得名的原因。
6.非线性SVM代码复现
我们将继续使用sklearn库中的SVC类来实现。在这个例子中,我们将使用径向基函数(RBF)核,这是一种常用的非线性核函数。
代码复现:
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
# 加载鸢尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 将标签转换为二进制形式,因为RBF核通常用于二分类问题
y = y.astype(str)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建支持向量机分类器,使用RBF核
svm = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)
# 训练模型
svm.fit(X_train, y_train)
# 预测测试集
y_pred = svm.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print('Accuracy:', accuracy)
代码详解:
这段代码使用Python的sklearn库来训练和评估一个基于径向基函数(RBF)核的支持向量机(SVM)模型的示例:
-
from sklearn import datasets导入sklearn库中的datasets模块,该模块包含用于加载各种标准数据集的工具。 -
from sklearn.model_selection import train_test_split导入train_test_split函数,该函数用于将数据集分割为训练集和测试集。 -
from sklearn.svm import SVC导入SVC类,这是sklearn库中实现支持向量机分类器的类。 -
from sklearn.metrics import accuracy_score导入accuracy_score函数,用于计算分类模型的准确率。 -
iris = datasets.load_iris()使用load_iris函数加载鸢尾花数据集,该数据集包含150个样本,每个样本有4个特征,以及3个类别。 -
X = iris.data将数据集中的特征数据赋值给变量X。 -
y = iris.target将数据集中的目标变量(类别标签)赋值给变量y。 -
y = y.astype(str)将目标变量y的数据类型转换为字符串,这一步实际上是不必要的,因为RBF核可以用于多分类问题。在多分类问题中,SVC会自动处理。 -
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)使用train_test_split函数将数据集划分为训练集和测试集。test_size=0.2表示测试集占总数据集的20%,random_state=42确保每次划分的结果相同。 -
svm = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)创建一个SVC实例,即SVM分类器。kernel='rbf'指定使用径向基函数核,C=1.0设置正则化参数,gamma='scale'自动设置gamma参数,random_state=42用于确保结果的可重复性。 -
svm.fit(X_train, y_train)使用训练集数据调用fit方法训练SVM模型。 -
y_pred = svm.predict(X_test)使用训练好的SVM模型对测试集进行预测,并将预测结果存储在变量y_pred中。 -
accuracy = accuracy_score(y_test, y_pred)使用accuracy_score函数计算模型在测试集上的准确率。 -
print('Accuracy:', accuracy)打印出模型的准确率。
请注意,鸢尾花数据集是一个多分类问题,SVM可以处理多分类问题而不需要将标签转换为字符串。此外,SVC类在处理多分类问题时会使用一对多(OvR)策略。
代码总结:
其实我们在利用sklearn库引入SVM算法的核心就是这三步:
svc1 = sklearn.svm.LinearSVC(C=1, loss='hinge', max_iter=20000)
svc1.fit(data[['X1', 'X2']], data['y'])
svc1.score(data[['X1', 'X2']], data['y'])
这段代码是使用Python的sklearn库中的支持向量机(SVM)算法来训练一个分类模型:
svc1 = sklearn.svm.LinearSVC(C=1, loss='hinge', max_iter=20000)
非线性:svm = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)
这行代码初始化了一个名为svc1的LinearSVC模型实例。LinearSVC是线性支持向量分类器,它使用线性核函数来处理数据。参数解释如下:
-
C=1:正则化参数。在SVM中,C参数控制模型对误分类的惩罚程度。较大的C值会导致模型对误分类的惩罚增加,从而使得决策边界更加复杂,以减少训练误差。较小的C值则相反,会使得模型更加平滑,减少对单个数据点的敏感度。(在SVM中,正则化参数C控制着模型在训练过程中对于误分类样本的惩罚程度。具体来说,C越大,模型对于误分类样本的惩罚就越严格,这会导致模型更加倾向于选择较小的权重向量,从而得到更为严格的分类边界。相反,C小,模型对于误分类样本的惩罚就越宽松,这会导致模型更加倾向于选择较大的权重量,从而得到更为宽松的分类边界。
在实际应用中,C的取值需要进行调优。如果C取值过小,可能会导致模型欠拟合,无法很好地拟合训练数据;如果C取值过,可能会导致模型过拟合,无法很好地泛化到新的数据。因此,需要通过交叉验证等方法来确定合适的C值,以在保证模型性能的同时避免过拟合和欠拟合的问题。在这里,C被设置1,这个值在许多情况下可以作为一个合理的默认值。)
-
loss='hinge':损失函数类型。'hinge'损失函数是SVM中常用的损失函数,它用于最大化分类间隔。 -
max_iter=20000:最大迭代次数。这是训练过程中算法尝试找到最优解的最大迭代次数。增加这个值可以提高找到全局最优解的可能性,但也会增加计算时间。
-
svc1.fit(data[['X1', 'X2']], data['y'])这行代码用于训练
svc1模型。fit方法接受两个参数:特征数据和标签数据。data[['X1', 'X2']]:特征数据,这里假设data是一个DataFrame,其中包含两列特征X1和X2。data['y']:标签数据,这是模型需要预测的目标变量。
fit方法会使用提供的特征和标签数据来训练模型,找到最佳的决策边界。 -
svc1.score(data[['X1', 'X2']], data['y'])这行代码计算模型在训练数据上的性能。
score方法返回模型的准确率,即模型正确预测的样本数占总样本数的比例。data[['X1', 'X2']]:与fit方法中相同,提供特征数据。data['y']:提供标签数据。
这个分数可以用于评估模型在训练集上的表现,但请注意,为了得到模型的泛化能力,通常还需要在独立的测试集上进行评估。
总结来说,这段代码创建了一个线性SVM分类器,使用特定的参数配置,然后使用提供的数据进行训练,并计算模型在训练数据上的准确率。
7.通俗实例加深理解SVM
让我们通过一个通俗的例子来理解SVM中的对偶问题。
想象一下,你是一个农场主,你的农场里有两种作物,A和B。你想要在农场中划分一块区域,使得A作物和B作物被这条分界线尽可能清晰地分开。但是,A和B作物并不是完全按照直线分布的,它们的形状是不规则的,也就是说,它们是非线性分布的。
在这种情况下,你不能简单地画一条直线来分隔它们。你需要一种方法来找到一种曲线,这条曲线能够最好地分隔这两种作物,同时保持分界线两边的作物尽可能地远离这条线,以便于未来的扩展和管理。
原始问题:
- 你首先尝试直接解决这个问题,即找到一条曲线(在数学上,这对应于在高维空间中找到一个超平面),这条曲线能够将两种作物分开,并且最大化作物到这条线的距离(间隔最大化)。
对偶问题:
- 然而,直接解决这个问题可能会非常复杂,特别是当作物的分布非常不规则时。因此,你决定采取一种间接的方法。
- 你开始考虑作物之间的“冲突”。每次作物A和作物B靠得太近,你就会记录下来,并且尝试找到一种方法来最小化这些“冲突”的总和。这里的“冲突”可以想象成是原始问题中的误差项。
- 同时,你也不想让这条分界线过于复杂,因为这可能会使得未来的管理变得困难。所以,你还需要控制这条线的“复杂度”,在SVM中,这对应于正则化参数
C。
通过这种方法,你实际上是在解决一个更简单的问题(对偶问题),它只关心作物之间的“冲突”和分界线的“复杂度”,而不是直接去寻找那条分界线。这种方法的好处是,它可以更容易地找到解决方案,并且解决方案通常更加稳定和可靠。
拉格朗日乘子:
- 在这个过程中,你引入了一种叫做“拉格朗日乘子”的东西来帮助你平衡“冲突”和“复杂度”。这些乘子就像是你的助手,它们帮助你在增加分界线复杂度和减少冲突之间做出权衡。
求解对偶问题:
- 通过对这些“冲突”和“复杂度”进行优化,你最终找到了一种方法来描述这条分界线,而不需要直接去画它。这就是对偶问题的解。
回到原始问题:
- 最后,一旦你通过解决对偶问题找到了这些拉格朗日乘子,你就可以用它们来构造那条实际的分界线。这条线就是你的SVM模型,它可以准确地分隔两种作物。
通过这个例子,我们可以看到,对偶问题是一种间接解决问题的方法,它通过优化一个更简单的问题(在本例中是最小化“冲突”和控制“复杂度”)来帮助我们找到原始问题的解(分隔两种作物的曲线)。在SVM中,这种方法不仅简化了问题的求解过程,还提高了解的稳定性和泛化能力。
以上呢大概就是笔者对于SVM算法整理总结的全部内容,笔者承认,其中可能存在一些不准确的地方和瑕疵之处,欢迎大家指正,笔者参考了好几篇文章文献,想着省略大量数学推导过程而直接给出数学公式的作用和条件,奈何可能功力不深,仍存在囫囵吞枣处,笔者强力推荐数之道的svm数学推导视频,因为笔者可能在过程中理解但是无法很好地表达出来,还请各位海涵。抱拳了。
本篇文章部分引用吸收了下面几篇文章,感谢其原作者: