当前位置: 首页 > news >正文

关于支持向量机的一份介绍

在这篇文章中,我将介绍与支持向量机有关的东西,我们知道支持向量机主要分两类,就是线性支持向量机核支持向量机这两种(当然还有其他的,如多类支持向量机、 Nu-Support Vector Regression等),因此我将介绍它俩的联系与区别,但首先将会详细介绍它俩有关的知识及python实现。

一、 线性支持向量机

1.1 概念

线性支持向量机(Linear Support Vector Machine, Linear SVM)是一种用于分类和回归分析的监督学习模型,特别适用于数据在特征空间中是线性可分的情况。

线性SVM原本可用于进行二分类任务,但如果进行“一对多”等处理后,也可进行多分类任务。

下图就是iris数据集进行SVM后的图像:

1.2 数学模型

关于线性SVM的数学模型可以分为三来来看,分别是决策函数、原问题以及对偶问题。

(1)决策函数

线性SVM的决策函数是用来预测新输入样本所属类别的函数。在求解线性SVM的对偶问题之后,我们得到一系列拉格朗日乘子 αi,这些乘子用于构建最终的决策函数。其中拉格朗日乘子是对偶问题里的,暂且不谈。

我们知道SVM是用于划分类别的,所以我们可以用一个线性组合来描述:

我们将其记为:(W,b)。这样就会诞生一个空间中任意点到超平面的距离r。

然后我们假设这个超平面能正确分类样本,即方才的线性组合>0时,有yi = +1;反之小于0时,有yi = -1。

那么我将这个线性组合重写下就是:

如果用sign函数来表示,可以是这样:

(2)原问题

首先我们知道SVM问题就是一个优化问题,旨在数据线性可分的情况下去寻找一个最优的超平面将之划分,并使间隔最大化。

其中,距离超平面最近的几个训练样本使得其决策函数成立,它们就被称为是“支持向量”。而两个异类支持向量到超平面的和就是“间隔”。

为了间隔最大化,就有了原问题,所以可以写出以下式子:

(3)对偶问题

关于刚才的问题,我们要知道如果直接就用那些式子去找最优超平面会很复杂,所以我们我们需要对偶问题来帮助我们。而在对偶问题中就需要拉格朗日乘子,关于这个乘子,我们则需要了解下拉格朗日函数。

假如我们有目标函数f(x,y),我们要找到它的极值,但同时又存在一个g(x,y)=c(c为常数)来对其进行约束的话,我们就可以构造一个新函数来解决,这个新函数就是拉格朗日函数,表达式如下:

其中的λ(lambda)就是拉格朗日乘子。

而要解决这个式子就需要让其梯度为0,如下:

然后有:

最后就可分别求得x、y、λ的值了。

那么我们就来求取在对偶条件下的线性SVM的模型:

我们已知拉格朗日函数的形式,那么我们将相应的函数带入即可。首先是目标函数,因为我们要求取一个最优超平面,所以将刚才的原问题中的模型带入到f(x,y)的位置;然后是约束函数,因为要让间隔最大化,所以需要约束条件如此确保间隔的最大化;接下来是常数C,一般在没有先验条件的前提下,我们都会使用1作为默认值。(当C越大,模型越倾向于减少分类错误,C越小,模型的泛化能力越强)

那么就有了最后的模型:

