机器学习 | SVM支持向量机

news2024/11/27 1:34:01

         

        欲穷千里目,更上一层楼。

        一个空间的混乱在更高维度的空间往往意味着秩序。

        Machine-Learning: 《机器学习必修课:经典算法与Python实战》配套代码 - Gitee.com


1、核心思想及原理

         针对线性模型中分类两类点的直线如何确定。这是一个ill-posed problem。

         线性模型通过求解各点距离进行投票,可以使用sigmoid函数来求解总损失,转换成一个最优化问题。但是模型泛化能力太差,很容易受到噪声的干扰,直线可能会发生很大变化。

         所以我们更想让直线靠近中间位置。

        

        

        三个概念

        支持向量 support vector —— 距离决策边界最近的点,每个类别的极端数据点

        超平面 hyperplane —— “隔离带”中间的平分线

        间隔 margin —— 最大化margin

        

        民主集中的思想 ~

        


2、线性SVM —— 硬间隔 Hard Margin

 (假定数据本身线性可分)

        通过上一小节我们得到优化目标:

        最大化间隔margin 也就是 最大化距离 d,也就是点到超平面的垂直距离。

        注意此处的距离和线性模型中的距离不同,线性模型中的距离是 yhat-y (斜边)

        

        SVM的求解过程和线性方程一样:

                先假设一个超平面,

                这里的W和X都是高维向量,点到高维空间中的距离有现成公式可以套用:

                ||w||为w的范数,表示高维空间中长度的概念。

                

                有了这样一个距离公式,隔离带就可以表示为一个分段函数的形式。

                我们用1和-1来表示两个类别:

                

                

                现在我们给柿子两边同时除以d 变形,再继续整理做变量代换:

               

                为了方便表示,看着撇多难受,我们再用w和b换回去,

                但此时的w b和一开始推到时的w b,理论上已经不是同一个数了。

                但是存在一个比例关系。在做一个变形:

                

                则现在的问题就简化为:

                

                 这是一个不等式约束的最优化问题。梯度下降只能用于无约束的最优化。

                 ps:

                 不等式约束最优化 引入 松弛变量 到等式约束最优化。

                 等式约束最优化 引入 拉格朗日乘子 到无约束最优化。

        注意,这里的 i 是遍历所有的数据点。但在最小化范数时,我们只用到了支持向量。

        

         但是如果你相信的人也出了问题呢?


3、线性SVM —— 软间隔 Soft Margin

        软间隔要解决的问题:

                异常值 outliner      

                支持向量的选择、民主集中思想的弱点

                

        则需:建立容错机制,提升泛化能力

        那么体现在数学上:允许点越过线一点点 ~

        

        那么怎么保证 这个减去的值不能太大呢?

        

        也就是说尽量让所有数据容错值的和最小。让二者取一个平衡。

        C 就是一个新的超参数,用来调节两者的权重值。

        再看一下这个求和的形式,是不是特别像正则化?其实就可以看成正则化。

        正则化项是一次的,所以叫L1正则。这里省略了绝对值符号,因为其就是正数。

        


 4、线性SVM代码实现

数据集

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
x, y = make_blobs(
    n_samples=40, 
    centers=2, 
    random_state=0
)
plt.scatter(x[:,0], x[:,1], c = y)
plt.show()

sklearn中的线性SVM

from sklearn.svm import LinearSVC
clf = LinearSVC(C = 1)
clf.fit(x, y)

LinearSVC

LinearSVC(C=1)
clf.score(x, y)
1.0
def decision_boundary_plot(X, y, clf):
    axis_x1_min, axis_x1_max = X[:,0].min() - 1, X[:,0].max() + 1
    axis_x2_min, axis_x2_max = X[:,1].min() - 1, X[:,1].max() + 1
    
    x1, x2 = np.meshgrid( np.arange(axis_x1_min,axis_x1_max, 0.01) , np.arange(axis_x2_min,axis_x2_max, 0.01))
    z = clf.predict(np.c_[x1.ravel(),x2.ravel()])
    z = z.reshape(x1.shape)
    
    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#F5B9EF','#BBFFBB','#F9F9CB'])

    plt.contourf(x1, x2, z, cmap=custom_cmap)
    plt.scatter(X[:,0], X[:,1], c=y)
    plt.show()
