[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

这篇具有很好参考价值的文章主要介绍了[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  1. 视频链接
  2. 数据集下载地址:无需下载

学习目标:

  • 了解什么是 SVM 算法
  • 掌握 SVM 算法的原理
  • 知道 SVM 算法的损失函数
  • 知道 SVM 算法的核函数
  • 了解 SVM 算法在回归问题中的使用
  • 应用 SVM 算法实现手写数字识别器

1. SVM 算法简介

学习目标:

  • 了解 SVM 算法的定义
  • 知道软间隔和硬间隔

1.1 SVM 算法导入

在很久以前的情人节,英雄要去救他的爱人,但魔鬼和他玩了一个游戏。魔鬼在桌子上似乎有规律放了两种颜色的球,说:“你用一根棍分开它们。要求:尽量在放更多球之后,仍然适用。”。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

于是英雄这样放。似乎干的不错?

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

然后魔鬼又在桌上放了更多的球,但似乎有一个球站错了阵营。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

那怎么办?

英雄试图通过在棍子的两侧留出尽可能大的间隙来将棍子放在最佳位置。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

SVM 就是试图把棍放在最佳位置,好让在棍的两边有尽可能大的间隙

现在即使魔鬼放了更多的球,棍仍然是一个好的分界线。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

然后,在 SVM 工具箱中有另一个更加重要的技巧(trick)。魔鬼看到英雄已经学会了一个trick,于是魔鬼给了英雄一个新的挑战。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

现在,英雄没有棍可以很好帮他分开两种球了,现在怎么办呢?

当然像电影中一样,英雄桌子一拍,球飞到空中。然后,凭借英雄的轻功抓起一张,插到了两种球的中间。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

现在,从魔鬼的角度看这些球,这些球看起来像是被一条曲线分开了。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

再之后,无聊的大人们,把上面的物体起了别名:

  • 球 —— 「data」数据
  • 棍子 ―― 「classifier」分类器
  • 最大间隙 ―― 「optimization」最优化方法
  • 拍桌子 ―― 「kernelling」核方法
  • 纸 ―― 「hyperplane」超平面

案例来源: Support Vector Machines explained well

支持向量机直观感受:SVM with polynomial kernel visualization

1.2 SVM 定义

SVM 全称是 Supported Vector Machine(支持向量机),即寻找到一个超平面使样本分成两类,并且间隔最大

SVM 能够执行①线性或非线性分类②回归,甚至是③异常值检测任务。它是机器学习领域最受欢迎的模型之一。

SVM 特别适用于中小型复杂数据集的分类。

Q:SVM 只能做二分类吗?
A:SVM 最初是为二分类问题设计的,但它也可以用于多分类问题。目前,构造 SVM 多类分类器的方法主要有两类:一类是直接法,直接在目标函数上进行修改,将多个分类面的参数求解合并到一个最优化问题中,通过求解该最优化问题“一次性”实现多类分类。另一类是间接法,主要是通过组合多个二分类器来实现多分类器的构造,常见的方法有 one-against-one(一对一)和 one-against-all(一对多)两种。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

1.3 超平面最大间隔介绍

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

上左图显示了三种可能的线性分类器的决策边界:

  • 虚线(模型)的表现非常糟糕,甚至都无法正确实现分类。
  • 其余两个实线(模型)在这个训练集上表现堪称完美。但它们的决策边界与实例过于接近,导致在面对新实例时,表现可能不会太好

对于左图的两个实现模型而言,如果数据集稍微有一点小变动,那么就分错了,所以泛化性能可能有些不理想

右图中的实线代表 SVM 分类器的决策边界(具体是怎么分开的),两条虚线之间的距离表示最大间隔。实现模型不仅分离了两个类别,且尽可能远离最近的训练实例。

SVM 不仅仅要找到划分的线,而且要求线离两个实例的举例越大越好,这样就有足够的距离,从而提升对新数据集的包容

1.4 硬间隔和软间隔

1.4.1 硬间隔分类

在上面我们使用超平面进行分割数据的过程中,如果我们严格地让所有实例都不在最大间隔之间,并且位于正确的一边,这就是硬间隔分类。

简单来说,硬间隔就是要求百分百分对

硬间隔分类有两个问题:

  1. 它只在数据是线性可分离的时候才有效
  2. 它对异常值非常敏感

举例:当鸢尾花数据存在一个额外异常值时,

  • 左图的数据根本找不出硬间隔(没有办法保证百分百分对)
  • 右图最终显示的决策边界与我们之前所看到的无异常值时的决策边界也大不相同,可能无法很好地泛化

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

1.4.2 软间隔分类

要避免硬间隔因异常值出现的不可分的问题,最好使用更灵活的模型。目标是:尽可能在保持最大间隔宽阔和限制间隔违例(即位于最大间隔之上,甚至在错误的一边的实例)之间找到良好的平衡(tradeoff),这就是软间隔分类。

间隔违例:指位于最大间隔之上,甚至在错误的一边的实例。

简单来说,硬间隔(hard margin)是指在 SVM 中,我们假设数据是线性可分的,也就是说,我们可以找到一个超平面将不同类别的数据完全分开。但是,在现实世界中,数据往往不是线性可分的。为了解决这个问题,我们引入了软间隔(soft margin)的概念。软间隔允许一些数据点被错误分类,以便更好地拟合数据。这样,我们就可以在最大化间隔的同时,尽量减少不满足约束的样本数量。


在 Scikit-Learn 的 SVM 类中,可以通过超参数 C 来控制这个平衡:

  • C 值越小,则间隔越宽,但是间隔违例也会越多

超参数 C 我们可以理解为是一个惩罚项。C 越大,惩罚越重,间隔违例就越少,说明间隔宽度越小;C 越小,惩罚越轻,间隔违例就越多,说明间隔宽度就越大。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

上图显示了在一个非线性可分离数据集上,两个软间隔 SVM 分类器各自的决策边界和间隔。

  • 左边使用了高 C 值,分类器的错误样本(间隔违例)较少,但是间隔也较小。
  • 右边使用了低 C 值,间隔大了很多,但是位于间隔上的实例也更多。

看起来第二个分类器的泛化效果更好,因为大多数间隔违例实际上都位于决策边界正确的一边,所以即便是在该训练集上,它做出的错误预测也会更少。


小结

  • SVM 算法定义【了解】:寻找到一个超平面使样本分成两类,并且间隔最大。
  • 硬间隔和软间隔【知道】
    • 硬间隔:要求百分百分对
      • 只有在数据是线性可分离的时候才有效
      • 对异常值非常敏感
    • 软间隔:尽可能在保持最大间隔宽阔和限制间隔违例之间找到良好的平衡,允许有分错的样本

2. SVM 算法 API 初步使用

学习目标

  • 知道 SVM 算法 API 的用法

from sklearn import svm
  • 作用from sklearn import svm 这行代码是从 sklearn 库中导入 svm 模块。svm 模块中主要有 LinearSVCNuSVCSVC 三种方法,用于支持向量机分类(这三种方法都是基于支持向量机思想的分类器,但它们在模型的选择和参数调整方面有所不同。选择哪种方法主要取决于数据的特点和问题的需求)。

    1. LinearSVC:LinearSVC 是一种线性支持向量机分类器(Linear Support Vector Classifier)。它使用线性核函数,适用于解决线性可分的问题。它的目标是找到一个超平面,将不同类别的样本分隔开。LinearSVC在训练过程中使用了一系列的优化算法,以最小化分类错误率。
    2. NuSVC:NuSVC 是一种非线性支持向量机分类器(Nu-Support Vector Classifier),它使用了非线性核函数,适用于解决非线性可分的问题NuSVC 通过使用核函数将数据映射到高维空间,使得在高维空间中可以找到一个线性超平面来分隔不同的类别。NuSVC 在训练过程中通过调整参数 nu 来平衡支持和错分样本的数量。
    3. SVC:SVC 是一种支持向量机分类器(Support Vector Classifier),它提供了更灵活的核函数选择和参数调整。SVC 可以根据不同的问题选择适合的核函数,例如线性核函数、多项式核函数、高斯核函数等。此外,SVC 还提供了参数调整的灵活性,例如正则化参数、错误容忍度等。通过调整这些参数,可以更好地适应不同类型的数据和问题。
  • 方法一LinearSVC 方法(Linear Support Vector Classification,意为线性支持向量分类)

    • 作用:线性支持向量分类器,用于处理线性可分的数据集。它使用线性核函数,可以处理大规模的数据集。
    • 参数
      • penalty: 正则化参数,可选值为 ‘l1’ 和 ‘l2’,仅适用于 LinearSVC。
      • loss: 损失函数,可选值为 ‘hinge’ 和 ‘squared_hinge’。其中
        • ‘hinge’ 是 SVM 的标准损失
        • ‘squared_hinge’ 是 ‘hinge’ 的平方
      • dual: 是否转化为对偶问题求解,默认为 True。
      • tol: 残差收敛条件,默认为 0.0001。
      • C: 惩罚系数,用来控制损失函数的惩罚系数。
      • multi_class: 负责多分类问题中分类策略制定,可选值为 ‘ovr’ 和 ‘crammer_singer’。
      • fit_intercept: 是否计算截距。
      • class_weight: 用来处理不平衡样本数据的,可以直接以字典的形式指定不同类别的权重,也可以使用 ‘balanced’ 参数值。
      • verbose: 是否冗余,默认为 False。
      • random_state: 随机种子的大小。
      • max_iter: 最大迭代次数,默认为 1000。
    • 返回值
      • coef_: 各特征的系数(重要性)。
      • intercept_: 截距的大小(常数值)。
    • 方法
      • decision_function(X): 获取数据集 X 到分离超平面的距离。
      • fit(X, y): 在数据集 (X,y) 上使用 SVM 模型。
      • get_params([deep]): 获取模型的参数。
      • predict(X): 预测数据值 X 的标签。
      • score(X,y): 返回给定测试集和对应标签的平均准确率。
  • 方法二NuSVC 方法( Nu-Support Vector Classification,意为 Nu-支持向量分类)

    • 作用:是一种支持向量分类器,它允许用户控制支持向量的数量。它可以处理非线性可分的数据集,但对于大规模的数据集,拟合时间可能会很长。

    • 参数

      • nu: 训练误差部分的上限和支持向量部分的下限,取值在(0,1)之间,默认为 0.5。
      • kernel: 核函数,可选值为 ‘linear’、‘poly’、‘rbf’、‘sigmoid’ 和 ‘precomputed’。
      • degree: 当核函数为多项式核函数时,用来控制函数的最高次数。
      • gamma: 核函数系数,默认为 ‘auto’。
      • coef0: 核函数常数值,只有 ‘poly’ 和 ‘sigmoid’ 核函数有,默认值为 0。
      • shrinking: 是否采用启发式收缩,默认为 True。
      • probability: 是否使用概率估计,默认为 False。
      • tol: 停止拟合容忍度,默认为 0.001。
      • cache_size: 缓冲大小,默认为 200MB。
      • class_weight: 各类权重,与其他模型中参数含义类似,也是用来处理不平衡样本数据的,可以直接以字典的形式指定不同类别的权重,也可以使用 ‘balanced’ 参数值。
      • verbose: 是否冗余,默认为 False。
      • max_iter: 最大迭代次数,默认为 -1。
      • decision_function_shape: 与 ‘multi_class’ 参数含义类似。
      • random_state: 随机种子的大小 。
    • 返回值

      • support_: 以数组的形式返回支持向量的索引。
      • support_vectors_: 返回支持向量。
      • n_support_: 每个类别支持向量的个数。
      • dual_coef_: 支持向量系数。
      • coef_: 每个特征系数(重要性),只有核函数是 LinearSVC 的时候可用。
      • intercept_: 截距值(常数值)。
  • 方法三SVC 方法(C-Support Vector Classification,意为 C-支持向量分类)

    • 作用:是一种支持向量分类器,它可以处理非线性可分的数据集。与 NuSVC 类似,它也可以使用不同的核函数来处理非线性问题,但对于大规模的数据集,拟合时间可能会很长
    • 参数
      • C: 惩罚系数。与 NuSVC 方法基本一致,唯一区别就是损失函数的度量方式不同(NuSVC 中的 nu 参数和 SVC 中的 C 参数)。
    • 方法
      • 与上述相同。

举例:

from sklearn import svm


# 1. 准备数据
X = [[0, 0], [1, 1]]
y = [0, 1]

# 2. 定义模型
clf = svm.SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, 
              decision_function_shape="ovr", degree=3, gamma="scale", kernel="rbf", 
              max_iter=-1, probability=False, random_state=None, shrinking=True, 
              tol=0.001, verbose=False)

# 3. 模型训练
clf.fit(X, y)

# 4. 预测
clf.predict([[2, 2]])
array([1])

3. SVM 算法原理

学习目标

  • 知道 SVM 中线性可分支持向量机
  • 知道 SVM 中目标函数的推导过程
  • 了解朗格朗日乘子法、对偶问题
  • 知道 SVM 中目标函数的求解过程

3.1 定义输入数据

假设给定一个特征空间上的训练集为:

T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x N , y N ) } T = \{ (x_1, y_1), (x_2, y_2), ..., (x_N, y_N) \} T={(x1,y1),(x2,y2),...,(xN,yN)}

