机器学习之支持向量机(SVM)

news2024/11/25 2:02:28

1 支持向量机介绍

支持向量机(support vector machine,SVM)是有监督学习中最有影响力的机器学习算法之一,该算法的诞生可追溯至上世纪 60 年代, 前苏联学者 Vapnik 在解决模式识别问题时提出这种算法模型,此后经过几十年的发展直至 1995 年, SVM 算法才真正的完善起来,其典型应用是解决手写字符识别问题。

SVM 是一种非常优雅的算法,有着非常完善的数学理论基础,其预测效果,在众多机器学习模型中“出类拔萃”。在深度学习没有普及之前,“支持向量机”可以称的上是传统机器学习中的“霸主”。

支持向量机是一种二分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。支持向量机的学习算法是求解凸二次规划的最优化算法。

基础的SVM算法是一个二分类算法,至于多分类任务,可以通过多次使用SVM进行解决。

1.1 线性可分

对于一个数据集合可以画一条直线将两组数据点分开,这样的数据成为线性可分(linearly separable),如下图所示:

  •  分割超平面:将上述数据集分隔开来的直线成为分隔超平面。对于二维平面来说,分隔超平面就是一条直线。对于三维及三维以上的数据来说,分隔数据的是个平面,称为超平面,也就是分类的决策边界。
  • 间隔:点到分割面的距离,称为点相对于分割面的间隔。数据集所有点到分隔面的最小间隔的2倍,称为分类器或数据集的间隔。论文中提到的间隔多指这个间隔。SVM分类器就是要找最大的数据集间隔。
  • 支持向量:离分隔超平面最近的那些点。

SVM所做的工作就是找这样个超平面,能够将两个不同类别的样本划分开来,但是这种平面是不唯一的,即可能存在无数个超平面都可以将两种样本分开,那么我们如何才能确定一个分类效果最好的超平面呢?
Vapnik提出了一种方法,对每一种可能的超平面,我们将它进行平移,直到它与空间中的样本向量相交。我们称这两个向量为支持向量,之后我们计算支持向量到该超平面的距离d,分类效果最好的超平面应该使d最大。

1.2 寻找最大间隔

(1)分隔超平面

二维空间一条直线的方程为,y=ax+b,推广到n维空间,就变成了超平面方程,即

 w是权重,b是截距,训练数据就是训练得到权重和截距。

(2)如何找到最好的参数

支持向量机的核心思想: 最大间隔化, 最不受到噪声的干扰。如上图所示,分类器A比分类器B的间隔(蓝色阴影)大,因此A的分类效果更好。

SVM划分的超平面:f(x) = 0,w为法向量,决定超平面方向,

假设超平面将样本正确划分
  f(x) ≥ 1,y = +1
  f(x) ≤ −1,y = −1

  间隔:r=2/|w|

约束条件:

 (3)转化为凸优化

设 f(x) 为定义在n维欧式空间中某个凸集 S 上的函数,若对于任何实数α(0 < α< 1 )以及 S 中的不同两点 x,y ,均有:

那么,f(x)为定义在凸集 S 上的凸函数。

 有约束的凸优化问题:

如果f(x),g(x)为凸函数,h(x)为仿射函数时,这是一个凸优化的问题。

对于支持向量机:

SVM是一个凸二次规划问题,有最优解。

(4)拉格朗日对偶

通常我们需要求解的最优化问题有如下几类:

  (i) 无约束优化问题,可以写为:

                min f(x)

  (ii) 有等式约束的优化问题,可以写为:

                min f(x),

                s.t. h_i(x) = 0;i =1, ..., n

  (iii) 有不等式约束的优化问题,可以写为:

                min f(x),

                s.t. g_i(x) <= 0;i =1, ..., n

                h_j(x) = 0;j =1, ..., m
  对于第(i)类的优化问题,常常使用的方法就是Fermat定理,即使用求取f(x)的导数,然后令其为零,可以求得候选最优值,再在这些候选值中验证;如果是凸函数,可以保证是最优解。