decision_boundary_plot(x, y, clf)

def plot_svm_margin(x, y, clf, ax = None):
    from sklearn.inspection import DecisionBoundaryDisplay
    DecisionBoundaryDisplay.from_estimator(
        clf,
        x,
        ax = ax,
        grid_resolution=50,
        plot_method="contour",
        colors="k",
        levels=[-1, 0, 1],
        alpha=0.5,
        linestyles=["--", "-", "--"],
    )
    plt.scatter(x[:,0], x[:,1], c = y)
plot_svm_margin(x, y, clf)
plt.show()

plt.rcParams["figure.figsize"] = (12, 8)

params = [0.1, 1, 10, 100]
for i, c in enumerate(params):
    clf = LinearSVC(C = c, random_state=0)
    clf.fit(x, y)
    
    ax = plt.subplot(2, 2, i + 1)
    plt.title("C: {0}".format(c))
    plot_svm_margin(x, y, clf, ax)
    
plt.show()

多分类

from sklearn import datasets

iris = datasets.load_iris()
x = iris.data
y = iris.target

注意SVM中只支持ovr ~

clf = LinearSVC(C = 0.1, multi_class='ovr', random_state=0)
clf.fit(x, y)

LinearSVC

LinearSVC(C=0.1, random_state=0)
clf.predict(x)
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, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])


 5、非线性SVM —— 核技巧

线性不可分问题

        

         升维映射

        

        高维线性可分

        

       已经有前人在数学上证明:

        如果原始的空间是有限的,也就是说特征数是有限的,

        那么一定存在一个高位的特征空间能够分割这些样本。

        

软间隔对偶 dual 问题 

        

        则现在就要解决右边的问题。

         

        套上一个 φ 就可以升维,但是可能会导致维度灾难,所以就要使用核函数。

        【数之道26】SVM支持向量机-核技巧Kernel Trick详解(多项式核函数,无限维度高斯核函数)_哔哩哔哩_bilibili

        

常用的核函数

        

        他们就像一个武器套装,能够方便针对软间隔对偶问题实现升维操作。

 那么为什么升维就能解决不可分的问题呢?

        希尔伯特空间的元素是函数,因此可以看成无穷维度的向量。

        

 核技巧的作用

        映射到高维空间。

        大大减少了计算量,尤其是对于高维向量的相乘操作,同时也不需要额外存储中间的结果。

        不仅限于SVM,实际上 只要存在着 xi ,xj 的最优化问题。

        


 6、非线性SVM —— 核函数

        核函数:是映射关系的内积

        映射函数本身仅仅是一种映射关系,并没有增加维度的特性,不过可以利用核函数的特性,构造可以增加维度的核函数,这通常是我们希望的。

        要注意,核函数和映射没有关系。核函数只是用来计算映射到高维空间之后的内积的一种简便方法!

        一般英文文献对Kernel有两种提法,一是Kernel Function,二是Kernel Trick。从Trick一词中就可以看出,这只是一种运算技巧而已,不涉及什么高深莫测的东西。

        核技巧(kernel trick)的作用,一句话概括的话,就是降低计算的复杂度,甚至把不可能的计算变为可能。

多项式核函数

         

        以下将说明,为什么这个核函数相当于引入了多项式的特征。

        为了推导方便,此处使用x,y

                

                

        