1.3 python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score# 加载Iris数据集
iris = load_iris()
X = iris.data[:, :2]  # 只取前两个特征:花萼长度和花萼宽度
y = iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 创建SVM模型
svm = SVC(kernel='linear', C=1)
# 训练模型
svm.fit(X_train, y_train)
y_pre = svm.predict(X_test)
accuracy = accuracy_score(y_test, y_pre)
print("Accuracy is: {}".format(accuracy))# 绘制决策边界
def plot_decision_boundary(model, X, y):# 创建网格x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01),np.arange(y_min, y_max, 0.01))# 预测网格中的类别Z = model.predict(np.c_[xx.ravel(), yy.ravel()])Z = Z.reshape(xx.shape)# 绘制背景色plt.contourf(xx, yy, Z, alpha=0.8)# 绘制训练数据点markers = ['o', 's', '^']for i, label in enumerate(np.unique(y)):plt.scatter(X[y == label, 0], X[y == label, 1], marker=markers[i], label=iris.target_names[label])# 绘制决策边界plt.contour(xx, yy, Z, colors='k', levels=[-1, 0, 1], linestyles=['--', '-', '--'])# 图像设置plt.title('Iris Dataset with SVM Decision Boundary')plt.xlabel('Sepal Length (cm)')plt.ylabel('Sepal Width (cm)')plt.legend()plt.show()# 绘制决策边界
plot_decision_boundary(svm, X, y)

二、 核支持向量机

1.1 概念

核SVM利用核函数(Kernel Function)将输入数据映射到一个更高维的空间,在这个高维空间中,原本非线性可分的数据变得线性可分。

同样的,我给出一个用iris进行SVM分类后的图像,如下图:(其代码随后给出)

1.2 数学模型

我们来看核SVM的数学模型,其基本形式与线性的十分相似,我们令Φ(x)来表示将x映射后的特征向量,于是之前的模型就发生了改变,便成为:f(x) = w^T\phi (x)+b的形式。然后其对偶问题也就变为:

最后经过一些重写、化简等就变为:

f(x)=w^T\phi (x)+b \\=\sum_{i=1}^{m} \alpha i yi\phi (x)+b\\=\sum_{i=1}^{m}\alpha i yi\kappa (x,xi)+b

而这里的函数κ()就是“核函数”(kernal function)。

而关于核函数其实存在多种选择,因为我自己也对其不够了解,所以只在此给出西瓜书上的常用核函数表,如下:

1.3 联系

在我们初步了解二者的概念后,我们就可以知道,其实KSVM(核SVM)就是线性SVM在原本处理不了的非线性数据上做出的一个拓展,旨在增加维度而能实现让SVM进行分类。

1.4 区别

适用范围:在线性SVM中,它适用于处理线性可分的数据集,即可以通过一个超平面(在二维空间中是一条直线,在高维空间中是一个超平面)来分隔不同类别的数据点;而KSVM中,它适用于处理非线性可分的数据集,即数据不能通过一个简单的超平面来分隔。在这种情况下,数据可能需要被映射到一个更高维的空间,才能找到一个合适的分隔超平面。

计算复杂度:线性SVM的复杂度相对较低,而KSVM因为核函数的缘故,计算复杂度较高。

实际应用:在线性可分数据集上,线性SVM通常比KSVM更快并且更简单。例如,在文本分类或一些简单的图像识别任务中,数据可能是线性可分的;在非线性可分数据集上,KSVM能够更好地捕捉数据中的复杂关系。例如,在手写数字识别、生物信息学等领域,数据通常是非线性可分的,KSVM能够提供更高的准确率。

1.5 python代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.svm import SVC
from mpl_toolkits.mplot3d import Axes3D# 加载Iris数据集
iris = datasets.load_iris()
X = iris.data[:, :3]  # 使用前三个特征
y = iris.target
# 使用线性核的支持向量机
svm = SVC(kernel='linear')
svm.fit(X, y)
# 创建3D图形
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')  # 使用add_subplot代替Axes3D
ax.view_init(elev=-152, azim=-26)  # 设置视角
# 掩码
mask_0 = y == 0
mask_1 = y == 1
mask_2 = y == 2
# 绘制散点图
ax.scatter(X[mask_0, 0], X[mask_0, 1], X[mask_0, 2], c='b', s=60, label="Setosa")
ax.scatter(X[mask_1, 0], X[mask_1, 1], X[mask_1, 2], c='r', marker='^', s=60, label="Versicolour")
ax.scatter(X[mask_2, 0], X[mask_2, 1], X[mask_2, 2], c='g', marker='s', s=60, label="Virginica")
# 设置坐标轴标签
ax.set_xlabel("Sepal length")
ax.set_ylabel("Sepal width")
ax.set_zlabel("Petal length")
# 添加图例
ax.legend()
# 绘制决策平面
w = svm.coef_[0]
a = -w[0] / w[2]
b = -w[1] / w[2]
xx, yy = np.meshgrid(np.linspace(X[:, 0].min(), X[:, 0].max(), 50),np.linspace(X[:, 1].min(), X[:, 1].max(), 50))
zz = (-svm.intercept_[0] - a * xx - b * yy) / w[2]# 画出平面
surf = ax.plot_surface(xx, yy, zz, rstride=1, cstride=1, color='none',alpha=0.3, edgecolor='darkblue')
# 显示图形
plt.show()