x i ∈ R n ( 实数 ) y i ∈ { + 1 , − 1 } i = 1 , 2 , . . . , N \begin{aligned} & x_i \in R^n(实数)\\ & y_i \in \{ +1, -1 \}\\ & i = 1, 2, ..., N \end{aligned} xiRn(实数)yi{+1,1}i=1,2,...,N

其中, ( x i , y i ) (x_i, y_i) (xi,yi) 称为样本点。

  • x i x_i xi 为第 i i i 个实例(样本)
  • y i y_i yi x i x_i xi 的标记:
    • y i = + 1 y_i=+1 yi=+1 时, x i x_i xi 为正例
    • y i = − 1 y_i = -1 yi=1 时, x i x_i xi 为负例

Q:为什么正负用 ( − 1 , 1 ) (-1, 1) (1,1) 表示呢?
A:其实这里没有太多原理,就是一个标记,你也可以用 ( 2 , − 3 ) (2,-3) (2,3) 来标记,只是为了方便。
使用 ( − 1 , 1 ) (-1, 1) (1,1) 则在 y i y j = y i ∗ y j \frac{y_i}{y_j} = y_i * y_j yjyi=yiyj 的过程中刚好可以相等,便于之后的计算。

3.2 线性可分支持向量机

给定了上面提出的线性可分训练数据集,通过间隔最大化得到分离超平面,为:

y ( x ) = w T Φ ( x ) + b y(x) = w^T\Phi(x) + b y(x)=wTΦ(x)+b

其中:

  • y ( x ) y(x) y(x) 表示样本 x x x 到分离超平面的距离。

相应的分类决策函数为:

f ( x ) = s i g n ( w T Φ ( x ) + b ) f(x) = \mathrm{sign}(w^T\Phi(x) + b) f(x)=sign(wTΦ(x)+b)

  • 其中 s i g n \mathrm{sign} sign 函数表示符号函数。

以上的决策函数就称为线性可分支持向量机。


这里解释一下 Φ \Phi Φ

这是某个确定的特征空间转换函数,它的作用是将 x x x 映射到更高的维度,它有一个以后我们经常会见到的专有称号“核函数(Kernel Function)”。

比如我们看到的特征有 2 个,即 x 1 , x 2 x_1, x_2 x1,x2 组成最先见到的线性函数 w 1 x 1 + w 2 x 2 w_1x_1 + w_2 x_2 w1x1+w2x2

但也许这两个特征并不能很好地描述数据,于是我们进行维度的转化,转化到五维特征空间,变成:

w 1 x 1 + w 2 x 2 + w 3 x 1 x 2 + w 4 x 1 2 + w 5 x 2 2 w_1x_1 + w_2x_2 + w_3x_1x_2 + w_4x_1^2 + w_5x_2^2 w1x1+w2x2+w3x1x2+w4x12+w5x22

于是我们多了三个特征。

以上就是笼统地描述 Φ \Phi Φ 是如何对 x x x 映射的。

Φ \Phi Φ 最简单的映射就是:

Φ ( x ) = x \Phi(x) = x Φ(x)=x

即不进行任何映射。


以上就是线性可分支持向量机的模型表达式。我们要去求出这样一个模型,或者说这样一个超平面 y ( x ) y(x) y(x),它能够最优地分离两个集合。

其实也就是我们要去求一组参数 ( w , b ) (w,b) (w,b) 使其构建的超平面函数能够最优地分离两个集合。

核函数 Φ \Phi Φ 是已知的,不需要我们求。


如下就是一个最优超平面:

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

硬间隔分类

又比如说这样:

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

阴影部分是一个“过渡带”,“过渡带”的边界是集合中离超平面最近的样本点落在的地方。

软间隔分类

3.3 SVM 的计算过程与算法步骤

3.3.1 推导目标函数

我们知道了支持向量机是个什么东西了。现在我们要去寻找这个支持向量机,也就是寻找一个最优的超平面。于是我们要建立一个目标函数。那么如何建立呢?

再来看一下我们的超平面表达式:

y ( x ) = w T Φ ( x ) + b y(x) = w^T\Phi(x) + b y(x)=wTΦ(x)+b

其中 y ( x ) y(x) y(x) 表示样本 x x x 到分离超平面的距离。

为了方便,我们让核函数不进行映射,即 Φ ( x ) = x \Phi(x) = x Φ(x)=x。那么在样本空间中,划分超平面可通过如下线性方程来描述:

w T x + b = 0 w^Tx+b = 0 wTx+b=0

我们知道:

  • w = ( w 1 , w 2 , . . . , w d ) w=(w_1, w_2,..., w_d) w=(w1,w2,...,wd) 为法向量,决定了超平面的方向
  • b b b 为位移项,决定了超平面和原点之间的距离

要让点到线的距离最近,要垂直,所以称为法向量。

显然,划分超平面可被法向量 w w w 和位移 b b b 确定,我们把其记为 ( w , b ) (w,b) (w,b)

于是,样本空间中任意点 x x x 到超平面 ( w , b ) (w,b) (w,b) 的距离可写成:

r = ∣ w T x + b ∣ ∣ ∣ w ∣ ∣ r = \frac{|w^Tx + b|}{||w||} r=∣∣w∣∣wTx+b

∣ ∣ w ∣ ∣ ||w|| ∣∣w∣∣ 就是求向量 w w w 的 2-范数。

范数的说明:【文间跳转】范数说明

假设超平面 ( w , b ) (w, b) (w,b) 能将训练样本正确分类,即对于 ( x i , y i ) ∈ D (x_i, y_i) \in D (xi,yi)D

  • y i = + 1 y_i = +1 yi=+1,则有 w T x i + b > 0 w^T x_i + b > 0 wTxi+b>0
  • y i = − 1 y_i = -1 yi=1,则有 w T x i + b < 0 w^T x_i + b < 0 wTxi+b<0