高斯核函数

        

        也叫 RBF核函数、径向基函数

        Radial Basic Function Kernel

        

        则根据下图可知,当 γ 越大的时候,映射的高斯函数就越发陡峭。

                

        在做高斯核映射时,需要选择地标。也就是下图中公式里的 y。

        

        每个数据点都可以当做地标。

        所以有多少个数据就会映射出多少个维度。

        假定现在有m个维度为n的数据,则高斯核就可以将其映射成mxm维的数据。

        当m非常大的时候,高斯核的运算效率其实很低,但当m并不大甚至小于n的时候,使用核函数就会变得非常高效了。(?存疑 核函数不是升维吗?)

存疑(以下为GPT解答)

在使用高斯核函数进行样本处理时,将维度缩减是一种常见的降维技术。核函数能够将原始样本从n维映射到m维(m < n),从而达到降低样本维度的目的。

为什么在m小于n的情况下仍然要使用核函数呢?这是因为核函数的作用不仅仅是降维,还能够通过非线性映射将样本从原始空间映射到一个更高维的特征空间,从而更好地分离不同类别的样本。即使在降维的过程中,核函数也能够通过引入额外的非线性维度来提高分类性能。

具体来说,当m小于n时,使用核函数的优势在于:

  1. 非线性映射:核函数通过非线性映射将样本从原始空间映射到一个更高维的特征空间,可以更好地分离不同类别的样本。

  2. 解决线性不可分问题:在原始空间中,某些样本可能是线性不可分的,但在高维特征空间中可能是线性可分的。通过核函数的映射,可以将原始空间中线性不可分的样本转换为高维特征空间中线性可分的样本,从而提高分类的准确性。

  3. 计算效率:尽管高斯核在特征空间中引入了更高的维度,但由于核函数的计算与原始样本维度无关,因此计算效率并不受到影响。相反,通过核技巧,我们可以在低维空间中计算高维特征空间的内积,避免了显式地进行高维计算,从而提高了计算效率。

总之,即使在m小于n的情况下,使用核函数仍然能够发挥作用,通过非线性映射和解决线性不可分问题来提高分类性能,并且可以在计算效率上获得一定的优势。


 7、非线性SVM代码实现

如何选择核函数?

当特征多且接近样本数量,可直接选择线性核SVM。

当特征数少,样本数正常,推荐选用高斯核函数。

当特征数少,样本数很大,建议选择多项式核函数,切记阶数不能过高,否则复杂度过高,难以计算。

多项式特征解决非线性问题

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
x, y = make_moons(n_samples=100, noise=0.2, random_state=0)

plt.scatter(x[:,0], x[:,1], c = y)
plt.show()

from sklearn.svm import LinearSVC

lsvc = LinearSVC()
lsvc.fit(x,y)

LinearSVC

LinearSVC()
def decision_boundary_plot(X, y, clf):
    axis_x1_min, axis_x1_max = X[:,0].min() - 1, X[:,0].max() + 1
    axis_x2_min, axis_x2_max = X[:,1].min() - 1, X[:,1].max() + 1
    
    x1, x2 = np.meshgrid( np.arange(axis_x1_min,axis_x1_max, 0.01) , np.arange(axis_x2_min,axis_x2_max, 0.01))
    z = clf.predict(np.c_[x1.ravel(),x2.ravel()])
    z = z.reshape(x1.shape)
    
    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#F5B9EF','#BBFFBB','#F9F9CB'])

    plt.contourf(x1, x2, z, cmap=custom_cmap)
    plt.scatter(X[:,0], X[:,1], c=y)
    plt.show()
decision_boundary_plot(x,y,lsvc)

from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.pipeline import Pipeline
poly_svc = Pipeline([
    ("poly", PolynomialFeatures(degree=3)),
    ("std_scaler", StandardScaler()),
    ("linearSVC", LinearSVC())
])
poly_svc.fit(x,y)

Pipeline

Pipeline(steps=[('poly', PolynomialFeatures(degree=3)),
                ('std_scaler', StandardScaler()), ('linearSVC', LinearSVC())])

