机器学习实战教程(十一):支持向量机SVM

news2024/11/14 3:47:11

什么是SVM?

VM的英文全称是Support Vector Machines,我们叫它支持向量机。支持向量机是我们用于分类的一种算法。让我们以一个小故事的形式,开启我们的SVM之旅吧。

在很久以前的情人节,一位大侠要去救他的爱人,但天空中的魔鬼和他玩了一个游戏。

魔鬼在桌子上似乎有规律放了两种颜色的球,说:“你用一根棍分开它们?要求:尽量在放更多球之后,仍然适用。”
在这里插入图片描述
于是大侠这样放,干的不错?
在这里插入图片描述
然后魔鬼,又在桌上放了更多的球,似乎有一个球站错了阵营。显然,大侠需要对棍做出调整。
在这里插入图片描述
SVM就是试图把棍放在最佳位置,好让在棍的两边有尽可能大的间隙。这个间隙就是球到棍的距离。
在这里插入图片描述
现在好了,即使魔鬼放了更多的球,棍仍然是一个好的分界线。
在这里插入图片描述
现在,大侠没有棍可以很好帮他分开两种球了,现在怎么办呢?当然像所有武侠片中一样大侠桌子一拍,球飞到空中。然后,凭借大侠的轻功,大侠抓起一张纸,插到了两种球的中间。
在这里插入图片描述
现在,从空中的魔鬼的角度看这些球,这些球看起来像是被一条曲线分开了。
在这里插入图片描述
再之后,无聊的大人们,把这些球叫做data,把棍子叫做classifier, 找到最大间隙的trick叫做optimization,拍桌子叫做kernelling, 那张纸叫做hyperplane。

概述一下:

当一个分类问题,数据是线性可分的,也就是用一根棍就可以将两种小球分开的时候,我们只要将棍的位置放在让小球距离棍的距离最大化的位置即可,寻找这个最大间隔的过程,就叫做最优化。但是,现实往往是很残酷的,一般的数据是线性不可分的,也就是找不到一个棍将两种小球很好的分类。这个时候,我们就需要像大侠一样,将小球拍起,用一张纸代替小棍将小球进行分类。想要让数据飞起,我们需要的东西就是核函数(kernel),用于切分小球的纸,就是超平面

数学建模

支持向量机(Support Vector Machine, SVM)是一类按监督学习(supervised learning)方式对数据进行广义线性分类,其决策边界是对学习样本求解的最大边距超平面(maximum-margin hyperplane)。SVM可以通过核函数进行非线性分类,是常见的核学习(kernel learning)方法之一。

支持向量机(support vector machines)是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化,最终转化为一个凸二次规划问题来求解。它既能解决线性可分又能解决线性不可能,既能解决分类问题又能完成回归问题。

间隔最大化

当训练样本线性可分时使用硬间隔最大化(Hard Margin SVM)或者近似线性可分时使用软件最大化(Soft Margin SVM)。当训练样本线性不可分时使用核函数和软间隔最大化。
在这里插入图片描述
在实际问题中往往都存在着决策边界不唯一的情况,这就是不适定问题。给定训练样本集
D = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x m , y m ) } , y i ∈ { − 1 , 1 } D = \{(x_{1}, y_{1}), (x_{2}, y_{2}), \dots , (x_{m}, y_{m})\}, y_{i} \in \{-1, 1\} D={(x1,y1),(x2,y2),,(xm,ym)},yi{1,1} 分类算法的基本思想就是基于训练集在样本空间中找到一个划分超平面,但是能将训练样本分开的划分超平面可能有很多,所以,应该努力地去找哪一个?
在这里插入图片描述
而svm找到的这条直线希望距离最近的红色的点和蓝色的点,距离决策边界尽可能的远,这样就能保证模型的泛化能力。svm尝试寻找一个最优的决策边界,距离两个类别最近的样本最远,图中3个点到决策边界距离相同。这三个点就叫做支持向量(support vector)。而平行于决策边界的两条直线之间的距离就是margin,svm就是要最大化 margin,这样就把这个问题转化称为最优化问题。

最优化问题

分类间隔方程

svm最大化margin,margin=2d,,就对应于最大化d,也就是点到直线的距离最大。回忆解析几何,在二维空间中点 ( x , y ) (x,y) (x,y)到直线 A x + B y + C = 0 Ax+By+C=0 Ax+By+C=0的距离公式 : ∣ A x + B y + C ∣ A 2 + B 2 \frac{\mid Ax+By+C \mid} {\sqrt{A^2+B^2}} A2+B2 Ax+By+C
将其拓展到n维 θ T ⋅ x b = 0 \theta^T \cdot x_{b}=0 θTxb=0
其中 θ \theta θ包含截距和系数, x b x_b xb就是在 x x x 样本中加入一行常数1,这就跟之前的线性回归中是一样的。