{ w T x i + b ≥ + 1 , y i = + 1 ; w T x i + b ≤ − 1 , y i = − 1 ; \begin{cases} w^Tx_i + b \ge +1, & y_i = +1; \\ w^Tx_i + b \le -1, & y_i = -1; \\ \end{cases} {wTxi+b+1,wTxi+b1,yi=+1;yi=1;

如图所示,距离超平面最近的几个训练样本点使上式等号成立,他们被称为“支持向量”,则两个异类支持向量到超平面的距离之和为: y = 2 ∣ ∣ w ∣ ∣ y = \frac{2}{||w||} y=∣∣w∣∣2,它被称为“间隔”。

支持向量才是真正决定间隔的数据。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

想要找到具有最大间隔的划分超平面,也就是要找到能满足下式中约束的参数 w w w b b b,使得 r r r 最大。

{ w T x i + b ≥ + 1 , y i = + 1 w T x i + b ≤ − 1 , y i = − 1 \begin{cases} w^Tx_i + b \ge +1, & y_i = +1\\ w^Tx_i + b \le -1, & y_i = -1 \end{cases} {wTxi+b+1,wTxi+b1,yi=+1yi=1

即:

max ⁡ w , b = 2 ∣ ∣ w ∣ ∣ s.t. y i ( w T x i + b ) ≥ + 1 , i = 1 , 2 , . . . , m \underset{w, b}{\max} = \frac{2}{||w||} \quad \text{s.t.} \quad y_i(w^Tx_i + b) \ge +1, \quad i=1, 2, ..., m w,bmax=∣∣w∣∣2s.t.yi(wTxi+b)+1,i=1,2,...,m

在数学公式中,“s.t.” 是 “such that” 的缩写,意为“使得”或“满足条件”。它用来引入一些限制条件或约束条件。
例如,在优化问题中,我们通常会看到这样的形式: min ⁡ x f ( x ) s.t. g ( x ) ≤ 0 \min_x f(x) \quad \text{s.t.} \quad g(x) \leq 0 xminf(x)s.t.g(x)0
这表示我们要最小化目标函数 f ( x ) f(x) f(x),使得 g ( x ) ≤ 0 g(x) \leq 0 g(x)0 这个约束条件得到满足。

所以上式的意思就是:求得 2 ∣ ∣ w ∣ ∣ \frac{2}{||w||} ∣∣w∣∣2 的最大值,使得 y i ( w T x i + b ) ≥ 1 y_i(w^Tx_i + b) \ge 1 yi(wTxi+b)1 满足。

显然,为了最大化间隔,仅需要最大化 ∣ ∣ w ∣ ∣ − 1 ||w||^{-1} ∣∣w1,这等价于最小化 ∣ ∣ w ∣ ∣ 2 ||w||^2 ∣∣w2。于是上式可以重写为:

max ⁡ w , b = 1 2 ∣ ∣ w ∣ ∣ 2 s.t. y i ( w T x i + b ) ≥ + 1 , i = 1 , 2 , . . . , m \underset{w, b}{\max} = \frac{1}{2}||w||^2 \quad \text{s.t.} \quad y_i(w^Tx_i + b) \ge +1, \quad i=1, 2, ..., m w,bmax=21∣∣w2s.t.yi(wTxi+b)+1,i=1,2,...,m

这就是支持向量机的基本型。

3.3.2 目标函数的求解

到这一步,终于把目标函数给建立起来了。那么下一步自然是去求目标函数的最优值。因为目标函数带有一个约束条件,所以我们可以用拉格朗日乘子法求解。

3.3.2.1 朗格朗日乘子法

拉格朗日乘子法(Lagrange multipliers)是一种寻找多元函数在一组约束下的极值的方法。通过引入拉格朗日乘子,可将有 d d d 个变量与 k k k 个约束条件的最优化问题转化为具有 d + k d + k d+k 个变量的无约束优化问题求解。

【文间跳转】拉格朗日乘子法举例复习


经过朗格朗日乘子法,我们可以把目标函数转换为:

L ( w , b , α ) = 1 2 ∣ ∣ w ∣ ∣ 2 − ∑ i = 1 n α i ( y i ( w T ⋅ Φ ( x i ) + b ) − 1 ) L(w, b, \alpha) = \frac{1}{2} ||w||^2 - \sum_{i=1}^n \alpha_i(y_i(w^T \cdot \Phi(x_i) + b) - 1) L(w,b,α)=21∣∣w2i=1nαi(yi(wTΦ(xi)+b)1)

其中,上式后半部分:

− ∑ i = 1 n α i ( y i ( w T ⋅ Φ ( x i ) + b ) − 1 ) = 0 -\sum_{i=1}^n \alpha_i(y_i(w^T \cdot \Phi(x_i) + b) - 1) = 0 i=1nαi(yi(wTΦ(xi)+b)1)=0

走到这一步,这个目标函数还是不能开始求解,现在我们的问题是极小极大值问题。

3.3.2.2 对偶问题

我们要将其转换为对偶问题,变成极大极小值问题:

从 min ⁡ max ⁡ L ( w , b , α ) 变为 max ⁡ α min ⁡ w , b L ( w , b , α ) 从 \min \max L(w, b, \alpha) \quad 变为 \quad \underset{\alpha}{\max} \underset{w, b}{\min} L(w, b, \alpha) minmaxL(w,b,α)变为αmaxw,bminL(w,b,α)

在最优化问题中,对偶问题是指通过转换原问题来求解最优目标函数的一种方法。通俗来讲,对偶问题就是使求解更加高效且目标函数值不变,通过先消去 w w w b b b,得到关于 α \alpha α 的函数,然后单独计算 α \alpha α ,通过得到的 α \alpha α 反求 w w w b b b,最后获得超平面的参数,相比于先对 α \alpha α 的不等式约束进行计算,对偶的方式使得计算更加便捷。

简单来说:对于一个函数而言,它的极大值中的极小值就是极小值中的极大值(注意,这句话其实是有很大问题的,这里主要是为了理解)。

参考资料: 运筹学_8 对偶问题概念 转换方法

如何获取对偶函数?

首先我们对原目标函数的 w w w b b b 分别求导:

  • 原目标函数: L ( w , b , α ) = 1 2 ∣ ∣ w ∣ ∣ 2 − ∑ i = 1 n α i ( y i ( w T ⋅ Φ ( x i ) + b ) − 1 ) L(w, b, \alpha) = \frac{1}{2} ||w||^2 - \sum_{i=1}^n \alpha_i(y_i(w^T \cdot \Phi(x_i) + b) - 1) L(w,b,α)=21∣∣w2i=1nαi(yi(wTΦ(xi)+b)1)
  • w w w 求偏导: ∂ L ∂ w = 0 → w = ∑ i = 1 n α i y i Φ ( x n ) \frac{\partial L}{\partial w} = 0 \rightarrow w = \sum_{i=1}^n \alpha_i y_i \Phi(x_n) wL=0w=i=1nαiyiΦ(xn)
  • b b b 求偏导: ∂ L ∂ b = 0 → 0 = ∑ i = 1 n α i y i \frac{\partial L}{\partial b} = 0 \rightarrow 0 = \sum_{i=1}^n \alpha_i y_i bL=00=i=1nαiyi

然后将以上 w w w b b b 的求导函数重新代入原目标函数的 w w w b b b 中,得到的就是原函数的对偶函数:

L ( w , b , α ) = 1 2 ∣ ∣ w ∣ ∣ 2 − ∑ i = 1 n α i ( y i ( w T ⋅ Φ ( x i ) + b ) − 1 ) = 1 2 w T w − w T ∑ i = 1 n α i y i Φ ( x i ) − b ∑ i = 1 n α i y i + ∑ i = 1 n α i = 1 2 w T ∑ i = 1 n α i y i Φ ( x i ) − w T ∑ i = 1 n α i y i Φ ( x i ) − b ⋅ 0 + ∑ i = 1 n α = ∑ i = 1 n α i − 1 2 ( ∑ i = 1 n α i y i Φ ( x i ) ) T ∑ i = 1 n α i y i Φ ( x i ) = ∑ i = 1 n α i − 1 2 ∑ i = 1 n α i α j y i y j Φ T ( x i ) Φ ( x j ) \begin{aligned} L(w, b, \alpha) & = \frac{1}{2} ||w||^2 - \sum_{i=1}^n \alpha_i(y_i(w^T \cdot \Phi(x_i) + b) - 1)\\ & = \frac{1}{2}w^T w - w^T\sum_{i=1}^n\alpha_i y_i \Phi(x_i) - b\sum_{i=1}^n \alpha_i y_i + \sum_{i = 1}^n \alpha_i\\ & = \frac{1}{2}w^T \sum_{i = 1}^n \alpha_i y_i \Phi(x_i) - w^T\sum_{i = 1}^n \alpha_i y_i \Phi(x_i) - b \cdot 0 + \sum_{i=1}^n\alpha\\ & = \sum_{i = 1}^n \alpha_i - \frac{1}{2}\left( \sum_{i=1}^n \alpha_i y_i \Phi(x_i) \right)^T \sum_{i=1}^n \alpha_i y_i \Phi(x_i)\\ & = \sum_{i=1}^n \alpha_i - \frac{1}{2} \sum_{i=1}^n \alpha_i \alpha_j y_i y_j \Phi^T(x_i)\Phi(x_j) \end{aligned} L(w,b,α)=21∣∣w2i=1nαi(yi(wTΦ(xi)+b)1)=21wTwwTi=1nαiyiΦ(xi)bi=1nαiyi+i=1nαi=21wTi=1nαiyiΦ(xi)wTi=1nαiyiΦ(xi)b0+i=1nα=i=1nαi21(i=1nαiyiΦ(xi))Ti=1nαiyiΦ(xi)=i=1nαi21i=1nαiαjyiyjΦT(xi)Φ(xj)

这个对偶函数其实求的是 max ⁡ α min ⁡ w , b L ( w , b , α ) \underset{\alpha}{\max} \underset{w, b}{\min} L(w, b, \alpha) αmaxw,bminL(w,b,α) 中的 min ⁡ L ( w , b ) \min L(w, b) minL(w,b) 部分(因为对 w w w b b b 求了偏导)。于是现在要求的是这个函数的极大值 max ⁡ ( a ) \max(a) max(a),写成公式就是:

a ∗ = argmax α ( ∑ i = 1 n α i − 1 2 ∑ i = 1 n α i α j y i y j Φ T ( x i ) Φ ( x j ) ) a^* = \underset{\alpha}{\text{argmax}} \left( \sum_{i=1}^n \alpha_i - \frac{1}{2} \sum_{i=1}^n \alpha_i \alpha_j y_i y_j \Phi^T(x_i)\Phi(x_j) \right) a=αargmax(i=1nαi21i=1nαiαjyiyjΦT(xi)Φ(xj))

好了,现在我们只需要对上式求出极大值 a a a,然后将 a a a 代入 w w w 求偏导的那个公式:

w = ∑ i = 1 n α i y i Φ ( x n ) w = \sum_{i = 1}^n \alpha_i y_i \Phi(x_n) w=i=1nαiyiΦ(xn)

从而求出 w w w。再将 w w w 代入超平面的表达式,计算 b b b 值。

现在的 w w w b b b 就是我们要寻找的最优超平面的参数。

3.3.2.3 整体流程确定

我们用数学表达式来说明上面的过程:

第一步:首先是求 min ⁡ w , b L ( w , b , α ) \underset{w, b}{\min}L(w, b, \alpha) w,bminL(w,b,α) 的极大值,即:

max ⁡ α ∑ i = 1 n α i − 1 2 ∑ i = 1 n ∑ j = 1 n α i α j y i y j ( Φ T ( x i ) Φ ( x j ) ) s.t. ∑ i = 1 n α i , y i = 0 α i ≥ 0 , i = 1 , 2 , . . . , n \underset{\alpha}{\max}\sum_{i=1}^n \alpha_i - \frac{1}{2} \sum_{i=1}^n \sum_{j=1}^n \alpha_i \alpha_j y_i y_j \left( \Phi^T(x_i)\Phi(x_j) \right)\\ \begin{aligned} \text{s.t.} \quad & \sum_{i=1}^n \alpha_i, y_i = 0\\ & \alpha_i \ge 0, \quad i = 1, 2, ..., n \end{aligned} αmaxi=1nαi21i=1nj=1nαiαjyiyj(ΦT(xi)Φ(xj))s.t.i=1nαi,yi=0αi0,i=1,2,...,n

注意有两个约束条件。

对目标函数添加符号,转换成求极小值:

min ⁡ α 1 2 ∑ i = 1 n ∑ j = 1 n α i α j y i y j ( Φ T ( x i ) Φ ( x j ) ) − ∑ i = 1 n α i s.t. ∑ i = 1 n α i , y i = 0 α i ≥ 0 , i = 1 , 2 , . . . , n \underset{\alpha}{\min}\frac{1}{2} \sum_{i=1}^n\sum_{j=1}^n \alpha_i \alpha_j y_i y_j \left( \Phi^T(x_i)\Phi(x_j) \right) - \sum_{i=1}^n \alpha_i \\ \begin{aligned} \text{s.t.} \quad & \sum_{i=1}^n \alpha_i, y_i = 0\\ & \alpha_i \ge 0, \quad i = 1, 2, ..., n \end{aligned} αmin21i=1nj=1nαiαjyiyj(ΦT(xi)Φ(xj))i=1nαis.t.i=1nαi,yi=0αi0,i=1,2,...,n

第二步:计算上面式子的极值求出 α ∗ \alpha^* α

第三步:将 α ∗ \alpha^* α 代入,计算 w w w b b b

w ∗ = ∑ i = 1 n α i ∗ y i Φ ( x i ) b ∗ = y i − ∑ i = 1 n α i ∗ y i ( Φ ( x i ) ⋅ Φ ( x j ) ) \begin{aligned} & w^* = \sum_{i = 1}^n \alpha_i^* y_i \Phi(x_i)\\ & b^* = y_i - \sum_{i = 1}^n \alpha_i^* y_i \left( \Phi(x_i) \cdot \Phi(x_j) \right) \end{aligned} w=i=1nαiyiΦ(xi)b=yii=1nαiyi(Φ(xi)Φ(xj))

第四步:求得超平面 w ∗ Φ ( x ) + b ∗ = 0 w^* \Phi(x) + b^* = 0 wΦ(x)+b=0

第五步:求得分类决策函数 f ( x ) = s i g n ( w ∗ Φ ( x ) + b ∗ ) f(x) = \mathrm{sign}(w^*\Phi(x) + b^*) f(x)=sign(wΦ(x)+b)

3.4 举例

给定 3 个数据点:正例点 x 1 = ( 3 , 3 ) x_1 = (3,3) x1=(3,3) x 2 = ( 4 , 3 ) x_2 = (4, 3) x2=(4,3),负例点 x 3 = ( 1 , 1 ) x_3 = (1, 1) x3=(1,1),求线性可分支持向量机。我们把这三个点画出来:

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

第一步:首先确定目标函数

  • 求解 1 2 ∑ i = 1 n ∑ j = 1 n α i α j y i y j ( x i ⋅ x j ) − ∑ i = 1 n α i \frac{1}{2}\sum_{i=1}^n \sum_{j=1}^n \alpha_i \alpha_j y_i y_j(x_i \cdot x_j) - \sum_{i=1}^n \alpha_i 21i=1nj=1nαiαjyiyj(xixj)i=1nαi

  • 约束条件 { α 1 + α 2 − α 3 = 0 α i ≥ 0 , i = 1 , 2 , 3 \begin{cases} \alpha_1 + \alpha_2 - \alpha_3 = 0\\ \alpha_i \ge 0, \quad i = 1, 2, 3 \end{cases} {α1+α2α3=0αi0,i=1,2,3

第二步:求得目标函数的极值

  • 原式: 1 2 ∑ i = 1 n ∑ j = 1 n α i α j y i y j ( x i ⋅ x j ) − ∑ i = 1 n α i \frac{1}{2}\sum_{i=1}^n \sum_{j=1}^n \alpha_i \alpha_j y_i y_j(x_i \cdot x_j) - \sum_{i=1}^n \alpha_i 21i=1nj=1nαiαjyiyj(xixj)i=1nαi
  • 把数据代入: 1 2 ( 18 α 1 2 + 25 α 2 2 + 2 α 3 2 + 42 α 1 α 2 − 12 α 1 α 3 − 14 α 2 α 3 ) − α 1 − α 2 − α 3 \frac{1}{2}\left( 18\alpha^2_1 + 25\alpha^2_2 + 2\alpha^2_3 + 42\alpha_1\alpha_2 - 12\alpha_1\alpha_3 -14\alpha_2\alpha_3 \right) - \alpha_1 - \alpha_2 - \alpha_3 21(18α12+25α22+2α32+42α1α212α1α314α2α3)α1α2α3

其中:

18 = 3 2 + 3 2 25 = 4 2 + 3 2 2 = 1 2 + 1 2 42 = ( 3 × 4 + 3 × 3 ) × 2 12 = ( 3 × 1 + 3 × 1 ) × 2 14 = ( 4 × 1 + 3 × 1 ) × 2 \begin{aligned} & 18 = 3^2 + 3^2\\ & 25 = 4^2 + 3^2\\ & 2 = 1^2 + 1^2\\ & 42 = (3 \times 4 + 3 \times 3) \times 2\\ & 12 = (3 \times 1 + 3 \times 1) \times 2\\ & 14 = (4 \times 1 + 3 \times 1) \times 2\\ \end{aligned} 18=32+3225=42+322=12+1242=(3×4+3×3)×212=(3×1+3×1)×214=(4×1+3×1)×2

由于 α 1 + α 2 = α 3 \alpha_1 + \alpha_2 = \alpha_3 α1+α2=α3,化简可得:

4 α 1 2 + 13 2 α 2 2 + 10 α 1 α 2 − 2 α 1 − 2 α 2 4 \alpha^2_1 + \frac{13}{2}\alpha^2_2 + 10 \alpha_1 \alpha_2 - 2\alpha_1 - 2\alpha_2 4α12+213α22+10α1α22α12α2

α 1 \alpha_1 α1 α 2 \alpha_2 α2 求偏导并令其为0可知: s ( α 1 , α 2 ) s(\alpha_1, \alpha_2) s(α1,α2) 在点 ( 1.5 , − 1 ) (1.5, -1) (1.5,1) 处取极值。但是该点不满足条件 α 2 ≥ 0 \alpha_2 \ge 0 α20(约束条件说了, α i ≥ 0 \alpha_i \ge 0 αi0),所以最小值在边界上达到。

  • α 1 = 0 \alpha_1 = 0 α1=0 时,最小值 s ( 0 , 2 13 ) = − 0.1538 s(0, \frac{2}{13}) = -0.1538 s(0,132)=0.1538
  • α 2 = 0 \alpha_2 = 0 α2=0 时,最小值 s ( 1 4 , 0 ) = 1 4 = − 0.25 s(\frac{1}{4}, 0) = \frac{1}{4} = -0.25 s(41,0)=41=0.25

因为 s ( 1 4 , 0 ) = − 0.25 < s ( 0 , 2 13 ) = − 0.1538 s(\frac{1}{4}, 0) = -0.25 < s(0, \frac{2}{13}) = -0.1538 s(41,0)=0.25<s(0,132)=0.1538,所以 s ( α 1 , α 2 ) s(\alpha_1, \alpha_2) s(α1,α2) α 1 = 1 4 , α 2 = 0 \alpha_1 = \frac{1}{4}, \alpha_2 = 0 α1=41,α2=0 时达到最小,此时:

α 3 = α 1 + α 2 = 1 4 \alpha_3 = \alpha_1 + \alpha_2 = \frac{1}{4} α3=α1+α2=41

第三步:将求得到极值代入,从而求得最优参数 w w w b b b

α 1 = α 3 = 1 4 \alpha_1 = \alpha_3 = \frac{1}{4} α1=α3=41 对应的点 ( x 1 , x 3 ) (x_1, x_3) (x1,x3) 就是支持向量机。

对于公式:

w = ∑ i = 1 n α i y i Φ ( x n ) w = \sum_{i=1}^n \alpha_iy_i\Phi(x_n) w=i=1nαiyiΦ(xn)

α \alpha α 的结果代入可知:

w = 1 4 × 1 × ( 3 , 3 ) + 1 4 × ( − 1 ) × ( 1 , 1 ) = ( 1 2 , 1 2 ) b = y i − ∑ i = 1 n ∑ j = 1 n α i y i ( x i ⋅ x j ) = 1 − ( 1 4 × 1 × 18 + 1 4 × ( − 1 ) × 6 ) = − 2 \begin{aligned} & w = \frac{1}{4} \times 1 \times (3,3) + \frac{1}{4} \times (-1) \times (1, 1) = (\frac{1}{2}, \frac{1}{2})\\ & b = y_i - \sum_{i=1}^n\sum_{j=1}^n \alpha_i y_i (x_i\cdot x_j) = 1 - (\frac{1}{4} \times 1 \times 18 + \frac{1}{4} \times( -1) \times 6) = -2 \end{aligned} w=41×1×(3,3)+41×(1)×(1,1)=(21,21)b=yii=1nj=1nαiyi(xixj)=1(41×1×18+41×(1)×6)=2

因此可知,平面方程为:

0.5 x 1 + 0.5 x 2 − 2 = 0 0.5x_1 + 0.5x_2 - 2 = 0 0.5x1+0.5x22=0

第四步:分离超平面

故可知分离超平面为:

0.5 x 1 + 0.5 x 2 − 2 = 0 0.5x_1 + 0.5x_2 - 2 = 0 0.5x1+0.5x22=0

第五步:分离决策函数

由于分离超平面可知,故分离决策函数也可知:

f ( x ) = s i g n ( 0.5 x 1 + 0.5 x 2 − 2 ) f(x) = \mathrm{sign}(0.5x_1 + 0.5x_2 - 2) f(x)=sign(0.5x1+0.5x22)

另一种计算方式(参考):SVM-求解最大间隔分离超平面


小结

  • SVM 中目标函数 max ⁡ w , b = 1 2 ∣ ∣ w ∣ ∣ 2 s.t. y i ( w T x i + b ) ≥ + 1 , i = 1 , 2 , . . . , m \underset{w, b}{\max} = \frac{1}{2}||w||^2 \quad \text{s.t.} \quad y_i(w^Tx_i + b) \ge +1, \quad i=1, 2, ..., m w,bmax=21∣∣w2s.t.yi(wTxi+b)+1,i=1,2,...,m
  • SVM 中目标函数的求解过程
    1. 首先是求 min ⁡ w , b L ( w , b , α ) \underset{w, b}{\min}L(w, b, \alpha) w,bminL(w,b,α) 的极大值,即: max ⁡ α ∑ i = 1 n α i − 1 2 ∑ i = 1 n ∑ j = 1 n α i α j y i y j ( Φ T ( x i ) Φ ( x j ) ) s.t. ∑ i = 1 n α i , y i = 0 α i ≥ 0 , i = 1 , 2 , . . . , n \underset{\alpha}{\max}\sum_{i=1}^n \alpha_i - \frac{1}{2} \sum_{i=1}^n \sum_{j=1}^n \alpha_i \alpha_j y_i y_j \left( \Phi^T(x_i)\Phi(x_j) \right)\\ \begin{aligned} \text{s.t.} \quad & \sum_{i=1}^n \alpha_i, y_i = 0\\ & \alpha_i \ge 0, \quad i = 1, 2, ..., n \end{aligned} αmaxi=1nαi21i=1nj=1nαiαjyiyj(ΦT(xi)Φ(xj))s.t.i=1nαi,yi=0αi0,i=1,2,...,n注意有两个约束条件。
      对目标函数添加符号,转换成求极小值: min ⁡ α 1 2 ∑ i = 1 n ∑ j = 1 n α i α j y i y j ( Φ T ( x i ) Φ ( x j ) ) − ∑ i = 1 n α i s.t. ∑ i = 1 n α i , y i = 0 α i ≥ 0 , i = 1 , 2 , . . . , n \underset{\alpha}{\min}\frac{1}{2} \sum_{i=1}^n\sum_{j=1}^n \alpha_i \alpha_j y_i y_j \left( \Phi^T(x_i)\Phi(x_j) \right) - \sum_{i=1}^n \alpha_i \\ \begin{aligned} \text{s.t.} \quad & \sum_{i=1}^n \alpha_i, y_i = 0\\ & \alpha_i \ge 0, \quad i = 1, 2, ..., n \end{aligned} αmin21i=1nj=1nαiαjyiyj(ΦT(xi)Φ(xj))i=1nαis.t.i=1nαi,yi=0αi0,i=1,2,...,n
    2. 计算上面式子的极值求出 α ∗ \alpha^* α
    3. α ∗ \alpha^* α 代入,计算 w w w b b b w ∗ = ∑ i = 1 n α i ∗ y i Φ ( x i ) b ∗ = y i − ∑ i = 1 n α i ∗ y i ( Φ ( x i ) ⋅ Φ ( x j ) ) \begin{aligned} & w^* = \sum_{i = 1}^n \alpha_i^* y_i \Phi(x_i)\\ & b^* = y_i - \sum_{i = 1}^n \alpha_i^* y_i \left( \Phi(x_i) \cdot \Phi(x_j) \right)\end{aligned} w=i=1nαiyiΦ(xi)b=yii=1nαiyi(Φ(xi)Φ(xj))
    4. 求得超平面 w ∗ Φ ( x ) + b ∗ = 0 w^* \Phi(x) + b^* = 0 wΦ(x)+b=0
    5. 求得分类决策函数 f ( x ) = s i g n ( w ∗ Φ ( x ) + b ∗ ) f(x) = \mathrm{sign}(w^*\Phi(x) + b^*) f(x)=sign(wΦ(x)+b)

4. SVM 的损失函数

学习目标

  • 了解 SVM 的损失函数
  • 知道 SVM 中的 Hinge 损失函数

SVM 之所以这么成功,主要取决于两个因素:

  1. 损失函数
  2. 核函数

在 SVM 中,我们主要讨论三种损失函数:

  1. 0/1 损失
  2. Hinge 损失函数
  3. Logistic 损失函数

Hinge:英[hɪndʒ] 美[hɪndʒ]
n. 铰链; 合叶;
vt. 给(某物)装铰链;

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

绿色:0/1 损失

  • 当正例的点落在 y = 0 y=0 y=0 这个超平面的下边,说明是分类正确。无论距离超平面所远多近,误差都是0。
  • 当这个正例的样本点落在 y = 0 y=0 y=0 的上方的时候,说明分类错误。无论距离多远多近,误差都为1。
  • 图像就是上图绿色线。

简单来讲,分对了误差为0,分错了误差为1,就是这么绝对,就是这么二极管😂。

蓝色:SVM Hinge损失函数

  • 当一个正例的点落在 y = 1 y=1 y=1 的直线上,距离超平面( y = 0 y=0 y=0 是超平面)长度 1,那么 1 − ξ = 1 1-\xi=1 1ξ=1 ξ = 0 \xi=0 ξ=0,也就是说误差为 0。
  • 当它落在距离超平面 0.5 的地方, 1 − ξ = 0.5 1-\xi=0.5 1ξ=0.5 ξ = 0.5 \xi=0.5 ξ=0.5,也就是说误差为 0.5(其实这个点已经分对了,对还不够好,所以存在损失)
  • 当它落在 y = 0 y=0 y=0 直线上时,距离为 0, 1 − ξ = 0 1-\xi=0 1ξ=0 ξ = 1 \xi=1 ξ=1,误差为 1
  • 当这个点落在了 y = 0 y=0 y=0 直线的上方,被误分到了负例中(分错了),距离算出来应该是负的,比如 -0.5,那么 1 − ξ = − 0.5 1-\xi=-0.5 1ξ=0.5 ξ = − 1.5 \xi=-1.5 ξ=1.5,误差为 1.5
  • 以此类推,画在二维坐标上就是上图中蓝色那根线了。

ξ \xi ξ 就是误差

红色:Logistic损失函数

  • 损失函数的公式为: ln ⁡ ( 1 + e − y i ) \ln(1+e^{-y_i}) ln(1+eyi)
    • y i = 0 y_i=0 yi=0 时,损失等于 ln ⁡ \ln ln,这样真丑,所以我们给这个损失函数除以 ln ⁡ 2 \ln2 ln2。所以当 y i = 0 y_i=0 yi=0 时,损失为 1,即损失函数过 ( 0 , 1 ) (0,1) (0,1)
    • 即上图中的红色线。

对于支持向量机(SVM),这三种损失函数各有优缺点。

  • 0/1 损失:0/1 损失是一种直观的损失函数,它将分类正确的样本损失设为 0,分类错误的样本损失设为 1。但是,0/1 损失不是连续函数,不利于优化问题的求解。

  • Hinge 损失函数:Hinge 损失函数是 SVM 中使用的损失函数。它使得 y f ( x ) > 1 yf(x)>1 yf(x)>1 的样本损失皆为 0,由此带来了稀疏解,使得 SVM 仅通过少量的支持向量就能确定最终超平面。

  • Logistic 损失函数:Logistic 损失函数是逻辑回归中使用的损失函数。它给出了后验概率,但对异常值敏感。


小结

  • SVM 的损失函数:
    • 0/1 损失函数
    • Hinge 损失函数
    • Logistic 损失函数

5. SVM 的核方法

学习目标

  • 知道 SVM 的核方法
  • 了解常见的核函数

SVM + 核函数 具有极大威力。

核函数并不是 SVM 特有的,核函数可以和其他算法也进行结合,只是核函数与 SVM 结合的优势非常大。

5.1 什么是核函数

5.1.1 核函数概念

核函数,是将原始输入空间映射到新的特征空间,从而使得原本线性不可分的样本可能在核空间可分

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

上图所示的两类数据,分别分布为两个圆圈的形状(大圆套着小圆),这样的数据本身就是线性不可分的,此时该如何把这两类数据分开呢?

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

假设 X X X 是输入空间, H H H 是特征空间,存在一个映射 ϕ \phi ϕ 使得 X X X 中的点 x x x 能够计算得到 H H H 空间中的点 h h h,且对于所有的 X X X 中的点都成立。

h = ϕ ( x ) h = \phi(x) h=ϕ(x)

x x x z z z X X X 空间中的点,函数 k ( x , z ) k(x,z) k(x,z) 满足下述条件:

k ( x , z ) = ϕ ( x ) ⋅ ϕ ( z ) k(x, z) = \phi(x) \cdot \phi(z) k(x,z)=ϕ(x)ϕ(z)

如果都成立,则称函数 k k k 为核函数,而 ϕ \phi ϕ 为映射函数。

5.1.2 核函数举例

5.1.2.1 举例 1

ϕ : R 2 → R 3 ( x 1 , x 2 ) → ( z 1 , z 2 , z 3 ) = ( x 1 2 , 2 x 1 x 2 , x 2 2 ) \begin{aligned} & \phi: R^2 \rightarrow R^3\\ & (x_1, x_2) \rightarrow (z_1, z_2, z_3) = (x^2_1, \sqrt{2}x_1x_2, x_2^2) \end{aligned} ϕ:R2R3(x1,x2)(z1,z2,z3)=(x12,2 x1x2,x22)

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

< ϕ ( x 1 , x 2 ) ϕ ( x 1 ′ , x 2 ′ ) > = < ( z 1 , z 2 , z 3 ) ( z 1 ′ , z 2 ′ , z 3 ′ ) > = < ( x 1 2 , 2 x 1 x 2 , x 2 2 ) ( x 1 ′ 2 , 2 x 1 ′ x 2 ′ , x 2 ′ 2 ) > = x 1 2 x 1 ′ 2 + 2 x 1 x 2 x 1 ′ x 2 ′ + x 2 2 x 2 ′ 2 = ( x 1 x 1 ′ + x 2 x 2 ′ ) 2 = ( < x , x ′ > ) 2 = K ( x , x ′ ) \begin{aligned} \left< \phi(x_1, x_2) \phi(x'_1, x'_2) \right> & = \left< (z_1, z_2, z_3)(z'_1, z'_2, z'_3) \right> \\ & = \left< (x_1^2, \sqrt{2}x_1x_2, x_2^2)(x'^2_1, \sqrt{2}x'_1x'_2, x'^2_2) \right>\\ & = x_1^2x'^2_1 + 2x_1x_2x'_1x'_2 + x^2_2x'^2_2\\ & = (x_1x'_1 + x_2x'_2)^2\\ & = (\left< x, x' \right>)^2\\ & = \mathcal{K}(x, x') \end{aligned} ϕ(x1,x2)ϕ(x1,x2)=(z1,z2,z3)(z1,z2,z3)=(x12,2 x1x2,x22)(x1′2,2 x1x2,x2′2)=x12x1′2+2x1x2x1x2+x22x2′2=(x1x1+x2x2)2=(x,x)2=K(x,x)

经过上面公式,具体变换过过程为:

x = ( x 1 , x 2 , x 3 ) = ( 1 , 2 , 3 ) y = ( y 1 , y 2 , y 3 ) = ( 4 , 5 , 6 ) f ( x ) = ( x 1 x 1 , x 1 x 2 , x 1 x 3 , x 2 x 1 , x 2 x 2 , x 2 x 3 , x 3 x 1 , x 3 x 2 , x 3 x 3 ) f ( x ) = ( 1 , 2 , 3 , 2 , 4 , 6 , 3 , 6 , 9 ) f ( y ) = ( 16 , 20 , 24 , 20 , 25 , 36 , 24 , 30 , 36 ) < f ( x ) , f ( y ) > = 16 + 40 + 72 + 40 + 100 + 180 + 72 + 180 + 324 = 1024 K ( x , y ) = ( < z , y > ) 2 − < f ( x ) , f ( y ) > = ( 4 + 10 + 18 ) 2 − 3 2 2 = 1024 \begin{aligned} & x = (x_1,x_2,x_3) = (1,2,3)\\ & y = (y_1, y_2, y_3)= (4,5,6)\\ & f(x) = (x_1x_1, x_1x_2, x_1x_3, x_2x_1, x_2x_2, x_2x_3, x_3x_1, x_3x_2, x_3x_3)\\ & f(x) = (1,2,3,2,4,6,3,6,9)\\ & f(y) = (16,20,24,20,25, 36, 24, 30, 36)\\ & \left< f(x),f(y) \right> = 16 + 40 + 72 + 40 + 100 + 180 + 72 + 180 + 324 = 1024\\ & \mathcal{K}(x, y) = (\left< z,y \right>)^2 - \left< f(x),f(y) \right> =(4 + 10 + 18)^2- 32^2 = 1024 \end{aligned} x=(x1,x2,x3)=(1,2,3)y=(y1,y2,y3)=(4,5,6)f(x)=(x1x1,x1x2,x1x3,x2x1,x2x2,x2x3,x3x1,x3x2,x3x3)f(x)=(1,2,3,2,4,6,3,6,9)f(y)=(16,20,24,20,25,36,24,30,36)f(x),f(y)=16+40+72+40+100+180+72+180+324=1024K(x,y)=(z,y)2f(x),f(y)=(4+10+18)2322=1024

5.1.2.2 举例 2

下面这张图位于第一、二象限内。我们关注红色的门,以及“北京四合院”这几个字和下面的紫色的字母。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

我们把红色的门上的点看成是“+”数据,字母上的点看成是“-”数据,它们的横、纵坐标是两个特征。显然,在这个二维空间内,“+”和“-”两类数据不是线性可分的。

简单来说,黑色和红色不是线性可分的。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

如上图所示,将二维数据映射到三维空间后,可以使用绿色的平面完美地分割 红色 和 紫色,因此二维数据在三维空间中变成线性可分的了。

前后轴为 x x x 轴,左右轴为 y y y 轴,上下轴为 z z z

将切分回到二维平面,如下图所示。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

我们可以看到,三维空间中判决边界再映射回二维空间后,并不是一条直线,而是是一条双曲线,它不是线性的。


通过上述的例子我们可以知道,核函数的作用就是一个从低维空间到高维空间的映射,而这个映射可以把低维空间中线性不可分的两类点变成线性可分的。

5.2 常见核函数

名称 表达式 参数
线性核 K ( x i , x j ) = x i T x j \mathcal{K}(x_i, x_j) = x_i^Tx_j K(xi,xj)=xiTxj x i x_i xi x j x_j xj 为输入向量,表示数据集中的两个样本
多项式核 K ( x i , x j ) = ( x i T x j ) d \mathcal{K}(x_i, x_j) = (x_i^Tx_j)^d K(xi,xj)=(xiTxj)d d ≥ 1 d\ge 1 d1 为多项式的次数
高斯核 K ( x i , x j ) = exp ⁡ ( − ∣ x i − x j ∣ 2 2 σ 2 ) \mathcal{K}(x_i, x_j) = \exp\left( -\frac{|x_i - x_j|^2}{2\sigma^2} \right) K(xi,xj)=exp(2σ2xixj2) σ > 0 \sigma > 0 σ>0 为高斯核的带宽(width), ∣ x i − x j ∣ |x_i - x_j| xixj 表示 x i x_i xi x j x_j xj 之间的欧几里得距离
拉普拉斯核 K ( x i , x j ) = exp ⁡ ( − ∣ x i − x j ∣ σ ) \mathcal{K}(x_i, x_j) = \exp\left( -\frac{|x_i - x_j|}{\sigma} \right) K(xi,xj)=exp(σxixj) σ > 0 \sigma > 0 σ>0,控制了核函数的宽度
Sigmoid 核 K ( x i , x j ) = tanh ⁡ ( β x i T x j + θ ) \mathcal{K}(x_i, x_j) = \tanh(\beta x_i^Tx_j + \theta) K(xi,xj)=tanh(βxiTxj+θ) tanh ⁡ \tanh tanh 为双曲正切函数, β > 0 \beta > 0 β>0 θ < 0 \theta < 0 θ<0 β \beta β 是一个缩放因子,它控制了输入向量 x i T x j x_i^Tx_j xiTxj 的缩放程度; θ \theta θ 是一个常数偏置项,它控制了双曲正切函数的水平位移
  1. 多项核中,当 d = 1 d=1 d=1 时,退化为线性核
  2. 高斯核亦称为 RBF 核(Radial Basis Function,径向基函数)。
  • 线性核和多项式核
    • 这两种核的作用也是首先在属性空间中找到一些点,把这些点当做 base,核函数的作用就是找与该点距离和角度满足某种关系的样本点。
      • 当样本点与该点的夹角近乎垂直时,两个样本的欧式长度必须非常长才能保证满足线性核函数大于0
      • 而当样本点与 base 点的方向相同时,长度就不必很长
      • 而当方向相反时,核函数值就是负的,被判为反类。即它在空间上划分出一个梭形,按照梭形来进行正反类划分。
  • RBF 核(高斯核)
    • 高斯核函数就是在属性空间中找到一些点,这些点可以是也可以不是样本点,把这些点当做base。
      • 以这些 base 为圆心向外扩展(画圆),扩展半径即为带宽,即可划分数据。
      • 换句话说,在属性空间中找到一些超圆,用这些超圆来判定正反类。
  • Sigmoid 核
    • 同样地是定义一些 base。
    • 核函数就是将线性核函数经过一个 tanh ⁡ \tanh tanh 函数进行处理,把值域限制在了-1到1上。
    • 总之,都是在定义距离,大于该距离,判为正,小于该距离,判为负。至于选择哪一种核函数,要根据具体的样本分布情况来确定。

核函数选择的指导规则

  1. 如果 Feature 的数量很大,甚至和样本数量差不多时,往往线性可分,这时选用 LR(线性回归)或者线性核 Linear
  2. 如果 Feature 的数量很小,样本数量正常,不算多也不算少,这时选用 RBF 核(高斯核)
  3. 如果 Feature 的数量很小,而样本的数量很大,这时手动添加一些 Feature,使得线性可分,然后选用 LR 或者线性核 Linear
  4. 多项式核一般很少使用,效率不高,结果也不优于 RBF
  5. 特点:
    • 线性核参数少,速度快;
    • RBF 核参数多,分类结果非常依赖于参数,需要交叉验证或网格搜索最佳参数,比较耗时
  6. 应用最广的应该就是 RBF 核,无论是小样本还是大样本,高维还是低维等情况,RBF 核函数均适用。

我们一般优先使用 RBF 高斯核进行计算


Q:高斯核为什么叫做 RBF 核?
A:RBF 是 Radial Basis Function(径向基函数)的缩写。径向基函数是一类以原点为中心,对称于原点的函数。它们通常用来描述以某个点为中心,向外扩散的过程。高斯核函数是一种常用的径向基函数,它的表达式为 K ( x i , x j ) = exp ⁡ ( − ∥ x i − x j ∥ 2 2 σ 2 ) \mathcal{K}(x_i, x_j) = \exp\left( -\frac{\|x_i - x_j\|^2}{2\sigma^2} \right) K(xi,xj)=exp(2σ2xixj2),其中 σ > 0 \sigma > 0 σ>0 是高斯核的带宽(width), ∥ x i − x j ∥ \|x_i - x_j\| xixj 表示 x i x_i xi x j x_j xj 之间的欧几里得距离。由于高斯核函数是一种径向基函数,因此它也被称为 RBF 核


小结

  • SVM 的核方法:
    • 将原始输入空间映射到新的特征空间,从而使得原本线性不可分的样本可能在核空间可分。
  • 常见核函数
    • 线性核
    • 多项式核
    • RBF 核
    • Sigmoid 核

6. SVM 回归

学习目标

  • 了解 SVM 回归的实现原理

SVM 回归与 SVM 的分类有一些区别。SVM 的回归是让尽可能多的实例位于预测线上,同时限制间隔违例(也就是不在预测线距上的实例)。

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

线距的宽度由超参数 ϵ \epsilon ϵ 控制。

SVM 的目的是让图中的点在线上就可以。SVM 本身是有一个最大间隔的(不管是回归还是分类,这个最大间隔都是存在的),这个最大间隔通过 ϵ \epsilon ϵ 决定:

  • ϵ \epsilon ϵ 越大,最大间隔越大
  • ϵ \epsilon ϵ 越小,最大间隔越小

要想让 SVM 实现回归,API 应该使用 SVR(之前分类用的是 SVC),具体的 API 接下来会讲到。

7. SVM 算法 API 再介绍

学习目标

  • 知道 SVM 算法 API 中的 SvV、NuSVC、LinearSVC

7.1 SVM 算法 API 综述

SVM 方法既可以用于分类(二/多 分类),也可用于回归和异常值检测。

SVM 具有良好的鲁棒性,对未知数据拥有很强的泛化能力,特别是在数据量较少的情况下,相较其他传统机器学习算法具有更优的性能。


使用 SVM 作为模型时,通常采用如下流程:

  1. 对样本数据进行归一化
  2. 应用核函数对样本进行映射(最常采用的核函数是 RBF 核和 Linear核。在样本线性可分时,Linear 核的效果要比 RBF 核好)
  3. 用 Cross-Validation(交叉验证,CV)和 Grid-Search(网格搜索,GS)对超参数进行优选
  4. 用最优参数训练得到模型
  5. 模型测试

sklearn 中支持向量分类主要有三种方法:SVC、NuSVC、LinearSVC,扩展为三个支持向量回归方法:

  1. SVR
  2. NuSVR
  3. LinearSVR
  • SVC 和 NuSVC 方法基本一致,唯一区别就是损失函数的度量方式不同
    • NuSVC 中的 nu 参数和 SVC 中的 C 参数
  • LinearSVC 是实现线性核函数的支持向量分类,没有 kernel 参数

7.2 SVC

class sklearn.svm.SVC(C=1.0,kernel='rbf', degree=3, coef0=0.0, random_state=None)
  • 作用sklearn.svm.SVC 是 scikit-learn 库中的一个类,用于进行 C-支持向量分类。它基于 libsvm 实现,拟合时间至少与样本数量的平方成正比,对于超过数万个样本的大型数据集可能不切实际。对于大型数据集,可以考虑使用 LinearSVC 或 SGDClassifier,也可以在使用 Nystroem 变换器或其他核近似之后使用。
  • 参数
    • C:正则化参数(惩罚系数)。用来控制损失函数的惩罚系数,类似于线性回归中的正则化系数。正则化强度与 C 成反比。必须严格为正。惩罚是平方 l2 惩罚。
      • C 越大,相当于惩罚松弛变量,希望松弛变量接近0,即对误分类的惩罚增大,趋向于对训练集全分对的情况,这样会出现训练集测试时准确率很高,但泛化能力弱,容易导致过拟合。
      • C 值小,对误分类的惩罚减小,容错能力增强,泛化能力较强,但也可能欠拟合。
    • kernel:算法中采用的核函数类型,核函数是用来将非线性问题转化为线性问题的一种方法。
      • 默认使用"rbf":即高斯核
      • “Linear”:线性核函数
      • “Poly”:多项式核
      • “Sigmoid”:双曲正切tanh函数核
    • degree:多项式内核函数(“poly”)的次数。
      • 默认为3次多项式。
      • 必须为非负数。
      • 所有其他内核都忽略它。
    • coef0:内核函数中的独立项,即 y = k x + b y=kx+b y=kx+b 中的 b b b 值。
      • 默认为0。
      • 仅在 “poly” 和 “sigmoid” 中有意义。
    • random_state:控制伪随机数生成以进行混洗和概率估计时使用的交叉验证。传递一个 int 以获得可重复的输出。
  • 方法
    • fit
    • predict
    • score

7.3 NuSVC

class sklearn.svm.NuSVC(nu=0.5)
  • 作用sklearn.svm.NuSVC 是 scikit-learn 库中的一个类,用于进行 Nu-支持向量分类。它与 SVC 类似,但使用一个参数来控制支持向量的数量。它基于 libsvm 实现。

  • 参数说明

    • nu:边界误差的上限和支持向量分数的下限(训练误差部分的上限和支持向量部分的下限)。应在区间 ( 0 , 1 ] (0, 1] (0,1] 内,默认是 0.5。
    • kernel:指定算法中要使用的内核类型。如果没有给出,则将使用“rbf”。如果给定了可调用对象,则用它来预先计算内核矩阵。
    • degree:多项式内核函数(“poly”)的次数。必须为非负数。所有其他内核都忽略它。
    • coef0:内核函数中的独立项。仅在“poly”和“sigmoid”中有意义。
    • random_state:控制伪随机数生成以进行混洗和概率估计时使用的交叉验证。传递一个 int 以获得可重复的输出。
  • 方法

    • fit
    • predict
    • score

NuSVC 和 SVC 的唯一区别就是多了一个参数 Nu,即 ν \nu ν

7.4 LinearSVC

class sklearn.svm.LinearSVC(penalty='l2', loss='squared_hinge', dual=True, C=1.0)
  • 作用sklearn.svm.LinearSVC 是 scikit-learn 库中的一个类,用于进行线性支持向量分类。它与参数 kernel='linear' 的 SVC 类似,但是以 liblinear 而不是 libsvm 的形式实现,因此它在惩罚和损失函数的选择方面具有更大的灵活性,并且应该更好地扩展到大量样本。该类支持密集和稀疏输入,多类支持根据一对多方案进行处理。

  • 参数说明

    • penalty:指定用于惩罚的范数。
      • ‘l2’ 惩罚是 SVC 中使用的标准。
      • ‘l1’ 导致 coef_ 向量稀疏。
      • penalty 参数是 线性 SVC 独有的
    • loss:指定损失函数。有 “hinge” 和 “squared_hinge” 两种可选:
      • "hinge"称为 L1 损失
      • "squared_hinge"称为 L2 损失
      • 默认是 “squared_hinge”
        • "hinge"是 SVM 的标准损失
        • “squared_hinge” 是 “hinge” 的平方
    • dual:是否转化为对偶问题求解,默认是True。
      • 当 n_samples > n_features 时,建议使用 dual=False。
    • C:正则化参数。用来控制损失函数的惩罚系数,类似于线性回归中的正则化系数。正则化强度与 C 成反比。必须严格为正。
  • 方法

    • fit
    • predict
    • score

三种 SVC 中用的最多的就是 SVC(原始的SVC)


小结

  • SVM 的核方法:
    • 将原始输入空间映射到新的特征空间,从而,使得原本线性不可分的样本可能在核空间可分。
  • SVM 算法 API
    • sklearn.svm.SVC
    • sklearn.svm.NuSVC
    • sklearn.svm.LinearSVC

8. SVM 案例实践:数字识别器

学习目标

  • 应用 SVM 算法实现数字识别器

8.1 案例背景介绍

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

数据集下载地址:Digit Recognizer

MNIST(“修改后的国家标准与技术研究所”)是计算机视觉事实上的 “hello world” 数据集。自 1999 年发布以来,这一经典的手写图像数据集已成为分类算法基准测试的基础。随着新的机器学习技术的出现,MNIST 仍然是研究人员和学习者的可靠资源。

MNIST 是 Modified National Institute of Standards and Technology database 的缩写。它是一个大型手写数字数据库,常用于训练各种图像处理系统。该数据库也广泛用于机器学习领域的训练和测试。

本次案例中,我们的目标是从数万个手写图像的数据集中正确识别数字。

8.2 数据介绍

数据文件 train.csvtest.csv 包含从 0 到 9 的手绘数字的灰度图像。每个图像的高度为 28 个像素,宽度为 28 个像素,总共为 784 个像素(正方形)。

每个像素具有与其相关联的单个像素值,指示该像素的亮度或暗度,较高的数字意味着较亮。该像素值是 0 到 255 之间的整数(包括 0 和 255)。

训练数据集(train.csv)有 785 列。第一列称为“标签”,是用户绘制的数字。其余列包含关联图像的像素值。

训练集中的每个像素列都具有像 p i x e l x \mathrm{pixel}_x pixelx 这样的名称,其中 x x x 是 0 到 783 之间的整数(包括 0 和 783)。为了在图像上定位该像素,假设我们已经将 x x x 分解为 x = i × 28 + j x = i \times 28 + j x=i×28+j,其中 i i i j j j 是 0 到 27 之间的整数(包括 0 和27)。然后, p i x e l x \mathrm{pixel}_x pixelx 位于 28 × 28 28 \times 28 28×28 矩阵的第 i i i 行和第 j j j 列上(索引为0)。

例如, p i x e l 31 \mathrm{pixel}_{31} pixel31 表示从左边开始的第 4 列中的像素,以及从顶部开始的第 2 行,如下面的 ASCII 图中所示。在视觉上,如果我们省略“像素(pixel)”的前缀,像素组成图像如下:

000 001 002 003 ... 026 027
028 029 030 031 ... 054 055
056 057 058 059 ... 082 083
 |   |   |   |  ...  |   |
728 729 730 731 ... 754 755
756 757 758 759 ... 782 783

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

测试数据集(test.csv)与训练集相同,只是它不包含“标签”列。

8.3 代码实现

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.model_selection import train_test_split

8.3.1 获取数据

# 1. 获取数据
train = pd.read_csv("./data/digit-recognizer/train.csv")
print(train.shape)  # (42000, 785)
train.head()

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

我们可以看到,MNIST 数据集中,训练集的样本数量很多,且特征数也很多,这么多的特征数是不利于模型训练的,此时我们可以对其进行降维。

从上图可以看到,特征值和目标值是在一起的,所以我们需要将其进行分离:

# 获取图片数据
train_image = train.iloc[:, 1:]
train_image.head()

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

# 获取目标值
train_label = train.iloc[:, :1]
train_label.head()

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)


我们可以查看一下具体的图像:

# 查看一下具体的图像
train_exp = train_image.iloc[0, :]
print(train_exp)
"""
pixel0      0
pixel1      0
pixel2      0
pixel3      0
pixel4      0
           ..
pixel779    0
pixel780    0
pixel781    0
pixel782    0
pixel783    0
Name: 0, Length: 784, dtype: int64
"""

# 我们发现此时还是带着index列的,我们将其去除一下
train_exp = train_exp.values
print(train_exp)
"""
[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0 188 255  94   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 191 250 253
  93   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0 123 248 253 167  10   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  80 247 253
 208  13   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0  29 207 253 235  77   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  54 209 253
 253  88   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0  93 254 253 238 170  17   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  23 210 254
 253 159   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0  16 209 253 254 240  81   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  27 253
 253 254  13   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0  20 206 254 254 198   7   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 168
 253 253 196   7   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0  20 203 253 248  76   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  22
 188 253 245  93   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0 103 253 253 191   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
  89 240 253 195  25   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0  15 220 253 253  80   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0  94 253 253 253  94   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0  89 251 253 250 131   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0 214 218  95   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0]
"""

# 此时我们仍然看不出来到底是怎样的数字(主要是print函数打印不下了,其实是可以看出来的),我们画一下就清晰明了了
train_exp = train_exp.reshape(28, 28)

plt.figure(dpi=100)
plt.imshow(train_exp)
plt.axis("off")  # 关闭轴
plt.show()

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

为了能够更加方便的展示数据,我们写一个函数:

def show_digit(n):
    """
        n:展示第n张图片
    """
    show_img = train_image.iloc[n, :].values.reshape(28, 28)
    plt.figure(dpi=100)
    plt.imshow(show_img)
    plt.axis("off")  # 关闭轴
    plt.show()
    

show_digit(50)

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

8.3.2 数据基本处理

因为灰度图的取值范围是 [ 0 , 255 ] [0, 255] [0,255],落差太大了,不利于模型的训练,因此我们需要对其进行归一化处理。归一化的方式也很简单,直接除以 255 即可。

# 2. 数据基本处理
# 对数据特征值进行归一化
train_image = train_image.values / 255  # 这样处理后,就没有第一列了
print("数据最大值为:", np.max(train_image))
train_image
数据最大值为:1.0

array([[0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]])

我们还需要对目标值进行处理,现在的目标值是带有索引列的,这个索引列我们是不需要的。

train_label = train_label.values
train_label
array([[1],
       [0],
       [1],
       ...,
       [7],
       [6],
       [9]], dtype=int64)

接下来我们需要对数据集进行划分,分为训练集和测试集(因为 MNIST 的测试集没有 Ground Truth,因此我们只使用训练集):

x_train, x_test, y_train, y_test = train_test_split(train_image, train_label, train_size=0.8, random_state=0)

print("x_train.shape:", x_train.shape)
print("x_test.shape:", x_test.shape)
print("y_train.shape:", y_train.shape)
print("y_test.shape:", y_test.shape)
x_train.shape: (33600, 784)
x_test.shape: (8400, 784)
y_train.shape: (33600, 1)
y_test.shape: (8400, 1)

从上面数据的 shape 可以看到,784 个特征还是太大了,所以我们需要对其进行降维。可以考虑对数据进行降维,原因有以下几点:

  1. 计算效率:当数据维度很高时,计算量会很大,这会导致模型训练和预测速度变慢。通过降维,可以减少计算量,提高计算效率。

  2. 去除冗余信息:原始数据中可能存在冗余信息或噪声,这些信息对模型的预测能力没有帮助,甚至会影响模型的性能。通过降维,可以去除这些冗余信息,提高模型的预测能力。

  3. 可视化:当数据维度很高时,很难直观地观察数据的分布情况。通过降维,可以将高维数据映射到二维或三维空间中,方便进行可视化。

常用的降维方法有主成分分析(PCA)、线性判别分析(LDA)等。

8.3.3 特征降维和模型训练

思路:通过多次使用 PCA 确定最优模型。

# 3. 特征降维和模型训练
import time
from sklearn.decomposition import PCA


def n_components_analysis(n, x_train, y_train, x_test, y_test):
    """
        思路:通过多次使用 PCA 确定最优模型
        
        参数说明:
            n: 降维后的目标维度(可以是整数也可以是小数)
              整数:具体降到多少维
              小数:表示保留百分之多少的信息
            x_train:训练集数据
            y_train:训练集标签
            x_test:测试集数据
            y_test:测试集标签
    """
    # 记录开始时间
    start_tm = time.time()  
    
    # PCA降维实现
    pca = PCA(n_components=n)  # Python中会区分大小写
    print("特征降维传递的参数为:{}".format(n))
    
    # 学习如何降维
    pca.fit(x_train)
    
    # 在训练集和测试集进行降维
    x_train_pca = pca.transform(x_train)
    x_test_pca = pca.transform(x_test)
    
    """
    `pca.fit(x_train)` 是用来训练 PCA 模型的。它会根据训练数据 `x_train` 来计算降维所需的参数,如主成分和方差解释度等。

    `pca.transform` 是用来对数据进行降维的。它会根据训练好的 PCA 模型,将原始数据映射到低维空间中。
        例如,如果我们希望将原始数据降维到 100 维,则可以使用 `pca.transform(x_train)` 将训练数据降维到 100 维,
        使用 `pca.transform(x_test)` 将测试数据降维到 100 维。
    
    需要注意的是,在对测试数据进行降维时,应该使用与训练数据相同的 PCA 模型,即使用相同的主成分和方差解释度等参数。
    """
    
    # 利用 SVM 进行模型训练(这里使用常见的svc)
    svc = svm.SVC()
    
    print("开始使用SVC进行训练")
    """
        svc.fit 函数期望接收一个一维数组作为标签,而不是一个列向量。
        因此我们需要借助 .ravel()方法 将多维数组展平为一维数组。
        
            例如,如果 y_train 是一个形状为 (n_samples, 1) 的列向量,
            则 y_train.ravel() 会返回一个形状为 (n_samples,) 的一维数组。
    """
    svc.fit(x_train_pca, y_train.ravel())
    
    # 获取accuracy结果
    acc = svc.score(x_test_pca, y_test)
    
    # 记录结束时间
    end_tm = time.time()
    
    print(f"[n_components={n}]准确率为:{acc * 100:.4f}%,耗时{end_tm - start_tm:.2f}s\r\n")
    
    return acc
# 传递多个 n_components 参数以寻找合理的降维数和 SVM 模型(注意这里是“合理的”而不是“最优的”)
n_lst = np.linspace(0.70, 0.85, num=5)

acc_lst = []

for n in n_lst:
    acc = n_components_analysis(n, x_train, y_train, x_test, y_test)
    acc_lst.append(acc)
print("\r\nacc_lst:", acc_lst)
特征降维传递的参数为:0.7
开始使用SVC进行训练
[n_components=0.7]准确率为:97.6190%,耗时15.19s

特征降维传递的参数为:0.7374999999999999
开始使用SVC进行训练
[n_components=0.7374999999999999]准确率为:97.7976%,耗时16.66s

特征降维传递的参数为:0.7749999999999999
开始使用SVC进行训练
[n_components=0.7749999999999999]准确率为:97.8333%,耗时16.80s

特征降维传递的参数为:0.8125
开始使用SVC进行训练
[n_components=0.8125]准确率为:97.9881%,耗时19.69s

特征降维传递的参数为:0.85
开始使用SVC进行训练
[n_components=0.85]准确率为:98.0357%,耗时22.84s


acc_lst: [0.9761904761904762, 0.9779761904761904, 0.9783333333333334, 0.9798809523809524, 0.9803571428571428]

思考:我们可以看到,随着保留特征的增加,模型的准确率会逐渐上升,这是一个好现象吗?

我们很明显的看到,随着保留特征数的增加,训练时间也在增加。而且我们要记得,这个准确率是训练集准确率,而训练集准确率的提升并不意味着模型就在变好,因为可能会发生过拟合

这也就解释了为什么我们说要找一个“合理的” n_component,而不是找“最优的”的 n_component

干巴巴的数字总是枯燥且抽象的,所以我们对训练集准确率进行可视化展示:

# 训练集准确率可视化展示
plt.figure(dpi=300)
plt.plot(n_lst, acc_lst, 'r')
plt.scatter(n_lst, acc_lst)
plt.show()

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

经过图像展示,选择合理的 n_component。综合考虑,我们选择 n_component=0.80

8.3.4 确定最优模型

# 4. 确定最优模型
pca = PCA(n_components=0.80)

# 训练pca
pca.fit(x_train)
print("经过PCA降维后,数据的特征数为:", pca.n_components_)
经过PCA降维后,数据的特征数为: 43

我们可以看到,大量的特征被剔除,只剩下 43 个特征被保留。

接下来我们对数据应用 PCA 降维:

x_train_pca = pca.transform(x_train)
x_test_pca = pca.transform(x_test)

print("经过PCA降维后,训练集shape为:", x_train_pca.shape)
print("经过PCA降维后,测试集shape为:", x_test_pca.shape)
经过PCA降维后,训练集shape为: (33600, 43)
经过PCA降维后,测试集shape为: (8400, 43)

接下来我们可以训练选择出来的最优模型:

# 训练最优模型
svc = svm.SVC()

svc.fit(x_train_pca, y_train.ravel())

acc = svc.score(x_test_pca, y_test)
print(f"最优模型的准确率为:{acc*100:.4f}%")
最优模型的准确率为:97.9048%

9. SVM 总结

9.1 SVM 基本综述

SVM是一种二类分类模型。

SVM 也可以用于 多分类 和 回归 问题上!只不过二分类是 SVM 最擅长的问题。

它的基本模型是在特征空间中寻找 间隔最大化的分离超平面的线性分类器。

  1. 当训练样本线性可分时,通过 硬间隔最大化,学习一个线性分类器,即线性可分支持向量机
  2. 当训练数据近似线性可分时,引入松弛变量,通过软间隔最大化,学习一个线性分类器,即线性支持向量机
  3. 当训练数据线性不可分时,通过使用核技巧(引入核函数)及软间隔最大化,学习非线性支持向量机

9.2 SVM 的优缺点

9.2.1 SVM 的优点

  • 在高维空间中非常高效
  • 即使在数据维度比样本数量大的情况下仍然有效(一般而言,如果特征数比样本数要大,会出现维度灾难(curse of dimensionality)的问题)
  • 在决策函数(称为支持向量)中使用训练集的子集,因此它也是高效利用内存的
  • 通用性:不同的核函数与特定的决策函数是一一对应的

维度灾难是指当数据维度增加时,数据的分布会变得稀疏,这会导致模型的预测能力下降。为了解决这个问题,可以考虑使用降维技术来减少数据的维度。

需要注意的是,维度灾难并不仅仅发生在特征数比样本数大的情况下,它也可能发生在特征数较大但样本数充足的情况下。

9.2.2 SVM 的缺点

  • 如果特征数量比样本数量大得多,在选择核函数时要避免过拟合(一般我们会进行 PCA 降维)
  • 对缺失数据敏感
  • 对于核函数的高维映射解释力不强(举个例子,对于一个 3 维的数据,如果我们将其映射到 9 维,那么我们就很难直观的理解了)

10. 拓展\补充知识

10.1 范数

Q:什么是 ∣ ∣ w ∣ ∣ ||w|| ∣∣w∣∣
A ∣ ∣ w ∣ ∣ ||w|| ∣∣w∣∣ 就是求向量 w w w 的 2-范数。

范数是一种度量向量大小的函数,它满足一些特定的性质,如非负性、齐次性、三角不等式等。

常见的范数有 1-范数、2-范数和无穷范数。对于一个向量 w = ( w 1 , w 2 , . . . , w n ) w = (w_1, w_2, ..., w_n) w=(w1,w2,...,wn),它们分别定义为:

  • 1-范数: ∣ ∣ w ∣ ∣ 1 = ∑ i = 1 n ∣ w i ∣ ||w||_1 = \sum_{i=1}^n |w_i| ∣∣w1=i=1nwi
  • 2-范数: ∣ ∣ w ∣ ∣ 2 = ∑ i = 1 n w i 2 ||w||_2 = \sqrt{\sum_{i=1}^n w_i^2} ∣∣w2=i=1nwi2
  • 无穷范数: ∣ ∣ w ∣ ∣ ∞ = max ⁡ 1 ≤ i ≤ n ∣ w i ∣ ||w||_{\infty} = \max_{1 \leq i \leq n} |w_i| ∣∣w=max1inwi

当未指定具体的范数类型时, ∣ ∣ w ∣ ∣ ||w|| ∣∣w∣∣ 默认表示向量 w w w 的 2-范数。

10.1.1 向量的范数(Vector Norm)

  • 向量的 1-范数:各个元素的绝对值之和。
  • 向量的 2-范数:每个元素的平方和再开平方根。 ∣ ∣ X ∣ ∣ 2 = ( ∑ i = 1 n x i 2 ) = ∑ i = 1 n x i 2 ||X||_2 = \left( \sum_{i=1}^n x_i^2 \right) = \sqrt{\sum_{i=1}^n x_i^2} ∣∣X2=(i=1nxi2)=i=1nxi2
  • 向量的无穷范数:向量中所有元素绝对值的最大值。 ∣ ∣ X ∣ ∣ ∞ = max ⁡ 1 ≤ i ≤ n ∣ x i ∣ ||X||_\infty = \underset{1\le i \le n}{\max}{|x_i|} ∣∣X=1inmaxxi

例子:向量 X = [ 2 , 3 , − 5 , − 7 ] X=[2,3, -5, -7] X=[2,3,5,7],求向量的 1-范数,2-范数和无穷范数。

  • 向量的 1-范数:各个元素的绝对值之和: ∣ ∣ X ∣ ∣ 1 = 2 + 3 + 5 + 7 = 17 ||X||_1 = 2+3+5+7=17 ∣∣X1=2+3+5+7=17
  • 向量的 2-范数:每个元素的平方和再开平方根: ∣ ∣ X ∣ ∣ 2 = 2 2 + 3 2 + 5 2 + 7 2 = 9.3274 ||X||_2 = \sqrt{2^2 + 3^2 + 5^2 + 7^2} = 9.3274 ∣∣X2=22+32+52+72 =9.3274
  • 向量的无穷范数:向量中所有元素绝对值的最大值: ∣ ∣ X ∣ ∣ ∞ = 7 ||X||_\infty = 7 ∣∣X=7

10.1.2 矩阵的范数(Matrix Norm)

  • 矩阵的 1-范数(列模):矩阵的每一列上的元素绝对值先求和,再从中取个最大的(列和最大)。 ∣ ∣ A ∣ ∣ 1 = max ⁡ X ≠ 0 ∣ ∣ A X ∣ ∣ 1 ∣ ∣ X ∣ ∣ 1 = max ⁡ 1 ≤ j ≤ n ∑ i = 1 n ∣ a i j ∣ ||A||_1 = \underset{X \ne 0}{\max} \frac{||AX||_1}{||X||_1} = \underset{1 \le j \le n}{\max}\sum_{i=1}^n |a_{ij}| ∣∣A1=X=0max∣∣X1∣∣AX1=1jnmaxi=1naij
  • 矩阵的 2-范数(谱模):矩阵 A T A A^TA ATA 的最大特征值开平方根。 ∣ ∣ A ∣ ∣ 2 = max ⁡ X ≠ 0 ∣ ∣ A X ∣ ∣ 2 ∣ ∣ X ∣ ∣ 2 = λ max ⁡ ( A T A ) = max ⁡ 1 ≤ i ≤ n ∣ λ i ∣ ||A||_2 = \underset{X \ne 0}{\max}\frac{||AX||_2}{||X||_2} = \sqrt{\lambda_{\max}(A^TA)} = \sqrt{\underset{1 \le i \le n}{\max}|\lambda_i|} ∣∣A2=X=0max∣∣X2∣∣AX2=λmax(ATA) =1inmaxλi 其中 λ i \lambda_i λi A T A A^TA ATA 的特征值
  • 矩阵的无穷范数(行模):矩阵的每一行上的元素绝对值先求和,再从中取个最大的(行和最大)。 ∣ ∣ A ∣ ∣ ∞ = max ⁡ X ≠ 0 ∣ ∣ A X ∣ ∣ ∞ ∣ ∣ X ∣ ∣ ∞ = max ⁡ 1 ≤ i ≤ n ∑ j = 1 n ∣ a i j ∣ ||A||_\infty = \underset{X\ne 0}{\max}\frac{||AX||_{\infty}}{||X||_{\infty}} = \underset{1 \le i \le n}{\max}\sum_{j=1}^n |a_{ij}| ∣∣A=X=0max∣∣X∣∣AX=1inmaxj=1naij

例子:矩阵 A A A为:

A = [ 2 3 − 5 − 7 4 6 8 − 4 6 − 11 − 3 16 ] A = \begin{bmatrix} 2 & 3 & -5 & -7\\ 4 & 6 & 8 & -4\\ 6 & -11 & -3 & 16 \end{bmatrix} A= 24636115837416

求矩阵 A A A 的 1-范数,2-范数和无穷范数。

  • 矩阵的 1-范数:矩阵的每一列上的元素绝对值先求和,再从中取个最大的(列和最大): ∣ ∣ A ∣ ∣ 1 = max ⁡ ( 12 , 20 , 16 , 27 ) = 27 ||A||_1 = \max(12,20,16,27)=27 ∣∣A1=max(12,20,16,27)=27
  • 矩阵的 2-范数:矩阵 A T A A^TA ATA 的最大特征值开平方根:看下方代码
  • 矩阵的 无穷范数:矩阵的每一行上的元素绝对值先求和,再从中取个最大的(行和最大): ∣ ∣ A ∣ ∣ 2 = max ⁡ ( 17 , 22 , 36 ) = 36 ||A||_2 = \max(17,22,36)=36 ∣∣A2=max(17,22,36)=36

矩阵的 2-范数定义为矩阵的最大奇异值。计算奇异值需要进行奇异值分解,这一过程比较复杂,无法手动计算。可以使用计算软件(如 MATLAB 或 NumPy)来计算矩阵的奇异值。在 NumPy 中,您可以这样做:

import numpy as np

A = np.array([[2, 3, -5, -7], [4, 6, 8, -4], [6, -11, -3, 16]])
u, s, vh = np.linalg.svd(A)
norm_2 = s[0]
print("矩阵 A 的 2-范数为:", norm_2)
矩阵 A 的 2-范数为: 22.44432815341996

原文链接:向量与矩阵的范数(比较1-范数、2-范数、无穷范数、p-范数、L0范数 和 L1范数等)

10.2 朗格朗日乘子法

10.2.1 定义

拉格朗日乘子法(Lagrange multipliers)是一种寻找多元函数在一组约束下的极值的方法。通过引入拉格朗日乘子,可将有 d d d 个变量与 k k k 个约束条件的最优化问题转化为具有 d + k d + k d+k 个变量的无约束优化问题求解。

10.2.2 举例练习

以包含 1 个变量 1 个约束的简单优化问题为例。

min ⁡ x f ( x ) = x 2 + 4 x − 1 (1)s.t. x + 1 ≤ 0 (2)s.t. − x − 1 ≤ 0 \underset{x}{\min}f(x) = x^2 + 4x - 1 \\ \text{(1)s.t.} \quad x+1 \le 0\\ \text{(2)s.t.} \quad -x-1 \le 0\\ xminf(x)=x2+4x1(1)s.t.x+10(2)s.t.x10

它的图像如下:

[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)

如图所示,我们的目标函数是: f ( x ) = x 2 + 4 x − 1 f(x) = x^2 + 4x - 1 f(x)=x2+4x1,讨论两种约束条件 g ( x ) g(x) g(x)

  1. 在满足 x ≤ − 1 x \le -1 x1 约束条件 g ( x ) g(x) g(x) 下求目标函数的最小值
  2. 在满足 x ≥ − 1 x \ge -1 x1 约束条件 g ( x ) g(x) g(x) 下求目标函数的最小值

我们可以直观地从图中得到:

  • 对于约束(1),使目标值 f ( x ) f(x) f(x) 最小的最优解是 x = − 2 x=-2 x=2
  • 对于约束(2),使目标值 f ( x ) f(x) f(x) 最小的最优解是 x = − 1 x=-1 x=1

上面是通过看图得到的,下面我们用拉格朗日乘子来求解这个最优解。

当没有约束的时候,我们可以直接令目标函数的导数为0,求最优值(这是我们最常用的一种方式)。

可现在有约束,那怎么一边考虑约束一边求目标函数最优值呢?

最直观的办法是把约束放进目标函数里。由于本例中只有一个约束,所以引入一个朗格朗日乘子 λ \lambda λ,构造一个新的函数,即拉格朗日函数 h ( x ) h(x) h(x),如下所示:

h ( x ) = f ( x ) + λ g ( x ) h(x)= f(x) + \lambda g(x) h(x)=f(x)+λg(x)

该拉格朗日函数 h ( x ) h(x) h(x) 最优解可能在 g ( x ) < 0 g(x)<0 g(x)<0 区域中,或者在边界 g ( x ) = 0 g(x)=0 g(x)=0 上,下面具体分析这两种情况:

  • g ( x ) < 0 g(x)<0 g(x)<0 时,也就是最优解在 g ( x ) < 0 g(x)<0 g(x)<0 区域中,对应约束(1) x ≤ − 1 x \le -1 x1 的情况。此时约束对求目标函数最小值不起作用,等价于 λ = 0 \lambda=0 λ=0,直接通过条件 ▽ f ( x ∗ ) = 0 \triangledown f(x^*) = 0 f(x)=0,得到拉格朗日函数 h ( x ) h(x) h(x) 最优解,为 x = − 2 x=-2 x=2
  • g ( x ) = 0 g(x)=0 g(x)=0 时,也就是最优解在边界 g ( x ) = 0 g(x)=0 g(x)=0 上,对应约束(2) x ≥ − 1 x \ge -1 x1 的情况。此时不等式约束转换为等式约束,也就是在 λ > 0 \lambda > 0 λ>0、约束起作用的情况下,通过求 ▽ f ( x ∗ ) + λ ▽ g ( x ∗ ) = 0 \triangledown f(x^*) + \lambda \triangledown g(x^*)=0 f(x)+λg(x)=0,得到拉格朗日函数 h ( x ) h(x) h(x) 的最优解,为 x = − 1 x=-1 x=1

其中:

  • ▽ \triangledown 是一个数学符号,它表示梯度(gradient)运算。梯度是一个向量,它指向函数在某一点处的最大增长方向。对于一个多元函数 f ( x 1 , x 2 , . . . , x n ) f(x_1, x_2, ..., x_n) f(x1,x2,...,xn),它的梯度定义为: ▽ f = ( ∂ f ∂ x 1 , ∂ f ∂ x 2 , . . . , ∂ f ∂ x n ) \triangledown f = \left( \frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, ..., \frac{\partial f}{\partial x_n} \right) f=(x1f,x2f,...,xnf)其中, ∂ f ∂ x i \frac{\partial f}{\partial x_i} xif 表示函数 f f f 对变量 x i x_i xi 的偏导数。
  • 在优化问题中, x ∗ x^* x 通常表示目标函数的最优解。上标 ∗ * 表示这是一个最优值
    • 例如,在无约束优化问题中,我们要求解 min ⁡ x f ( x ) \min_x f(x) minxf(x)。如果 x ∗ x^* x 是目标函数的最小值点,那么我们可以写成 f ( x ∗ ) = min ⁡ x f ( x ) f(x^*) = \min_x f(x) f(x)=minxf(x)
    • 在上述中的表达式 ▽ f ( x ∗ ) = 0 \triangledown f(x^*) = 0 f(x)=0 中, x ∗ x^* x 表示目标函数的极值点。对于无约束优化问题,目标函数的极值点满足一阶必要条件,即梯度为零。

所以整合这两种情况,必须满足 λ g ( x ) = 0 \lambda g(x) = 0 λg(x)=0。因此约束 g ( x ) g(x) g(x) 最小化 f ( x ) f(x) f(x) 的优化问题,可通过引入拉格朗日因子转化为在如下约束,即问题变为最小化拉格朗日函数 h ( x ) h(x) h(x)

{ g ( x ) ≤ 0 λ ≥ 0 λ g ( x ) ≥ 0 \begin{cases} g(x) \le 0\\ \lambda \ge 0\\ \lambda g(x) \ge 0 \end{cases} g(x)0λ0λg(x)0

上述约束条件称为 KKT 条件。该 KKT 条件可扩展到多个等式约束和不等式约束的优化问题。


简单求解

我们可以使用拉格朗日乘子法来求解这个带有两个不等式约束的优化问题。首先,我们构造拉格朗日函数:

L ( x , λ 1 , λ 2 ) = f ( x ) + λ 1 ( x + 1 ) + λ 2 ( − x − 1 ) L(x, \lambda_1, \lambda_2) = f(x) + \lambda_1 (x + 1) + \lambda_2 (-x - 1) L(x,λ1,λ2)=f(x)+λ1(x+1)+λ2(x1)

其中, λ 1 \lambda_1 λ1 λ 2 \lambda_2 λ2 是拉格朗日乘子。

然后,我们求解拉格朗日函数的极值点。对拉格朗日函数求偏导,得到:

∂ L ∂ x = 2 x + 4 + λ 1 − λ 2 = 0 \frac{\partial L}{\partial x} = 2x + 4 + \lambda_1 - \lambda_2 = 0 xL=2x+4+λ1λ2=0

由于 x = − 1 x = -1 x=1,代入上式得到 λ 1 − λ 2 = 2 \lambda_1 - \lambda_2 = 2 λ1λ2=2

根据 KKT 条件,我们有:

{ x + 1 ≤ 0 − x − 1 ≤ 0 λ 1 ≥ 0 λ 2 ≥ 0 λ 1 ( x + 1 ) = 0 λ 2 ( − x − 1 ) = 0 \begin{cases} x + 1 \le 0 \\ -x - 1 \le 0 \\ \lambda_1 \ge 0 \\ \lambda_2 \ge 0 \\ \lambda_1 (x + 1) = 0 \\ \lambda_2 (-x - 1) = 0 \end{cases} x+10x10λ10λ20λ1(x+1)=0λ2(x1)=0

由于 x = − 1 x = -1 x=1,所以 λ 1 ( x + 1 ) = 0 \lambda_1 (x + 1) = 0 λ1(x+1)=0 λ 2 ( − x − 1 ) = 0 \lambda_2 (-x - 1) = 0 λ2(x1)=0 都成立。因此,我们只需考虑 λ 1 \lambda_1 λ1 λ 2 \lambda_2 λ2 的非负性。

由于 λ 1 − λ 2 = 2 \lambda_1 - \lambda_2 = 2 λ1λ2=2,所以 λ 1 = λ 2 + 2 \lambda_1 = \lambda_2 + 2 λ1=λ2+2。又因为 λ 1 \lambda_1 λ1 λ 2 \lambda_2 λ2 都非负,所以 λ 2 ≥ − 2 \lambda_2 \ge -2 λ22

综上所述,最优解为 x ∗ = − 1 x^* = -1 x=1,此时目标函数的最小值为 f ( x ∗ ) = ( − 1 ) 2 + 4 ( − 1 ) − 1 = − 6 f(x^*) = (-1)^2 + 4(-1) - 1 = -6 f(x)=(1)2+4(1)1=6


KKT 的条件补充说明

KKT 条件(Karush-Kuhn-Tucker 条件)是一组用于求解带约束优化问题的必要条件。它是拉格朗日乘子法的推广,可以用来求解带有不等式约束和等式约束的优化问题。

对于一个带有不等式约束和等式约束的优化问题,其形式为:

min ⁡ x f ( x ) s.t. g i ( x ) ≤ 0 , i = 1 , 2 , . . . , m h j ( x ) = 0 , j = 1 , 2 , . . . , n \begin{aligned} & \min_x f(x) \\ & \text{s.t.} \quad g_i(x) \le 0, \quad i = 1, 2, ..., m \\ & \quad \quad h_j(x) = 0, \quad j = 1, 2, ..., n \end{aligned} xminf(x)s.t.gi(x)0,i=1,2,...,mhj(x)=0,j=1,2,...,n

其中, f ( x ) f(x) f(x) 是目标函数, g i ( x ) g_i(x) gi(x) h j ( x ) h_j(x) hj(x) 分别表示不等式约束和等式约束。

对于这个问题,我们可以构造拉格朗日函数:

L ( x , λ , μ ) = f ( x ) + ∑ i = 1 m λ i g i ( x ) + ∑ j = 1 n μ j h j ( x ) L(x, \lambda, \mu) = f(x) + \sum_{i=1}^m \lambda_i g_i(x) + \sum_{j=1}^n \mu_j h_j(x) L(x,λ,μ)=f(x)+i=1mλigi(x)+j=1nμjhj(x)

其中, λ i \lambda_i λi μ j \mu_j μj 分别表示不等式约束和等式约束对应的拉格朗日乘子。

根据 KKT 条件,最优解 x ∗ x^* x 必须满足以下条件:

{ g i ( x ∗ ) ≤ 0 , i = 1 , 2 , . . . , m h j ( x ∗ ) = 0 , j = 1 , 2 , . . . , n λ i ≥ 0 , i = 1 , 2 , . . . , m λ i g i ( x ∗ ) = 0 , i = 1 , 2 , . . . , m ▽ x L ( x ∗ , λ ∗ , μ ∗ ) = 0 \begin{cases} g_i(x^*) \le 0, \quad i = 1, 2, ..., m \\ h_j(x^*) = 0, \quad j = 1, 2, ..., n \\ \lambda_i \ge 0, \quad i = 1, 2, ..., m \\ \lambda_i g_i(x^*) = 0, \quad i = 1, 2, ..., m \\ \triangledown_x L(x^*, \lambda^*, \mu^*) = 0 \end{cases} gi(x)0,i=1,2,...,mhj(x)=0,j=1,2,...,nλi0,i=1,2,...,mλigi(x)=0,i=1,2,...,mxL(x,λ,μ)=0

其中, ▽ x L ( x ∗ , λ ∗ , μ ∗ ) \triangledown_x L(x^*, \lambda^*, \mu^*) xL(x,λ,μ) 表示拉格朗日函数关于 x x x 的梯度。

在实际应用中,我们可以通过求解上述 KKT 条件来得到最优解。具体方法取决于问题的具体形式,通常需要结合数学推导和计算软件来求解。文章来源地址https://www.toymoban.com/news/detail-487779.html

到了这里,关于[学习笔记] [机器学习] 10. 支持向量机 SVM(SVM 算法原理、SVM API介绍、SVM 损失函数、SVM 回归、手写数字识别)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 10- SVM支持向量机 (SVC) (算法)

    支持向量机 (support vector machines,SVM) 是一种 二分类算法 ,它的目的是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化,如果对应的样本特征少,一个普通的 SVM 就是一条线将样本分隔开,但是要求线到两个类别最近样本点的距离要最大。 支持向量机模型: 网格

    2023年04月20日
    浏览(42)
  • 机器学习——支持向量机SVM

    支持向量机(SVM)是一种二类分类模型,其基本模型是在特征空间上找到最佳的分离超平面使得训练集上正负样本间隔最大,间隔最大使它有别于感知机,支持向量机也可通过核技巧使它成为非线性分类器。支持向量机的学习策略是间隔最大化,可将其转化为一个求解凸二次

    2024年01月17日
    浏览(57)
  • 机器学习-支持向量机SVM

    在本练习中,我们将使用支持向量机(SVM)来构建垃圾邮件分类器。 我们将从一些简单的2D数据集开始使用SVM来查看它们的工作原理。 然后,我们将对一组原始电子邮件进行一些预处理工作,并使用SVM在处理的电子邮件上构建分类器,以确定它们是否为垃圾邮件。 我们要做

    2024年02月12日
    浏览(54)
  • SVM(支持向量机)-机器学习

    支持向量机(Support Vector Machine,SVM) 是一种用于分类和回归分析的监督学习算法 。它属于机器学习中的一类强大而灵活的模型,广泛应用于模式识别、图像分类、自然语言处理等领域。 基本原理: SVM的基本原理是通过找到能够有效分隔不同类别的超平面来进行分类。在二维

    2024年02月03日
    浏览(52)
  • 【机器学习】SVM支持向量机模型

     本站原创文章,转载请说明来自 《老饼讲解-机器学习》 ml.bbbdata.com 目录 一. SVM的目标和思想    1.1 SVM硬间隔模型的原始目的 1.2 SVM的直接目标 1.3 什么是支持向量  二. SVM的支持平面的表示方式 2.1 支持面表示方式的初步思路 2.2 初步思路的缺陷与改进 2.3 支持面的最终表示

    2023年04月23日
    浏览(204)
  • 机器学习(六)支持向量机(SVM)

    目录 1.间隔与支持向量 1.1线性可分 1.2支持向量 1.3 最大间隔超平面 2.对偶问题 2.1拉格朗日乘子法 2.2 SMO算法 2.3SMO算法代码实现 3.核函数 4. SVM实例(手写体数字识别) 5.实验总结 支持向量机(SVM) 是有监督学习中最有影响力的机器学习算法之一,一般用于解决二分类问题(

    2024年02月09日
    浏览(56)
  • 【机器学习】支持向量机SVM入门

    相较于之前学习的线性回归和神经网络,支持向量机(Supprot Vector Machine,简称SVM)在拟合复杂的非线性方程的时候拥有更出色的能力,该算法也是十分经典的算法之一。接下来我们需要学习这种算法 首先我们回顾逻辑回归中的经典假设函数,如下图: 对于任意一个实例 (

    2024年02月15日
    浏览(56)
  • 机器学习:基于支持向量机(SVM)进行人脸识别预测

    作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 专栏案例:

    2024年01月23日
    浏览(49)
  • 第29步 机器学习分类实战:支持向量机(SVM)建模

    支持向量机(SVM)建模。 先复习一下参数(传送门),需要调整的参数有: ① kernel:{‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’},默认为’rbf’。使用的核函数,必须是“linear”,“poly”,“rbf”,“sigmoid”,“precomputed”或者“callable”中的一个。 ② c:浮点

    2024年02月02日
    浏览(65)
  • 人工智能_机器学习065_SVM支持向量机KKT条件_深度理解KKT条件下的损失函数求解过程_公式详细推导_---人工智能工作笔记0105

    之前我们已经说了KKT条件,其实就是用来解决 如何实现对,不等式条件下的,目标函数的求解问题,之前我们说的拉格朗日乘数法,是用来对 等式条件下的目标函数进行求解. KKT条件是这样做的,添加了一个阿尔法平方对吧,这个阿尔法平方肯定是大于0的,那么 可以结合下面的文章去

    2024年02月04日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包