拉格朗日乘子法与对偶问题

  对于第(ii)类的优化问题,常常使用的方法就是拉格朗日乘子法(Lagrange Multiplier) ,即把等式约束h_i(x)用一个系数与f(x)写为一个式子,称为拉格朗日函数,而系数称为拉格朗日乘子。通过拉格朗日函数对各个变量求导,令其为零,可以求得候选值集合,然后验证求得最优值。

 例如给定椭球:

 求这个椭球的内接长方体的最大体积。

我们将这个转化为条件极值问题,即在条件

下,求f(x,y,z)=8xyz的最大值。

首先定义拉格朗日函数F(x)

λk是各个约束条件的待定系数

然后解变量的偏导方程:

如果有i个约束条件,就应该有i+1个方程。求出的方程组的解就可能是最优化值(极值),将结果带回原方程验证即可得解。

回到上面的题目,通过拉格朗日乘数法将问题转化为:

 对F(x,y,z,λ)求偏导得:

联立前面三个方程得到bx=ay和az=cx,代入第四个方程解得:

最大体积为:

KKT条件

对于第(iii)类的优化问题,常常使用的方法就是KKT条件(Karush-Kuhn-Tucker)。同样地,我们把所有的等式、不等式约束与f(x)写为一个式子,也叫拉格朗日函数,系数也称拉格朗日乘子,通过一些条件,可以求出最优值的必要条件,这个条件称为KKT条件。

原始含有不等式约束问题描述为:

                 min  f(x),

      s.t.  g(x)≤0

含有不等式约束的KKT条件为如下式(记为式①)所示:

 注意:KKT条件是非线性规划最优解的必要条件

  • KKT条件描述型理解

  (i)当最优解 x* 满足g(x*) <0时,最优解位于可行域内部,此时不等式约束无效,λ=0。

  (ii)当最优解 x*满足g(x*) = 0时,最优解位于可行域的边界,此时不等式约束变为等式约束,g(x)=0。

  (iii)同时根据几何意义,λ必<0(根据梯度可得)。

  根据上述讨论,由于我们所需的是必要条件,故将上述几种情况进行并集操作,可得最优解时的必要条件,即(记为式②):
          ∇xL=∇f+λ∇g=0

           g(x)≤0

           λ≥0

           λg(x)=0

  (iv)当有多个不等式约束时,可推广至式①形式。

KKT条件要求强对偶,形式如下:

 前两条为x*满足的原问题的约束。第三条表示对偶变量满足的约束,第四条为互补松弛条件,第五条表示拉格朗日函数在x*处取得极小值(即x*是最优解,满足拉格朗日函数极小的条件)

 1.3 线性不可分

对于线性不可分的数据集,我们无法找到这样一种直线,将不同类型的样本分割开来,SVM的方法好像就不适用了。但是Vapnik提出了一种观点,我们所认为的线性不可分,只是在当前维度下线性不可分,并不代表它在高维空间中线性不可分。比如有一组样本在二维空间线性不可分,但是在三维空间中,我们是有可能找到这样一条直线将其分隔开来的,Vapnik还认为,当维数趋于无穷时,一定存在这样一条线,可以将不同类型的样本分割开来。

Cover定理:

在提升维度后,原本非线性的数据点变得线性可分,这在数学上是有严格证明的,即Cover定理。Cover定理可以定性地描述为:将复杂的模式分类问题非线性地投射到高维空间将比投射到低维空间更可能是线性可分的,当空间的维数D越大时,在该空间的N个数据点间的线性可分的概率就越大。

或者再通俗的说,这个定理描述的是线性可分的概率,如果能把数据从低维空间映射到高维空间,我们就很可能在高维空间把数据做线性可分。对于在N维空间中线性不可分的数据,在N+1维以上的空间会有更大可能变成线性可分的。

所以人们就努力的寻找一种映射,这映射能将样本从原始空间(低维数据)转变到高维特征空间,从而把低维空间中线性不可分的两类点变成线性可分的。这种映射ϕ(X) 又可称为“特征构建”,映射后的向量可称之为“特征向量”。

首先,输入的数据样本集为一组N个m0维的向量x1,x1,...,xN,每个样本都被归类到两个类C1和C2之一。定义一组实值函数(也就是输入一个向量输出一个实数的函数)φ1(x),φ2(x),...,φm1(x),用来将输入数据映射到一个m1维的空间,将它们组成一个向量:

这个函数向量ϕ的输出可被认为是被映射到高维空间之后的输入数据x。φi(x)称为隐藏函数,其组成的向量ϕ所在的空间称为隐藏空间特征空间。如果有那么个m1维的向量w,使得这个成立: 

也就是说被ϕ映射到另一个高维空间的数据样本们成了线性可分的,就说这个把x分类到C1和C2的分法是ϕ可分的。
对于x来说, wTϕ(x)=0就是一个分类曲面。

于是模式可分性的Cover定理在这就包含这两部分:

  • 隐藏函数的非线性转换。
  • 高维的特征空间(这个高维是相对原始数据的维度来说的,由隐藏函数的个数决定)。

异或问题

异或问题因为是个典型的线性不可分问题。其点(0,0)和(1,1)归于类0,点(0,1)和点(1,0)归于类1。然后我们要拿一组隐藏函数将这些点映射到零一空间里。在这里使用高斯隐藏函数。因为问题简单,所以只用了两个隐藏函数,维度没有增加:

 其中 t1=(1,1), t2=(0,0)。也就是拿样本点跟这两点的几何距离作为高斯函数的自变量。转换结果如下:

转换前转换后
(1,1)(1.0000, 0.1353)
(0,1)(0.3678, 0.3678)
(0,0)(0.1353, 1.0000)
(1,0)(0.3678, 0.3678)

映射后的数据如图所示,原来线性不可分的数据,已经变成了线性可分

1.3 核函数

映射可以看作是一种拉伸,把低维数据拉伸到了高维。虽然现在我们到了高维空间号称线性可分,但是有几个困难:

  • 不知道什么样的映射函数是完美的。
  • 难以在各种映射函数中找到一个合适的。
  • 高维空间计算量比较大。这样就会产生维灾难,计算内积是不现实的。

幸运的是,在计算中发现,我们需要的只是两个向量在新的映射空间中的内积结果,而映射函数到底是怎么样的其实并不需要知道。于是这样就引入了核函数的概念。

核函数事先在低维上计算,而将实质上的分类效果表现在了高维上,也就是

  • 包含映射,内积,相似度的逻辑。

  • 消除掉把低维向量往高维映射的过程。

  • 避免了直接在高维空间内的复杂计算。

即核函数除了能够完成特征映射,而且还能把特征映射之后的内积结果直接返回。即把高维空间得内积运算转化为低维空间的核函数计算。

注意,核函数只是将完全不可分问题,转换为可分或达到近似可分的状态。

在实际中,我们会经常遇到线性不可分的样例,此时,我们的常用做法是把样例特征映射到高维空间中去,但如果凡是遇到线性不可分的样例,一律映射到高维空间,那么这个维度大小是会高到可怕的,此时就需要使用核函数。核函数虽然也是将特征进行从低维到高维的转换,但核函数会先在低维上进行计算,而将实质上的分类效果表现在高维上,避免了直接在高维空间中的复杂计算。

 如下图所示的两类数据,这样的数据本身是线性不可分的,当我们将二维平面的坐标值映射一个三维空间中,映射后的结果可以很明显地看出,数据是可以通过一个平面来分开的。

核函数方法处理非线性问题的基本思想:按一定的规则进行映射,使得原来的数据在新的空间中变成线性可分的,从而就能使用之前推导的线性分类算法进行处理。计算两个向量在隐式映射过后的空间中的内积的函数叫做核函数

核函数是这样的一种函数:

仍然以二维空间为例,假设对于变量x和y,将其映射到新空间的映射函数为φ,则在新空间中,二者分别对应φ(x)和φ(y),他们的内积则为<φ(x),φ(y)>。

我们令函数Kernel(x,y)=<φ(x),φ(y)>=k(x,y)

可以看出,函数Kernel(x,y)是一个关于x和y的函数!而与φ无关!这是一个多么好的性质!我们再也不用管φ具体是什么映射关系了,只需要最后计算Kernel(x,y)就可以得到他们在高维空间中的内积。

我们则称Κ(x,y)为核函数,φ(x)为映射函数。