PolynomialFeatures

PolynomialFeatures(degree=3)

StandardScaler

StandardScaler()

LinearSVC

LinearSVC()
decision_boundary_plot(x,y,poly_svc)

核函数解决非线性问题

from sklearn.svm import SVC
poly_svc = Pipeline([
    ("std_scaler", StandardScaler()),
    ("polySVC", SVC(kernel='poly', degree=3, coef0=5 ))
])
poly_svc.fit(x,y)

Pipeline

Pipeline(steps=[('std_scaler', StandardScaler()),
                ('polySVC', SVC(coef0=5, kernel='poly'))])

StandardScaler

StandardScaler()

SVC

SVC(coef0=5, kernel='poly')
decision_boundary_plot(x,y,poly_svc)

rbf_svc = Pipeline([
    ("std_scaler", StandardScaler()),
    ("rbfSVC", SVC(kernel='rbf', gamma=0.1 ))
])
rbf_svc.fit(x,y)
decision_boundary_plot(x,y,rbf_svc)

rbf_svc = Pipeline([
    ("std_scaler", StandardScaler()),
    ("rbfSVC", SVC(kernel='rbf', gamma=10 ))
])
rbf_svc.fit(x,y)
decision_boundary_plot(x,y,rbf_svc)

rbf_svc = Pipeline([
    ("std_scaler", StandardScaler()),
    ("rbfSVC", SVC(kernel='rbf', gamma=100 ))
])
rbf_svc.fit(x,y)
decision_boundary_plot(x,y,rbf_svc)


 8、SVM解决回归任务

       

       

        解决回归任务则是希望落在 margin 里的样本点越多越好。

        

         

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(666)
x = np.random.uniform(-3,3,size=100)
y = 0.5 * x**2 +x +2 +np.random.normal(0,1,size=100)
X = x.reshape(-1,1)
plt.scatter(x,y)
plt.show()

from sklearn.svm import LinearSVR
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
def StandardLinearSVR(epsilon=0.1):
    return Pipeline([
        ("std_scaler",StandardScaler()),
        ("linearSVR",LinearSVR(epsilon=epsilon))
    ])
svr = StandardLinearSVR()
svr.fit(X,y)
y_predict = svr.predict(X)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict[np.argsort(x)],color='r')
plt.show()

svr.score(X,y)
0.48764762540009954
from sklearn.svm import SVR
def StandardSVR(epsilon=0.1):
    return Pipeline([
        ('std_scaler',StandardScaler())
        ,('SVR',SVR(kernel='rbf',epsilon=epsilon))
    ])
svr = StandardSVR()
svr.fit(X,y)
y_predict = svr.predict(X)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict[np.argsort(x)],color='r')
plt.show()

svr.score(X,y)
0.8138647789256847


9、SVM的优缺点及用条件

        优点:

                1、高效处理非线性数据

                2、L2正则化特性,良好的泛化能力

                3、解决分类 SVC 和回归 SVR 问题

                4、稳定性

        缺点:

                1、选择合适的核函数比较困难

                2、大量内存需求,必须将所有的支持向量都存储在内存中

                3、大数据集上训练时间长

                4、难以解释

        适用条件:小样本数据、非线性数据


参考

核函数 高斯核函数,线性核函数,多项式核函数-CSDN博客

对SVM中核函数的理解_核函数优缺点-CSDN博客

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

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

相关文章

【Docker光速搞定深度学习环境配置!】

你是否还在用压缩包打包你的代码&#xff0c;然后在新的机器重新安装软件&#xff0c;配置你的环境&#xff0c;才能跑起来&#xff1f; 特别有这样的情况&#xff1a;诶&#xff0c;在我电脑跑的好好的&#xff0c;怎么这里这么多问题&#xff1f; 当项目比较简单的时候&am…

接口自动化测试框架【AIM】