如果将截距提出来就是 w T x + b = 0 w^Tx + b = 0 wTx+b=0
其中的w就是对样本中的每一个数据赋予了一个权值。这就是直线方程的两种不同表示方式。那么,由此可以得到新的点到直线距离方程:
∣ w T x + b ∣ ∥ w ∥ \frac{\mid w^Tx + b \mid}{\parallel w \parallel} wwTx+b,其中 ∥ w ∥ = w 1 2 + w 2 2 + ⋯ + w n 2 \parallel w \parallel = \sqrt {w_{1}^2 + w_{2}^2 + \dots + w_{n}^2} w∥=w12+w22++wn2

约束条件

看起来,我们已经顺利获得了目标函数的数学形式。但是为了求解w的最大值。我们不得不面对如下问题:

  1. 我们如何判断超平面是否将样本点正确分类?
  2. 我们知道要求距离d的最大值,我们首先需要找到支持向量上的点,怎么在众多的点中选出支持向量上的点呢?
    上述我们需要面对的问题就是约束条件,也就是说我们优化的变量d的取值范围受到了限制和约束。事实上约束条件一直是最优化问题里最让人头疼的东西。但既然我们已经知道了这些约束条件确实存在,就不得不用数学语言对他们在这里插入图片描述
    进行描述。但SVM算法通过一些巧妙的小技巧,将这些约束条件融合到一个不等式里面。

这个二维平面上有两种点,我们分别对它们进行标记:

红颜色的圆点标记为1,我们人为规定其为正样本;
蓝颜色的五角星标记为-1,我们人为规定其为负样本。
对每个样本点xi加上一个类别标签yi:
在这里插入图片描述