我们大致能够得到核函数如下性质:

  • 核函数给出了任意两个样本之间关系的度量,比如相似度。
  • 每一个能被叫做核函数的函数,里面都藏着一个对应拉伸的函数。这些核函数的命名通常也跟如何做拉伸变换有关系。
  • 核函数和映射本身没有直接关系。选哪个核函数,实际上就是在选择用哪种方法映射。通过核函数,我们就能跳过映射的过程。
  • 我们只需要核函数,而不需要那个映射,也无法显式的写出那个映射。
  • 选择核函数就是把原始数据集上下左右前后拉扯揉捏,直到你一刀下去正好把所有的 0 分到一边,所有的 1 分到另一边。这个上下左右前后拉扯揉捏的过程就是kernel.


核函数存在的条件

定理表明,只要一个对称函数所对应的核矩阵半正定,那么它就可以作为核函数使用。事实上,对于一个半正定核矩阵,总能找到一个与之对应的映射ϕ。换言之,任何一个核函数都隐式定义了一个称为“再生核希尔伯特空间”的特征空间
 

常见的核函数

通过前面的介绍,核函数的选择,对于非线性支持向量机的性能至关重要。但是由于我们很难知道特征映射的形式,所以导致我们无法选择合适的核函数进行目标优化。于是“核函数的选择”称为支持向量机的最大变数,我们常见的核函数有以下几种:

此外,还可以通过函数组合得到,例如:

对于非线性的情况,SVM 的处理方法是选择一个核函数 κ(⋅,⋅),通过将数据映射到高维空间,来解决在原始空间中线性不可分的问题。由于核函数的优良品质,这样的非线性扩展在计算量上并没有比原来复杂多少,这一点是非常难得的。当然,这要归功于核方法——除了 SVM 之外,任何将计算表示为数据点的内积的方法,都可以使用核方法进行非线性扩展。

1.4 正则化与软间隔

 针对样本不是完全能够划分开的情况,可以允许支持向量机在一些样本上出错,为此要引入“软间隔”的概念。

引入正则化强度参数C(正则化:在一定程度上抑制过拟合,使模型获得抗噪声能力,提升模型对未知样本的预测性能的手段),损失函数重新定义为:

 上式为采用hinge损失的形式,再引入松弛变量ξi≥0,重写为:

 支持向量:

 由此可以看出,软间隔支持向量机的最终模型仅与支持向量有关,即通过采用hinge损失函数仍保持了稀疏特性。

2 SVM的优缺点及应用场景

2.1 SVM的优缺点

(1)SVM的优点:

  • 高效的处理高维特征空间:SVM通过将数据映射到高维空间中,可以处理高维特征,并在低维空间中进行计算,从而有效地处理高维数据。

  • 适用于小样本数据集:SVM是一种基于边界的算法,它依赖于少数支持向量,因此对于小样本数据集具有较好的泛化能力。

  • 可以处理非线性问题:SVM使用核函数将输入数据映射到高维空间,从而可以解决非线性问题。常用的核函数包括线性核、多项式核和径向基函数(RBF)核。

  • 避免局部最优解:SVM的优化目标是最大化间隔,而不是仅仅最小化误分类点。这使得SVM在解决复杂问题时能够避免陷入局部最优解。

  • 对于噪声数据的鲁棒性:SVM通过使用支持向量来定义决策边界,这使得它对于噪声数据具有一定的鲁棒性。

(2)SVM的缺点:

  • 对大规模数据集的计算开销较大:SVM的计算复杂度随着样本数量的增加而增加,特别是在大规模数据集上的训练时间较长。

  • 对于非线性问题选择合适的核函数和参数较为困难:在处理非线性问题时,选择适当的核函数和相应的参数需要一定的经验和领域知识。

  • 对缺失数据敏感:SVM在处理含有缺失数据的情况下表现不佳,因为它依赖于支持向量的定义。

  • 难以解释模型结果:SVM生成的模型通常是黑盒模型,难以直观地解释模型的决策过程和结果。

SVM在处理小样本数据、高维特征空间和非线性问题时表现出色,但对于大规模数据集和缺失数据的处理相对困难。同时,在模型的解释性方面也存在一定的挑战。

2.2 SVM的应用场景