最近在做公司项目的自动化接口测试&#xff0c;在现有几个小框架的基础上&#xff0c;反复研究和实践&#xff0c;搭建了新的测试框架。利用业余时间&#xff0c;把框架总结了下来。 AIM框架介绍 AIM&#xff0c;是Automatic Interface Monitoring的简称&#xff0c;即自动化…

Idea代码走查工具FindBus使用以及缺陷分析

1. 简介 Findbugs是一个静态分析工具&#xff0c;它检查类或者jar文件&#xff0c;将字节码与一组缺陷模式进行对比以发现可能的问题。利用这个工具可以在不实际运行程序的情况下对软件进行分析。可以帮助改进代码质量。Findbugs提供了方便操作的可视化界面&#xff0c;同时&a…

[计网00] 计算机网络开篇导论

目录 前言 计算机网络的概念 计算机网络的分层 计算机网络的分类 网络的标准化工作和相关组织 计算机网络的性能指标 前言 计算机网络在我们的日常生活中无处不在 在网络会有各种各样的协议和封装 保证我们的信息完整,无误的在各个客户端之前传输 计算机网络的概念 四…

Unity与Android交互通信系列(2)

在上一篇文章中&#xff0c;我们介绍了Unity和Android交互通信的原理及在Unity中直接调用Java代码的方式&#xff0c;但没有给出代码示例&#xff0c;下面通过实际例子演示上篇文章中AndroidJavaClass、AndroidJavaObject两个类的基本用法&#xff0c;由于交互通信涉及到两端&a…

1KW逆变器UPS纯正弦波方案

硬件方案--110V方案 本套逆变器方案分110V输出以及220V输出&#xff0c;电池最大电压是48V&#xff0c;包括了LCD。110V方案主控使用的dsp是MICROCHIP(美国微芯)的dsPIC33FJ16GS504芯片&#xff0c;ACDC控制器是TOP250YN&#xff0c;运算放大器包含LM358、MCP6022&#xff0c;电…

Spring IOC 原理(二)

Spring IOC 原理 概念 Spring 通过一个配置文件描述 Bean 及 Bean 之间的依赖关系&#xff0c;利用 Java 语言的反射功能实例化Bean 并建立 Bean 之间的依赖关系。 Spring 的 IoC 容器在完成这些底层工作的基础上&#xff0c;还提供了 Bean 实例缓存、生命周期管理、 Bean 实…

【数据结构复习之路】图(严蔚敏版)两万余字超详细讲解

专栏&#xff1a;数据结构复习之路 复习完上面四章【线性表】【栈和队列】【串】【数组和广义表】【树和二叉树】&#xff0c;我们接着复习 图&#xff0c;这篇文章我写的非常详细且通俗易懂&#xff0c;看完保证会带给你不一样的收获。如果对你有帮助&#xff0c;看在我这么辛…

我愿称其为神器-vscode-vim自动切换输入法

我愿称其为神器-vscode-vim自动切换输入法 smartinput在linux下无效 首先在 文件->首选项->配置 找到setting.json 在这个github中给出了详细的config.json配置文件 https://github.com/daipeihust/im-select/blob/master/README_CN.md 因为我使用的是ibus,在将set…

javaSE学习-3-数组的定义与使用

1 数组的创建及初始化 int[] array1 new int[10]; // 创建一个可以容纳10个int类型元素的数组 double[] array2 new double[5]; // 创建一个可以容纳5个double类型元素的数组 String[] array3 new double[3]; // 创建一个可以容纳3个字符串元素的数组 2 基本类型变量与…

新人做自动化测试,记住这5点涨薪指日可待...

关于新人如何做好自动化测试&#xff0c;以下是我个人的一些思考。 01、测试基础的重要性 作为一名测试新人&#xff0c;测试基础非常非常重要。这里说的基础&#xff0c;不仅仅是什么是软件测试、软件测试的目的&#xff0c;而是测试用例的设计能力。 因工作的原因&#xf…