三、 补足

此外,我们会发现在分类时偶尔会有些数据点分类错误或是在间隔内,那么我们就可以称它为“软间隔”,那么我可以在这里完整描述下关于软间隔的含义:它适用于不完全线性可分的数据集,允许一定的误差。并通过调整C来控制惩罚程度,以达到最好的泛化能力。而于此相对的,硬间隔的含义就是:适用于 完全线性可分的数据集,不允许任何训练样本出现在间隔内或是被错误地分类。

因为在现实中大多不能做到硬间隔的分类,所以我们我们需要软间隔,更需要关于它而对原有的SVM模型进行修改,比如加入损失函数,引入松弛变量等,这样就能得到常说的“软间隔SVM”。

SVM处了能处理分类问题还能进行回归,这样就是“支持向量回归”了,即Support Vector Regression。

关于SVM的东西还有很多,我将在之后继续介绍。

此上

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Ubuntu 20.04安装pycharm2022及配置快捷方式
  • 09 Shell Scriptfor循环结构语句
  • 【乐企-业务篇】OFD对应xml实体对象定义
  • uniapp快速入门教程,内容来源于官方文档,仅仅记录快速入门需要了解到的知识点
  • 分苹果 - 华为OD统一考试(E卷)
  • Flask 第十二课 -- 错误处理
  • 末端回路漏电监测仪为何不可或缺?
  • Qt窗口——QDockWidget
  • git reflog
  • 【Linux】yum、vim、gcc使用(超详细)
  • Go语言grequests库并发请求的实战案例
  • 基于SSM的宿舍管理系统的设计与实现 (含源码+sql+视频导入教程+文档+PPT)
  • 【Unity】对象池 - 未更新完
  • Zabbix 部署----安装 Zabbix(监控服务器)
  • 分布式事务seata
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • 07.Android之多媒体问题
  • echarts花样作死的坑
  • iOS 系统授权开发
  • mysql innodb 索引使用指南
  • OSS Web直传 (文件图片)
  • TypeScript实现数据结构(一)栈,队列,链表
  • 创建一个Struts2项目maven 方式
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • AI算硅基生命吗,为什么?
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • Spring Batch JSON 支持
  • 昨天1024程序员节,我故意写了个死循环~
  • ​queue --- 一个同步的队列类​
  • # centos7下FFmpeg环境部署记录
  • #{}和${}的区别是什么 -- java面试
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • $.ajax()
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (附源码)计算机毕业设计大学生兼职系统
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (一)Dubbo快速入门、介绍、使用
  • (转)Scala的“=”符号简介
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .net 4.0发布后不能正常显示图片问题
  • .net core webapi 大文件上传到wwwroot文件夹
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .Net FrameWork总结
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .NET的微型Web框架 Nancy
  • .NET中winform传递参数至Url并获得返回值或文件
  • //TODO 注释的作用
  • :class的用法及应用
  • [ 蓝桥杯Web真题 ]-Markdown 文档解析
  • [BZOJ2208][Jsoi2010]连通数