SVM在许多其他领域也有广泛的应用,特别是在分类和回归问题中。它的灵活性和强大的泛化能力使其成为机器学习中的重要工具之一。主要应用场景总结如下:

  • 文本分类:SVM可以用于对文本进行分类,如垃圾邮件分类、情感分析和文档分类等。

  • 图像识别:SVM可用于图像分类、目标识别和人脸识别等任务。它可以通过提取图像的特征向量,并将其作为输入来训练SVM模型。

  • 金融领域:SVM可用于信用评分、风险评估和股票市场预测等金融任务。

  • 医学诊断:SVM可以应用于医学图像分析,如疾病检测、癌症诊断和医学影像分类等。

  • 视频分类:SVM可以用于视频分类、行为识别和运动检测等任务,通过提取视频帧的特征并将其输入SVM模型进行分类。

  • 推荐系统:SVM可以用于个性化推荐和用户分类等推荐系统任务,通过分析用户行为和特征来预测用户的兴趣和偏好。

3 基于SVM实现鸢尾花分类预测

3.1 数据集介绍

Iris 鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作示例。数据集内包含 3 类共 150 条记录,每类各 50 个数据,每条记录都有 4 项特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度,可以通过这4个特征预测鸢尾花卉属于(iris-setosa, iris-versicolour, iris-virginica)三种中的哪一品种。

数据内容:

     sepal_len  sepal_wid  petal_len  petal_wid  label
0          5.1        3.5        1.4        0.2      0
1          4.9        3.0        1.4        0.2      0
2          4.7        3.2        1.3        0.2      0
3          4.6        3.1        1.5        0.2      0
4          5.0        3.6        1.4        0.2      0
..         ...        ...        ...        ...    ...
145        6.7        3.0        5.2        2.3      2
146        6.3        2.5        5.0        1.9      2
147        6.5        3.0        5.2        2.0      2
148        6.2        3.4        5.4        2.3      2
149        5.9        3.0        5.1        1.8      2

3.2 代码实现

(1)原生代码实现

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



def create_data():
    iris = load_iris()
    df = pd.DataFrame(iris.data, columns=iris.feature_names)
    df['label'] = iris.target

    df.columns = ['sepal_len', 'sepal_wid', 'petal_len', 'petal_wid', 'label']
    print(df)

    data = np.array(df.iloc[:100, [0, 1, -1]])

    for i in range(len(data)):
        if data[i,-1] == 0:
            data[i,-1] = -1

    return data[:,:2], data[:,-1]