教育机构小程序管理系统的全方位优化

随着互联网的快速发展&#xff0c;线上教育也日益受到人们的关注和欢迎。为了满足广大学生和家长的需求&#xff0c;教育机构纷纷开发出自己的小程序管理系统。本文将详细介绍如何使用乔拓云平台&#xff0c;一键开发出自己的教育机构小程序管理系统。 1.进入乔拓云后台 首先&…

记一次java for循环改造多线程的操作

背景 今天在开发质量平台时需要获取某些数据&#xff0c;要请求公司某个工程的OpenAPI接口A。此接口为返回通用数据的接口&#xff0c;且接口本身的RT都在2&#xff5e;3秒之间。使用该接口&#xff0c;需要进行两次循环获取&#xff0c;然后对返回数据进行处理组装&#xff0…

弹窗“由于找不到xinput1_3.dll,无法继续执行代码”的几种解决方法分享

日常中&#xff0c;我们在使用电脑过程中&#xff0c;偶尔会遇到一些错误提示“由于找不到xinput1_3.dll,无法继续执行代码”&#xff0c;这个报错会让程序无法正常运行的情况。那么&#xff0c;xinput1_3.dll到底是什么&#xff1f;它丢失会对计算机产生什么影响呢&#xff1f…

健康卤味思想引领市场新潮流,卤味市场迎来健康变革

健康卤味思想正在逐渐渗透到卤味市场中&#xff0c;引领着消费者对于卤味产品的选择和需求。这一变革不仅为消费者带来了更加健康、美味的卤味产品&#xff0c;也为卤味市场注入了新的活力。 一、健康卤味思想的兴起 随着消费者对于健康饮食的关注度不断提高&#xff0c;健康卤…

频谱论文:基于张量Tucker分解的频谱地图构建算法

#频谱# [1]陈智博,胡景明,张邦宁 郭道省.(2023).基于张量Tucker分解的频谱地图构建算法.电子与信息学报(11),4161-4169. &#xff08;陆军工程大学&#xff09; 研究内容 将动态电磁环境的时变频谱地图建模为3维频谱张量&#xff0c;通过张量Tucker分解提取出具有物理意义的核…

Linux---Ubuntu软件卸载

1. 软件卸载的介绍 Ubuntu软件卸载有两种方式: 离线安装包的卸载(deb 文件格式卸载&#xff09;在线安装包的卸载(apt-get 方式卸载) 2. deb 文件格式卸载 命令格式: sudo dpkg –r 安装包名 -r 选项表示安装的卸载 dpkg 卸载效果图: 3. apt-get 方式卸载 命令格式: …

svn 安装

安装系统 ubuntu 22 安装命令&#xff1a; sudo apt-get install subversion 创建第一个工程&#xff1a; 创建版本库、项目 1、先创建svn根目录文件夹 sudo mkdir /home/svn 2、创建项目的目录文件夹 sudo mkdir /home/svn/demo_0 svnadmin create /home/svn/demo_0 配置&a…

【Redis】五、Redis持久化、RDB和AOF

文章目录 Redis持久化一、RDB&#xff08;Redis DataBase&#xff09;触发机制如何恢复rdb文件 二、AOF&#xff08;Append Only File&#xff09;三、扩展 Redis持久化 面试和工作&#xff0c;持久化都是重点&#xff01; Redis 是内存数据库&#xff0c;如果不将内存中的数据…

单元测试计划、用例、报告、评审编制模板

单元测试支撑文档编制模板&#xff0c;具体文档如下&#xff1a; 1. 单元测试计划 2. 单元测试用例 3. 单元测试报告 4. 编码及测试评审报告 软件项目相关资料全套获取&#xff1a;软件项目开发全套文档下载-CSDN博客 1、单元测试计划 2、单元测试用例 3、单元测试报告 4、编码…