技巧
中间那根直线就是决策边界 w T x + b = 0 w^Tx+b=0 wTx+b=0 ,而上下两根直线意味着距离一定大于 d ,从而
{ w T x ( i ) + b ∥ w ∥ ≥ d ∀ y ( i ) = 1 w T x ( i ) + b ∥ w ∥ ≤ − d ∀ y ( i ) = − 1 \begin {cases} \frac{w^Tx^{(i)} + b} {\parallel w \parallel} \geq d \qquad \forall y^{(i)} = 1 \\ \frac{w^Tx^{(i)} + b}{\parallel w \parallel} \leq -d \qquad \forall y^{(i)} = -1 \\ \end {cases} {wwTx(i)+bdy(i)=1wwTx(i)+bdy(i)=1
此时,假设两类样本分别为1和-1。然后将上述式子的左右两侧同时除以d,得到
{ w T x ( i ) + b ∥ w ∥ d ≥ 1 ∀ y ( i ) = 1 w T x ( i ) + b ∥ w ∥ d ≤ − 1 ∀ y ( i ) = − 1 \begin {cases} \frac{w^Tx^{(i)} + b} {\parallel w \parallel d} \geq 1 \qquad \forall y^{(i)} = 1 \\ \frac{w^Tx^{(i)} + b}{\parallel w \parallel d} \leq -1 \qquad \forall y^{(i)} = -1 \\ \end {cases} {wdwTx(i)+b1y(i)=1wdwTx(i)+b1y(i)=1

其中 |w|和 d都是一个标量(不影响求极限值),此时消去分母,得到
{ w T x ( i ) + b ≥ 1 ∀ y ( i ) = 1 w T x ( i ) + b ≤ − 1 ∀ y ( i ) = − 1 \begin {cases} {w^Tx^{(i)} + b} \geq 1 \qquad \forall y^{(i)} = 1 \\ {w^Tx^{(i)} + b} \leq -1 \qquad \forall y^{(i)} = -1 \\ \end {cases} {wTx(i)+b1y(i)=1wTx(i)+b1y(i)=1
此时,就得到了两个式子,接下来通过一个小技巧将两个式子合并成一个。
y i ( w T x ( i ) + b ) ≥ 1 \boxed {y_{i} (w^Tx^{(i)} + b) \geq 1} yi(wTx(i)+b)1

最大化目标函数

现在整合一下思路,我们已经得到我们的目标函数:
m a x ∣ w T x + b ∣ ∥ w ∥ max \frac{\mid w^Tx +b \mid}{\parallel w \parallel} maxwwTx+b
我们的优化目标是是d最大化。我们已经说过,我们是用支持向量上的样本点求解d的最大化的问题的。那么支持向量上的样本点有什么特点呢?
∣ w T x + b ∣ = 1 |w^Tx+b|=1 wTx+b=1
所以转化为最大化 m a x 1 ∥ w ∥ max \frac{1}{\parallel w \parallel} maxw1 也即是最小化 m i n ∥ w ∥ min\parallel w \parallel minw
但是往往为了求导方便,通常都是最小化 m i n 1 2 ∥ w ∥ 2 \boxed{min\frac{1}{2} \parallel w \parallel^2} min21w2
,但是这是一个有约束条件的最优化问题,就是要满足 s . t . y i ( w T x ( i ) + b ) ≥ 1 , i = 1 , 2 , … , m s.t. \quad y_{i} (w^Tx^{(i)} + b) \geq 1, \quad i=1,2,\dots,m s.t.yi(wTx(i)+b)1,i=1,2,,m
这里m是样本点的总个数,缩写s.t.表示"Subject to",是"服从某某条件"的意思。上述公式描述的是一个典型的不等式约束条件下的二次型函数优化问题,同时也是支持向量机的基本数学模型。
解决有约束问题的最优化问题需要使用拉格朗日乘子法得到对偶问题。则该问题函数:
L ( w , b , α ) = 1 2 ∥ w ∥ 2 + ∑ i = 1 m α i ( 1 − y i ( w T x i + b ) ) \boxed{L(w, b, \alpha) = \frac{1}{2} \parallel w \parallel^2 + \sum_{i=1}^m \alpha_{i} (1-y_{i}(w^Tx_{i}+b))} L(w,b,α)=21w2+i=1mαi(1yi(wTxi+b))

其中 α i \alpha_i αi 就是拉格朗日乘子。这就是Hard Margin SVM。

Soft Margin和SVM正则化

如果在实际应用过程中有一个蓝色的点出现在红色的点附近,即两类相对较为接近,但整体跟蓝色的点差异明显,可以看做是一个特殊点或者错误的奇点,此时就会误导,导致最终的hard margin分类边界是直线1,此时模型的泛化能力就值得怀疑。正常来说应该像直线2一样忽略那个极度特殊的蓝点,保证大多数的数据到直线的距离最远,可能这才是最好的分类边界,也就是泛化能力更高。这也能间接地说明如果模型的准确率过高可能会导致模型的过拟合。

在这里插入图片描述
还有一种更一般的例子,那就是如果有一个蓝色的点混进了红色的点当中,这就导致数据集根本就是线性不可分的情况,根本找不出一条直线能够将这两类分开,在这种情况下Hard margin就不再是泛化能力强不强的问题,而是根本找不出一条直线将其分开。
在这里插入图片描述
因此不管才以上两种情况的哪个角度出发,都应该考虑给予svm模型部分容错能力。由此引出Soft Margin SVM。
m i n 1 2 ∥ w ∥ 2 , s . t . y i ( w T x ( i ) + b ) ≥ 1 − ζ i , ζ i > 0 , i = 1 , 2 , … , m min\frac{1}{2} \parallel w \parallel^2, \quad s.t. \quad y_{i} (w^Tx^{(i)} + b) \geq 1 - \zeta_{i}, \\ \quad \zeta_{i} >0, \quad i=1,2,\dots,m min21w2s.t.yi(wTx(i)+b)1ζi,ζi>0,i=1,2,,m
相比于Hard Margin SVM,就相当于把条件放得更加宽松一些,直观从图上理解,就是相当于把上面这根直线放宽到虚线。此外,更加重要的一点是 ζ i \zeta_{i} ζi并不是一个固定值,而是相对应于每个样本 x i x_i xi都有一个 ζ i \zeta_{i} ζi,但是对于这个 ζ i \zeta_{i} ζi也需要一定限制,并不是说可以无限放宽这个条件。也就是这个容错空间不能太大,因此需要对其加以限制。
在这里插入图片描述
L1正则
m i n ( 1 2 ∥ w ∥ 2 + C ∑ i = 1 m ζ i ) , s . t . y i ( w T x ( i ) + b ) ≥ 1 − ζ i , ζ i ≥ 0 , i = 1 , 2 , … , m \boxed { min(\frac{1}{2} \parallel w \parallel^2 +C \sum_{i=1}^m \zeta_{i}), \quad s.t. \quad y_{i} (w^Tx^{(i)} + b) \geq 1 - \zeta_{i}, \\ \qquad \qquad \qquad \qquad \zeta_{i} \geq 0, \quad i=1,2,\dots,m } min(21w2+Ci=1mζi)s.t.yi(wTx(i)+b)1ζi,ζi0,i=1,2,,m
引入一个新的超参数C去权衡容错能力和目标函数,其实这也可以理解为我们为其加入了L1正则项,避免模型向一个极端方向发展,使得对于极端的数据集不那么敏感,对于未知的数据有更好的泛化能力。这个所谓的L1正则跟之前的L1正则不同的是没有绝对值,只是因为已经限制了 ζ i ≥ 0 \zeta_{i} \geq 0 ζi0,所以不加绝对值也就合理了。C越大越趋近于一个Hard Margin SVM,C越小,就意味着有更大的容错空间。svm的正则与线性回归的正则不同的是在于C的位置不同。具体原因后续理解更深刻之后再更新。
那么有L1正则,相对应就有L2正则,如下。
m i n ( 1 2 ∥ w ∥ 2 + C ∑ i = 1 m ζ i 2 ) , s . t . y i ( w T x ( i ) + b ) ≥ 1 − ζ i , ζ i > 0 , i = 1 , 2 , … , m \boxed { min(\frac{1}{2} \parallel w \parallel^2 +C \sum_{i=1}^m \zeta_{i}^2), \quad s.t. \quad y_{i} (w^Tx^{(i)} + b) \geq 1 - \zeta_{i}, \\ \qquad \qquad \qquad \qquad \zeta_{i} >0, \quad i=1,2,\dots,m } min(21w2+Ci=1mζi2)s.t.yi(wTx(i)+b)1ζi,ζi>0,i=1,2,,m

Sklearn的svm

在实际使用SVM的时候和KNN一样需要对数据进行标准化处理,因为这两者都涉及距离。因为当数据尺度相差过大的话,比如下图横轴0-1,纵轴0-10000。所以先进行标准化是必要的。

第一步,准备一个简单二分类数据集:

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
"""
load_iris是一个经典的机器学习数据集,它包含了150个样本
这个数据集中的四个特征分别是花萼长度(sepal length)、花萼宽度(sepal width)、花瓣长度(petal length)和花瓣宽度(petal width),
它们都是以厘米(cm)为单位测量的。目标变量是鸢尾花的种类,
有三种不同的种类:Setosa、Versicolour和Virginica。
它们的中文名分别是山鸢尾、杂色鸢尾和维吉尼亚鸢尾。
"""
iris = datasets.load_iris()

x = iris.data
y = iris.target
# 只做一个简单的二分类,获取分类是山鸢尾、杂色鸢尾的数据,同时取2维的特征就行了
x = x[y<2, :2]
y = y[y<2]
#分别绘制出分类是0和1的点,不同的scatter颜色不一样
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()

在这里插入图片描述
实现svm,先使用一个比较大的C。


# 标准化数据
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
#数据归一化
standardscaler = StandardScaler()
standardscaler.fit(x)
x_standard = standardscaler.transform(x)
svc = LinearSVC(C=1e9)
svc.fit(x_standard, y)

def plot_decision_boundary(model, axis):
    x0, x1 = np.meshgrid(np.linspace(axis[0], axis[1], int((axis[1] - axis[0])*100)).reshape(1, -1),
                         np.linspace(axis[2], axis[3], int((axis[3] - axis[2])*100)).reshape(1, -1),)
    x_new = np.c_[x0.ravel(), x1.ravel()]
    y_predict = model.predict(x_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#EF9A9A', '#FFF59D', '#90CAF9'])

    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)
    w = model.coef_[0]
    b = model.intercept_[0]
    # w0*x0 + w1*x1 + b = 0
    # x1 = -w0/w1 * x0 - b/w1
    plot_x = np.linspace(axis[0], axis[1], 200)
    up_y = -w[0]/w[1] * plot_x - b/w[1] + 1/w[1]
    down_y = -w[0]/w[1] * plot_x - b/w[1] - 1/w[1]
    
    up_index = (up_y >= axis[2]) & (up_y <= axis[3])
    down_index = (down_y >= axis[2]) & (down_y <= axis[3])
    
    plt.plot(plot_x[up_index], up_y[up_index], color='black')
    plt.plot(plot_x[down_index], down_y[down_index], color='black')
plot_decision_boundary(svc, axis=[-3, 3, -3, 3])
plt.scatter(x_standard[y==0, 0], x_standard[y==0, 1], color='red')
plt.scatter(x_standard[y==1, 0], x_standard[y==1, 1], color='blue')
plt.show()

在这里插入图片描述
使用一个比较小的C,对比C取不同值的效果。

svc2 = LinearSVC(C=0.01)
svc2.fit(x_standard, y)

plot_decision_boundary(svc2, axis=[-3, 3, -3, 3])
plt.scatter(x_standard[y==0, 0], x_standard[y==0, 1], color='red')
plt.scatter(x_standard[y==1, 0], x_standard[y==1, 1], color='blue')
plt.show()

在这里插入图片描述
对比两幅图可以发现,当C较小时,误将一个红色的点分到蓝色当中,这也再次验证了当C越小,就意味着有更大的容错空间。

SVM中使用多项式特征

前面一直都在讲的是线性的svm,对于svm来说也可以解决非线性问题,类比线性回归到非线性回归的思想,首先使用多项式特征。

首先生成数据集:

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

x, y = datasets.make_moons()
x.shape
# (100, 2)
y.shape
# (100,)
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()

在这里插入图片描述
接下来给数据添加一些随机噪声:

x, y = datasets.make_moons(noise=0.15, random_state=666)
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()

在这里插入图片描述
使用多项式,归一,线性svm

from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.svm import LinearSVC
from sklearn.pipeline import Pipeline

def PolynomiaSVC(degree, C=1.0):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('linear_svc', LinearSVC(C=C))
    ])

poly_svc = PolynomiaSVC(degree=3)
poly_svc.fit(x, y)

def plot_decision_boundary(model, axis):
    x0, x1 = np.meshgrid(np.linspace(axis[0], axis[1], int((axis[1] - axis[0])*100)).reshape(1, -1),
                         np.linspace(axis[2], axis[3], int((axis[3] - axis[2])*100)).reshape(1, -1),)
    x_new = np.c_[x0.ravel(), x1.ravel()]
    y_predict = model.predict(x_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#EF9A9A', '#FFF59D', '#90CAF9'])

    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

plot_decision_boundary(poly_svc, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(x1[y1==0, 0], x1[y1==0, 1])
plt.scatter(x1[y1==1, 0], x1[y1==1, 1])
plt.show()

在这里插入图片描述
除了使用这种增加多项式特征之后再给入线性svc中之外,还有一种方法可以实现类似的功能。


from sklearn.svm import SVC

# 这种方法训练的过程并不完全是先将数据进行标准化,再使用linearSVC这么一个过程
# SVC中默认的C=0
def PolynomiaKernelSVC(degree, C=1.0):
    return Pipeline([
        ('std_scale', StandardScaler()),
        ('kernel_svc', SVC(kernel='poly', degree=degree, C=C))
    ])

poly_kernel_svc = PolynomiaKernelSVC(degree=3)
poly_kernel_svc.fit(x1, y1)
# Pipeline(memory=None,
#     steps=[('std_scale', StandardScaler(copy=True, with_mean=True, with_std=True)),
#  ('kernel_svc', SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
#   decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
#   kernel='poly', max_iter=-1, probability=False, random_state=None,
#   shrinking=True, tol=0.001, verbose=False))])

plot_decision_boundary(poly_kernel_svc, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(x1[y1==0, 0], x1[y1==0, 1])
plt.scatter(x1[y1==1, 0], x1[y1==1, 1])
plt.show()

在这里插入图片描述
这种方法就是svm中kernel函数。接下来具体说明核函数。

什么是核函数

在现实任务中,原始的样本空间也许并不存在一个能正确划分两类的超平面,对于这样一个问题,可将样本从原始空间映射到一个更高维的特征空间,使得样本在这个特征空间内线性可分。因此核函数的作用就是使得原本线性不可分的数据变得线性可分。下面是一个使用多项式核映射的过程。
在这里插入图片描述
转换为以下函数后,数据变的线性可分。
在这里插入图片描述
常用 核函数:
1、线性核: k ( x i , x j ) = x i T x j + c k(x_{i}, x_{j}) = x_{i}^T x_{j} + c k(xi,xj)=xiTxj+c
2、多项式核: k ( x i , x j ) = ( x i T x j + c ) d k(x_{i}, x_{j}) = (x_{i}^T x_{j} + c)^d k(xi,xj)=(xiTxj+c)d,当d=1时退化为线性核。
3、高斯核RBF: k ( x i , x j ) = e x p ( − ∥ x i − x j ∥ 2 2 σ 2 ) , σ > 0 k(x_{i}, x_{j}) = exp(-\frac{\parallel x_{i} - x_{j} \parallel ^2}{2\sigma ^2}), \sigma >0 k(xi,xj)=exp(2σ2xixj2),σ>0为高斯核的带宽RBF核:Radial Basis Function Kernel
4、拉普拉斯核: k ( x i , x j ) = e x p ( − ∥ x i − x j ∥ σ ) , σ > 0 k(x_{i}, x_{j}) = exp(-\frac{\parallel x_{i} - x_{j} \parallel}{\sigma}), \sigma > 0 k(xi,xj)=exp(σxixj)σ>0
5、Sigmoid核: k ( x i , x j ) = t a n h ( β x i T x j + θ ) k(x_{i}, x_{j}) = tanh(\beta x_{i}^T x_{j} + \theta) k(xi,xj)=tanh(βxiTxj+θ)

高斯核函数

高斯核函数是一种常用的核函数,通常用于支持向量机(SVM)等机器学习算法中。它可以将数据从原始空间映射到更高维的空间,使得原本不可分的样本在新的空间中可以被分离开来。

通俗地说,高斯核函数就像是一种“相似度度量方式”,它可以计算出两个样本之间的相似度。在使用高斯核函数时,我们会首先选择一个中心点,然后计算每个样本点与中心点之间的距离,并将距离作为相似度的度量值。这个距离通常用高斯分布函数进行加权,这也是高斯核函数名称的由来。
更具体地说,高斯核函数可以将两个样本点 x i x_i xi x j x_j xj映射到更高维的空间中,计算它们在新空间中的内积,得到如下公式:
K ( x i , x j ) = exp ⁡ ( − γ ∣ ∣ x i − x j ∣ ∣ 2 ) K(x_i, x_j) = \exp(-\gamma ||x_i - x_j||^2) K(xi,xj)=exp(γ∣∣xixj2)

其中, γ \gamma γ是一个控制高斯分布宽度的参数, ∣ ∣ x i − x j ∣ ∣ 2 ||x_i - x_j||^2 ∣∣xixj2是样本点 x i x_i xi x j x_j xj之间的欧几里得距离的平方。当 γ \gamma γ取值较大时,高斯分布的峰值会变得较窄,相似度的度量会更加关注两个样本点之间的距离;当 γ \gamma γ取值较小时,高斯分布的峰值会变得较宽,相似度的度量会更加平滑,关注两个样本点之间的整体相似度。

总的来说,高斯核函数是一种非常灵活、强大的相似度度量方式,可以用于许多机器学习算法中,特别是涉及到非线性分类问题时。

在这里插入图片描述
在这里插入图片描述
接下来通过高斯核函数映射来更加直观地理解整个映射的过程。

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-4, 5, 1)
# array([-4, -3, -2, -1,  0,  1,  2,  3,  4])
y = np.array((x >= -2) & (x <= 2), dtype='int')
# array([0, 0, 1, 1, 1, 1, 1, 0, 0])
plt.scatter(x[y==0], [0] * len(x[y==0]))
plt.scatter(x[y==1], [0] * len(x[y==1]))
plt.show()

在这里插入图片描述
高斯核后

def gaussian(x, l):
    gamma = 1.0
    return np.exp(-gamma *(x-l)**2)

l1, l2 = -1, 1

x_new = np.empty((len(x), 2))
for i,data in enumerate(x):
    x_new[i, 0] = gaussian(data, l1)
    x_new[i, 1] = gaussian(data, l2)

plt.scatter(x_new[y==0, 0], x_new[y==0, 1])
plt.scatter(x_new[y==1, 0], x_new[y==1, 1])
plt.show()

在这里插入图片描述
其实,真正的高斯核函数实现的过程中并不是固定的 γ \gamma γ,而是对于每一个数据点都是 γ \gamma γ,这里写死 gamma = 1.0。
在这里插入图片描述
高斯函数: g ( x ) = 1 σ 2 π e − 1 2 ( x − μ σ ) g(x)= \frac{1}{\sigma \sqrt{2 \pi} } e^{-\frac{1}{2}(\frac{x - \mu}{\sigma})} g(x)=σ2π 1e21(σxμ)
其中 μ \mu μ决定了函数的中心位置, σ \sigma σ决定了整个图形 的靠拢程度, σ \sigma σ越小,图像越高,图像相对比较集中。相反 σ \sigma σ越大,图形就越分散。
K ( x i , x j ) = e − γ ∥ x i − x j ∥ 2 K(x_{i},x_{j}) = e^{-\gamma \parallel x_{i} - x_{j} \parallel ^2} K(xi,xj)=eγxixj2
γ \gamma γ越大,高斯分布越宽;

γ \gamma γ越小,高斯分布越窄。

接下来,使用sklearn中封装的高斯核函数:

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

x, y = datasets.make_moons(noise=0.15, random_state=666)

from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline

def RBFKernelSVC(gamma=1.0):
    return Pipeline([
        ('std_scale', StandardScaler()),
        ('svc', SVC(kernel='rbf', gamma=gamma))
    ])

svc = RBFKernelSVC(gamma=1.0)
svc.fit(x, y)

def plot_decision_boundary(model, axis):
    x0, x1 = np.meshgrid(np.linspace(axis[0], axis[1], int((axis[1] - axis[0])*100)).reshape(1, -1),
                         np.linspace(axis[2], axis[3], int((axis[3] - axis[2])*100)).reshape(1, -1),)
    x_new = np.c_[x0.ravel(), x1.ravel()]
    y_predict = model.predict(x_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#EF9A9A', '#FFF59D', '#90CAF9'])

    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

plot_decision_boundary(svc, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()

在这里插入图片描述

svc_gamma100 = RBFKernelSVC(gamma=100)
svc_gamma100.fit(x, y)

plot_decision_boundary(svc_gamma100, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()

在这里插入图片描述

svc_gamma10 = RBFKernelSVC(gamma=10)
svc_gamma10.fit(x, y)

plot_decision_boundary(svc_gamma10, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()

在这里插入图片描述

svc_gamma01 = RBFKernelSVC(gamma=0.1)
svc_gamma01.fit(x, y)

plot_decision_boundary(svc_gamma01, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1, 0], x[y==1, 1])
plt.show()

在这里插入图片描述
gamma相当于是在调节模型的复杂度,gammma越小模型复杂度越低,gamma越高模型复杂度越高。因此需要调节超参数gamma平衡过拟合和欠拟合。

本文文字和例题来源:

  1. https://cuijiahua.com/blog/2017/11/ml_8_svm_1.html
  2. https://zhuanlan.zhihu.com/p/79679104

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/488603.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

买入苹果公司股票的三个理由

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 苹果股票的关键指标 苹果公司&#xff08;AAPL&#xff09;在2023财年第一季度财报发布会上透露&#xff0c;其“活跃设备安装数量”在七年内已经增长了100%&#xff0c;达到了20亿部&#xff0c;这相当于年复合年增长率已…

Vue---Vuex状态管理核心

目录 一、Vuex是干什么的 二、Vuex状态管理核心 &#xff08;1&#xff09;State &#xff08;2&#xff09;Getter &#xff08;3&#xff09;Mutation &#xff08;4&#xff09;Action 一、Vuex是干什么的 vuex的出现就是为了更加方便地管理组件之间的数据交互&#xf…

SpringMVC与SpringWebFlux

文章目录 Spring MVCMVC架构请求处理流程语法代码示例 Spring WebFlux请求处理流程语法代码示例 两者使用对比及建议 Spring MVC Spring Web MVC是建立在Servlet API上的原始Web框架&#xff0c;从一开始就包含在Spring框架中。正式名称 "Spring Web MVC "来自其源模…

控制系统的扰动补偿

名义模型干扰观测器 理论推导 所谓被控对象的名义模型&#xff0c;就是说&#xff0c;实际被控对象无论是通过系统建模还是系统辨识&#xff0c;都无法获得十分精确的参数&#xff0c;名义模型就是与实际系统模型相近的模型&#xff0c;可近似二者相同&#xff0c;即 则 连…

MySQL:常见运算符

前言&#xff1a; 五一过后&#xff0c;我又来啦&#xff01;狂玩五天&#xff0c;放松好心情~ MySQL中的运算符有以下4类&#xff0c;分别是&#xff1a;算数运算符&#xff0c;比较运算符&#xff0c;逻辑运算符&#xff0c;位操作运算符。 算数运算符&#xff1a; 有一定…

【hello Linux】vscode的下载与远程登陆

目录 1. vscode的下载 2. 使用vscode远程登陆至xshell 3. vscode背景颜色的设置 Linux&#x1f337; 1. vscode的下载 1. 点击下方链接进入vscode官网&#xff0c;选择自己所需的vscode版本&#xff0c;直接下载&#xff1b; vscode官网 2. 按如下步骤安装vscode&#xff1b…

USART串口发送

文章目录 运行环境&#xff1a;1.1 串口发送1)用户手册2)原理图 2.1配置1)串口引脚配置2)通讯配置3)RCC和SYS 3.1代码分析3.2添加代码1)串口发送函数2)硬件和驱动安装3)launch设置 4.1实验效果 运行环境&#xff1a; ubuntu18.04.melodic 宏基暗影骑士笔记本 stm32f427IIH6 st…

支持轴体热插拔的平价机械键盘,全尺寸带灯效,雷柏V700DIY上手

日常工作娱乐中少不了键盘&#xff0c;这两年定制化的机械键盘很受欢迎&#xff0c;不过动辄上千的发烧键盘还是让很多朋友望而却步&#xff0c;好在目前市面上也有不少平价款的DIY键盘可以选择&#xff0c;像是我现在用的这款雷柏 V700DIY&#xff0c;就可以轻松定制&#xff…

Distilling Step-by-Step: 可以用更少的训练数据与模型尺寸战胜同级别的LLM!

Distilling Step-by-Step: 可以用更少的训练数据与模型尺寸战胜同级别的LLM&#xff01; IntroductionMethod实验参考 Introduction 作者提到部署大模型存在时延、内存、算力等挑战&#xff0c;所以目前的趋势是微调、蒸馏一个不是很大的语言模型&#xff0c;如Vicuna、Alpaca…

一个WPF开发的、界面简洁漂亮的音频播放器

今天推荐一个界面简洁、美观的、支持国际化开源音频播放器。 项目简介 这是一个基于C# WPF开发的&#xff0c;界面外观简洁大方&#xff0c;操作体验良好的音频播放器。 支持各种音频格式&#xff0c;包括&#xff1a;MP4、WMA、OGG、FLAC、M4A、AAC、WAV、APE 和 OPUS&…

【Python入门知识】NumPy数组迭代及连接

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 数组迭代 迭代意味着逐一遍历元素&#xff0c;当我们在 numpy 中处理多维数组时&#xff0c; 可以使用 python 的基本 for 循环来完成此操作。 如果我们对 1-D 数组进行迭代&#xff0c;它将逐一遍历每个元素。 实例 迭…

openSUSE----openSUSE开启sshd服务

【原文链接】openSUSE----openSUSE开启sshd服务 &#xff08;1&#xff09;首先修改配置&#xff0c;编辑 vi /etc/ssh/sshd_config 文件&#xff0c;将如下两个字段设置为yes PermitRootLogin yes PasswordAuthentication yes&#xff08;2&#xff09;然后搜索firewall&…

Springboot +Flowable,DataObject的使用方式

一.简介 在 Flowable 流程图的绘制过程中&#xff0c;可以编写一个名为 dataObject &#xff08;数据对象&#xff09;的元素&#xff0c;这个元素可以指定变量的 id、名称以及数据类型等各种属性&#xff0c;并且在流程实例启动的时候&#xff0c;会自动将 dataObject 元素的…

Pyinstaller将python文件打包成exe程序——封装LoFTR开源匹配代码

Pyinstaller将python文件打包成exe程序——封装LoFTR开源匹配代码 1.LoFTR代码下载及环境搭建 源码下载&#xff1a;https://github.com/bodhisatan/LoFTR-Stitch 环境搭建&#xff1a;按照github项目中的readme文档进行搭建即可&#xff0c;几乎没有遇到问题&#xff0c;代码…

通用操作日志处理方案

why&#xff08;目的理念&#xff09;&#xff1a;操作日志是什么需要做哪些事情&#xff1f; 摘自美团博客的操作日志的介绍 操作日志的记录格式大概分为下面几种&#xff1a; * 单纯的文字记录&#xff0c;比如&#xff1a;2021-09-16 10:00 订单创建。 * 简单的动态的文本…

计算机网络中的路由选择背后的原理到底是什么样的?

路由选择是计算机网络中一个重要的概念&#xff0c;它指的是当一个数据包在网络中传输时&#xff0c;如何选择最优的路径以达到目的地。路由选择涉及到网络中的路由器和交换机&#xff0c;以及它们之间的通信协议。 本文将介绍路由选择的基本概念、算法和协议&#xff0c;以及…

虹科教您 | 基于Windows系统操作使用RELY-TSN-KIT评估套件

我们曾通过3篇文章详细介绍了如何在Linux系统中使用RELY-TSN-KIT并进行TSN协议测试&#xff0c;而本篇文章则将基于Windows系统来进行介绍。与Linux系统的操作类似的部分&#xff0c;本篇文章不再赘述&#xff0c;欢迎通过下方链接阅读前文&#xff1a; 虹科教您 | 基于Linux系…

UG NX二次开发(C#)-建模-一键获取直线与坐标轴的夹角

文章目录 1、前言2、在UG NX中随便创建几条直线3、在UG NX中的分析操作4、UG NX二次开发实现4.1 基本思路4.2 创建基准坐标系4.3 计算直线与轴向的夹角方法4.4 添加调用方法4.5 代码说明5、测试效果1、前言 在UG NX新版本中,测量的操作都集成在一起了,有读者私下问我,想开发…

OceanBase 4.0(小鱼)入选2023数字中国建设峰会“十大硬核科技”

4 月 27 日 &#xff0c;第六届数字中国建设峰会发布“十大硬核科技”&#xff0c;原生分布式数据库 OceanBase 4.0&#xff08;小鱼&#xff09;入选&#xff0c;这是对 OceanBase 在技术突破上的权威肯定。OceanBase 4.0 是业内首个单机分布式一体化数据库&#xff0c;突破了…

【深度学习】计算机视觉(13)——tensorboard

因为意识到tensorboard的使用远不止画个图放个图片那么简单&#xff0c;所以这里总结一些关键知识的笔记。由于时间问题&#xff0c;我先学习目前使用最多的功能&#xff0c;大部分源码都包含summary的具体使用&#xff0c;基本不需要自己修改&#xff0c;因此tensorboard的解读…