class SVM:
    def __init__(self, max_iter=100, kernel='poly'):
        self.max_iter = max_iter
        self._kernel = kernel

    def init_args(self, features, labels):
        self.m, self.n = features.shape
        self.X = features
        self.Y = labels
        self.b = 0.0

        # 将Ei保存在一个列表里
        self.alpha = np.ones(self.m)
        self.E = [self._E(i) for i in range(self.m)]
        # 松弛变量
        self.C = 1.0

    def _KKT(self, i):
        y_g = self._g(i)*self.Y[i]
        if self.alpha[i] == 0:
            return y_g >= 1
        elif 0 < self.alpha[i] < self.C:
            return y_g == 1
        else:
            return y_g <= 1

    # g(x)预测值,输入xi(X[i])
    def _g(self, i):
        r = self.b
        for j in range(self.m):
            r += self.alpha[j]*self.Y[j]*self.kernel(self.X[i], self.X[j])
        return r

    # 核函数
    def kernel(self, x1, x2):
        if self._kernel == 'linear':
            return sum([x1[k]*x2[k] for k in range(self.n)])
        elif self._kernel == 'poly':
            return (sum([x1[k]*x2[k] for k in range(self.n)]) + 1)**2

        return 0

    # E(x)为g(x)对输入x的预测值和y的差
    def _E(self, i):
        return self._g(i) - self.Y[i]

    def _init_alpha(self):
        # 外层循环首先遍历所有满足0<a<C的样本点,检验是否满足KKT
        index_list = [i for i in range(self.m) if 0 < self.alpha[i] < self.C]
        # 否则遍历整个训练集
        non_satisfy_list = [i for i in range(self.m) if i not in index_list]
        index_list.extend(non_satisfy_list)

        for i in index_list:
            if self._KKT(i):
                continue

            E1 = self.E[i]
            # 如果E2是+,选择最小的;如果E2是负的,选择最大的
            if E1 >= 0:
                j = min(range(self.m), key=lambda x: self.E[x])
            else:
                j = max(range(self.m), key=lambda x: self.E[x])
            return i, j

    def _compare(self, _alpha, L, H):
        if _alpha > H:
            return H
        elif _alpha < L:
            return L
        else:
            return _alpha

    def fit(self, features, labels):
        self.init_args(features, labels)

        for t in range(self.max_iter):
            # train
            i1, i2 = self._init_alpha()

            # 边界
            if self.Y[i1] == self.Y[i2]:
                L = max(0, self.alpha[i1]+self.alpha[i2]-self.C)
                H = min(self.C, self.alpha[i1]+self.alpha[i2])
            else:
                L = max(0, self.alpha[i2]-self.alpha[i1])
                H = min(self.C, self.C+self.alpha[i2]-self.alpha[i1])

            E1 = self.E[i1]
            E2 = self.E[i2]
            # eta=K11+K22-2K12
            eta = self.kernel(self.X[i1], self.X[i1]) + self.kernel(self.X[i2], self.X[i2]) - 2*self.kernel(self.X[i1], self.X[i2])
            if eta <= 0:
                # print('eta <= 0')
                continue

            alpha2_new_unc = self.alpha[i2] + self.Y[i2] * (E2 - E1) / eta
            alpha2_new = self._compare(alpha2_new_unc, L, H)

            alpha1_new = self.alpha[i1] + self.Y[i1] * self.Y[i2] * (self.alpha[i2] - alpha2_new)

            b1_new = -E1 - self.Y[i1] * self.kernel(self.X[i1], self.X[i1]) * (alpha1_new-self.alpha[i1]) - self.Y[i2] * self.kernel(self.X[i2], self.X[i1]) * (alpha2_new-self.alpha[i2])+ self.b
            b2_new = -E2 - self.Y[i1] * self.kernel(self.X[i1], self.X[i2]) * (alpha1_new-self.alpha[i1]) - self.Y[i2] * self.kernel(self.X[i2], self.X[i2]) * (alpha2_new-self.alpha[i2])+ self.b

            if 0 < alpha1_new < self.C:
                b_new = b1_new
            elif 0 < alpha2_new < self.C:
                b_new = b2_new
            else:
                # 选择中点
                b_new = (b1_new + b2_new) / 2

            # 更新参数
            self.alpha[i1] = alpha1_new
            self.alpha[i2] = alpha2_new
            self.b = b_new

            self.E[i1] = self._E(i1)
            self.E[i2] = self._E(i2)
        return 'train done!'

    def predict(self, data):
        r = self.b
        for i in range(self.m):
            r += self.alpha[i] * self.Y[i] * self.kernel(data, self.X[i])

        return 1 if r > 0 else -1

    def score(self, X_test, y_test):
        right_count = 0
        for i in range(len(X_test)):
            result = self.predict(X_test[i])
            if result == y_test[i]:
                right_count += 1
        return right_count / len(X_test)

    def _weight(self):
        # linear model
        yx = self.Y.reshape(-1, 1)*self.X
        self.w = np.dot(yx.T, self.alpha)
        return self.w


X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)


svm = SVM(max_iter=800)
print(svm.fit(X_train, y_train))
print(svm.score(X_train, y_train))
print(svm.score(X_test, y_test))

(2)基于sklearn的代码实现

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


def create_data():
    iris = load_iris()
    df = pd.DataFrame(iris.data, columns=iris.feature_names)
    df['label'] = iris.target
    df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
    data = np.array(df.iloc[:100, [0, 1, -1]])
    for i in range(len(data)):
        if data[i,-1] == 0:
            data[i,-1] = -1
    return data[:,:2], data[:,-1]


X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)


plt.scatter(X[:50,0],X[:50,1], label='0')
plt.scatter(X[50:,0],X[50:,1], label='1')
plt.show()


model = SVC()
model.fit(X_train, y_train)

SVC(C=1.0, break_ties=False, 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)


print('train accuracy: ' + str(model.score(X_train, y_train)))
print('test accuracy: ' + str(model.score(X_test, y_test)))

 3.3 运行结果

(1)数据分布展示:

 (2)训练集和测试集上的准确性

train accuracy: 1.0
test accuracy: 0.96

4 完整代码

代码下载地址:代码下载

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

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

相关文章

synchronized监视器锁

1、synchronized&监视器锁 1.1 synchronized 介绍 在 Java 中&#xff0c;synchronized 是一种关键字&#xff0c;用于实现线程的同步和互斥控制。它可以修饰方法或代码块&#xff0c;用于保护共享资源的访问&#xff0c;避免多个线程同时修改数据而引发的并发问题。 具…

chatgpt赋能python:Python重写父类__init__方法的必要性与实现方法

Python重写父类__init__方法的必要性与实现方法 在Python中&#xff0c;一个类可以继承自另一个类&#xff0c;从而获得另一个类的属性和方法。当我们继承一个父类时&#xff0c;通常我们需要重写其中的一些方法&#xff0c;以满足我们自己的需求。在这篇文章中&#xff0c;我…

玩机搞机-----带你了解高通刷机平台中的一些选项释义 玩转平台

很多刷机工具玩家都使用过&#xff0c;但对于一些新手来说。有些选项所表达的意义不太了解&#xff0c;选择与否严重会导致机型固件刷完个别功能出现故障&#xff0c;今天的这个博文对有些刷机平台中的选项做个简单的说明。 一 小米刷机平台 MiFlash.截止目前最新的版本是2022…

最新|2024年QS世界大学排名前100榜单发布

6月28日世界高等教育研究机构Quacquarelli Symonds&#xff08;QS&#xff09;率先公布了2024年世界大学排名&#xff0c;本次QS排名因指标和权重的重大调整&#xff0c;导致排名发生较大变化。知识人网小编将新的评分标准及前100的大学榜单整理如下&#xff0c;供读者参考。 前…

Unity渲染工程收集

NPR 非真实渲染 UnityURP-AnimeStyleCelShader SSR 屏幕空间反射 UnitySSReflectionURP

消息传输不丢失:掌握消息中间件的持久化机制

当涉及到消息的持久化和重放时&#xff0c;我们可以使用Spring Boot与RabbitMQ来实现这个场景。RabbitMQ支持消息的持久化&#xff0c;以确保在发送和接收过程中消息不会丢失。同时&#xff0c;我们可以使用消息的重放机制&#xff0c;以便在需要时重新发送消息。 首先&#xf…

leetcode:387. 字符串中的第一个唯一字符(python3解法)

难度&#xff1a;简单 给定一个字符串 s &#xff0c;找到 它的第一个不重复的字符&#xff0c;并返回它的索引 。如果不存在&#xff0c;则返回 -1 。 示例 1&#xff1a; 输入: s "leetcode" 输出: 0示例 2: 输入: s "loveleetcode" 输出: 2示例 3: 输…

1253. 重构 2 行二进制矩阵(力扣)

1253. 重构 2 行二进制矩阵&#xff08;力扣&#xff09; 题目第一种方式分析测试代码运行结果 第二种方式测试代码运行结果 题目 给你一个 2 行 n 列的二进制数组&#xff1a; 矩阵是一个二进制矩阵&#xff0c;这意味着矩阵中的每个元素不是 0 就是 1。 第 0 行的元素之和为…

系统架构设计师-软件工程(1)

一、软件过程模型 &#xff08;1&#xff09;瀑布模型、&#xff08;2&#xff09;V模型【瀑布变种】、&#xff08;3&#xff09;原型模型、 &#xff08;4&#xff09;螺旋模型【原型瀑布】、&#xff08;5&#xff09;构件组装模型/基于构件的开发方法、 &#xff08;…

学习Kotlin~类

类 类的field 类定义的每一个属性&#xff0c;kotlin都会产生一个filed,一个setter(),一个getter()field用来存储属性数据&#xff0c;不能直接定义&#xff0c;kotlin会封装&#xff0c;保护它里面数据&#xff0c;只暴露给getter和setter使用只有可变属性才有setter方法需要…

UNITY3D弹幕游戏,万人同屏解决方案_类萌宠宠之战

先上效果 &#xff08;类萌宠宠之战&#xff09;弹幕游戏&#xff0c;万人同屏解决方案演示 UNITY默认的人物动画显示方案是 SkinnedMeshRenderer 该动画的计算是由CPU计算&#xff08;计算骨骼位置所影响的顶点位置&#xff09; 所以是CPU计算&#xff0c;物体大于2000个时…

Python3,掌握这几种并行处理,轻轻松松提升for循环速度。

并行处理几种方法 1、引言2、并行处理2.1 定义2.2 并行处理优缺点2.3 并行处理的常用库2.4 代码示例2.4.1 multiprocessing2.4.2 concurrent.futures2.4.3 joblib2.4.4 threading 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;你给我讲一讲并行处理呗。 小鱼&#xff1…

Android:datePicker对话框的使用

一、前言&#xff1a;这篇文章是关于DatePickerDialog&#xff0c;点击按钮出现一个日期选择器对话框&#xff0c;通过点击确认把选则的日期显示到文本控件上。 二、上代码 页面布局xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout…

正则表达式回溯引发的生产惨案

文章目录 背景问题原因分析如何解决&#xff1f;chatgpt 3.5GP4的表现未完待续 背景 业务上的一个字段在解析时为了避免脏数据导致后续ETL的异常&#xff0c;决定从源头将该字段严格按照设计的规则去匹配。该字段的上传是设备端传上来的文件中的一个字段。 正向&#xff1f;反…

「C/C++」C++类与类的关系(UML类图+代码说明)

✨博客主页&#xff1a;何曾参静谧的博客 &#x1f4cc;文章专栏&#xff1a;「C/C」C/C学习 相关术语 &#x1f3af;依赖关系&#xff08;Dependency&#xff09;&#xff1a;表示一个类的实现需要另一个类的协助&#xff0c;虚线箭头&#xff0c;箭头指向被依赖的类。 &#…

基于当量因子法、InVEST、SolVES模型等多技术融合在生态系统服务功能社会价值评估中的应用及论文写作、拓展分析

生态系统服务是人类从自然界中获得的直接或间接惠益&#xff0c;可分为供给服务、文化服务、调节服务和支持服务4类&#xff0c;对提升人类福祉具有重大意义&#xff0c;且被视为连接社会与生态系统的桥梁。自从启动千年生态系统评估项目&#xff08;Millennium Ecosystem Asse…

2023软科中国大学智能建造专业排名结果出炉(共54所高校)

智能建造专业&#xff08;Intelligent Construction&#xff09;是一个新兴的跨学科领域&#xff0c;它涉及到建筑、土木工程、计算机科学、数据科学等多个学科的知识。智能建造专业专注于研究如何利用先进的计算机技术、人工智能&#xff08;AI&#xff09;、物联网&#xff0…

进销存软件市场成熟,为什么还要用低代码构建?

关键词&#xff1a;进销存软件、群晖NAS、低代码平台 编者按&#xff1a; 进销存管理软件产业已经逐步走向成熟&#xff0c;产品种类也越来越丰富&#xff0c;也正因如此&#xff0c;企业在选择购买进销存软件的时候&#xff0c;往往不知该如何选择。不少的企业会直接选择平台型…

[golang 微服务] 8.go-micro的负载均衡操作,go Web框(Gin,Beego)调用go-micro微服务

一.先创建go-micro服务端 启动consul 需要先启动consul, consol相关内容见 [golang 微服务] 5. 微服务服务发现介绍,安装以及consul的使用,Consul集群 [golang 微服务] 6. GRPC微服务集群Consul集群grpc-consul-resolver案例演示 启动consul命令,这里,使用dev模式: consul agen…

手机上怎么压缩视频?教你几招手机压缩视频小技巧

压缩视频是一种有益的技术&#xff0c;可以帮助人们在存储、传输和观看视频时更有效率和便捷。尤其是在现今数字化信息时代&#xff0c;视频已经成为人们日常生活中不可或缺的一部分&#xff0c;因此更需要使用视频压缩技术来更好地管理和使用这些视频文件。下面给大家分享几种…