基于sklearn的机器学习 — 支持向量机(SVM)

支持向量机(SVM:support vector machine)另一种功能强大、应用广泛的学习算法,可应用于分类、回归、密度估计、聚类等问题。SVM可以看作是感知器(可被视为一种最简单形式的前馈神经网络,是一种二元线性分类器)的扩展,与逻辑回归相比,支持向量机在学习复杂的非线性方程时提供了一种更为清晰,更加强大的方式。

SVM是一种监督式的学习方法,用统计风险最小化的原则来估计一个分类的超平面(hyperplane) ,其基础的概念非常简单,就是找到一个决策边界(decision boundary) ,让两类之间的边界(margins) 最大化,使其可以完美地分隔开来。

超平面(hyperplane) 是n维空间中的n - 1个子空间。例如,想要划分一个二维空间,需要使用一维超平面(即一条线),划分三维空间,需要使用二维超平面(即一张面),超平面只是将这一概念推广到 n 维空间。

不同维度下的超平面

支持向量(support vectors) 指的是最接近超平面或超平面上的数据点,它们影响超平面的位置和方向。

边界(margin) 的定义是:分离超平面(决策边界)与最接近该超平面的训练实例(即支持向量)之间的距离。

支持向量与边界

1. 支持向量机的类型

支持向量机有两种类型:

  1. 线性支持向量机
  2. 非线性支持向量机

线性与非线性可分问题

1.1 线性支持向量机

线性SVM适用于训练数据近似线性可分的情况,在这种情况下,存在一个超平面可以将不同类的样本完全划分开。

使用支持向量分类器 (SVC:support vector classifier) 查找使类之间的边距最大化的超平面,scikit-learn 的 LinearSVC实现了一个简单的 SVC。

下面基于鸢尾花数据集,在二维空间上对两组数据进行分类,然后绘制超平面:

# Load libraries  
from sklearn.svm import LinearSVC 
from sklearn import datasets 
from sklearn.preprocessing import StandardScaler 
import numpy as np  # Load data with only two classes and two features 
iris = datasets.load_iris() 
features = iris.data[:100,:2] 
target = iris.target[:100]  # Standardize features  
scaler = StandardScaler() 
features_standardized = scaler.fit_transform(features)  # Create support vector classifier 
svc = LinearSVC(C=1.0)  # Train model  
model = svc.fit(features_standardized, target)# Plot data points and color using their class  
color = ["red" if c == 0 else "black" for c in target] 
plt.scatter(features_standardized[:,0], features_standardized[:,1], c=color)# Create the hyperplane 
w = svc.coef_[0] 
a = -w[0] / w[1] 
xx = np.linspace(-2.5, 2.5) 
yy = a * xx - (svc.intercept_[0]) / w[1]# Plot the hyperplane 
plt.plot(xx, yy) 
plt.xlabel('Sepal length [standardized]')
plt.ylabel('Sepal width [standardized]')
plt.tight_layout()
plt.legend()
plt.show()

1.2 非线性支持向量机

对于线性不可分的问题,SVM可以借助核方法(Kernel methods)将样本从低维空间 (输入空间) 映射到高维空间 (特征空间) 来进行线性划分,从而解决非线性分类问题。

使用核方法对非线性数据进行分类的过程

上图展示了如何通过将数据投影到更高维度的空间来实现非线性可分数据的分类。

图中显示了一个二维平面上的数据集。红色圆点和蓝色方块代表两类数据,数据是非线性可分的,即没有一条直线可以将两类数据完美地分开。

通过使用映射函数( ϕ \phi ϕ)将原始的二维数据投影到三维空间,在这个新的高维空间中,原本在二维空间中非线性可分的数据,现在在三维空间中变得线性可分。

在三维空间中,我们可以学习一个线性分类器(比如一个超平面)来将两类数据分开。

通过逆映射函数( ϕ − 1 \phi^{-1} ϕ1),将三维空间中的决策边界投影回原始的二维空间,投影回二维空间后的决策边界不再是直线,而是曲线,这条曲线能很好地将两类数据分开。

通过核方法可以将非线性可分的数据映射到高维空间,在高维空间中应用线性分类器,然后将高维空间中的分类结果逆映射回原始空间,从而实现非线性分类。

下面通过一个简单的例子来理解,首先创建一个非线性可分的数据集:

# Load libraries  
from sklearn.svm import SVC 
from sklearn import datasets 
from sklearn.preprocessing import StandardScaler 
import numpy as np  # Set randomization seed 
np.random.seed(0)  # Generate two features  
features = np.random.randn(200, 2)  # Use an XOR gate to generate 
# linearly inseparable classes  
target_xor = np.logical_xor(features[:, 0] > 0, features[:, 1] > 0) 
target = np.where(target_xor, 0, 1)  # Create a support vector machine with a radial basis function kernel 
svc = SVC(kernel="rbf", random_state=0, gamma=1, C=1)  # Train the classifier  
model = svc.fit(features, target)

接着编写一个可以绘制二维空间的观测值和决策边界超平面的函数:

from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
def plot_decision_regions(X, y, classifier, test_idx=None,  resolution=0.02):  
# setup marker generator and color map  markers = ('o', 's', '^', 'v', '<') colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')cmap = ListedColormap(colors[:len(np.unique(y))])x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1  x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1  xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),  np.arange(x2_min, x2_max, resolution))  lab = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)  lab = lab.reshape(xx1.shape)  plt.contourf(xx1, xx2, lab, alpha=0.3, cmap=cmap)  plt.xlim(xx1.min(), xx1.max())  plt.ylim(xx2.min(), xx2.max())for idx, cl in enumerate(np.unique(y)):  plt.scatter(x=X[y == cl, 0],  y=X[y == cl, 1],  alpha=0.8,  c=colors[idx],  marker=markers[idx],  label=f'Class {cl}',  edgecolor='black')if test_idx:  # plot all examples  X_test, y_test = X[test_idx, :], y[test_idx]  plt.scatter(X_test[:, 0], X_test[:, 1], c='none', edgecolor='black', alpha=1.0,  linewidth=1, marker='o',  s=100, label='Test set')

上文创建的非线性数据集包含两个特征(即两个维度)和一个包含每个观测值类别的目标向量。

如果使用线性内核的支持向量机分类器进行分类:

# Create support vector classifier with a linear kernel 
svc_linear = SVC(kernel="linear", random_state=0, C=1)  # Train model  
svc_linear.fit(features, target)  # Plot observations and hyperplane  
plot_decision_regions(features, target, classifier=svc_linear) 
plt.legend()
plt.tight_layout()
plt.show()

可以看到,线性超平面的划分效果很差

现在将线性核函数换成径向基核函数,训练一个新模型:

# Create a support vector machine with a radial basis function kernel 
svc = SVC(kernel="rbf", random_state=0, gamma=1, C=1)# Train the classifier  
model = svc.fit(features, target)# Plot observations and hyperplane  
plot_decision_regions(features, target, classifier=svc) 
plt.legend()
plt.tight_layout()
plt.show()

划分结果为:

通过使用径向基核函数,可以创建一个更好的决策边界,这就是在支持向量机中使用核方法的目的。

在 scikit-learn中,我们可以通过kernel参数来选择要使用的核函数。

选择内核后,我们需要指定适当的内核选项,例如多项式内核(polynomial kernels)中的 d值,以及径向基函数内核中的γ值,还需要设置惩罚参数C

在训练模型时,大多数情况下我们应该将所有这些参数都视为超参数,并使用模型选择技术来确定它们的组合值,以产生性能最佳的模型。

2. 计算预测概率

许多监督学习算法都使用概率估计来预测类别。SVC 使用超平面来创建决策区域,并不能自然地输出观测值属于某个类别的概率估计值。不过,我们可以输出经过校准的类别概率。

在具有两个类别的 SVC 中,可以使用普拉特缩放(Platt scaling)法,即首先训练 SVC,然后训练一个单独的交叉验证逻辑回归,将 SVC 输出映射为概率:

P ( y = 1 ∣ x ) = 1 1 + e ( A × f ( x ) + B ) P(y=1\mid x)=\frac{1}{1+e^{(A\times f(x)+B)}} P(y=1x)=1+e(A×f(x)+B)1

式中:A 和 B 是参数向量, f ( x ) f(x) f(x)是第 i 个观测值距超平面的有符号距离。当我们有两个以上的类时,将使用普拉特缩放的扩展。

从更实际的角度来看,创建预测概率有两个主要问题:

  1. 由于我们要通过交叉验证来训练第二个模型,因此生成预测概率会大大增加训练模型所需的时间。

  2. 由于预测概率是通过交叉验证创建的,因此它们可能不总是与预测类别相匹配。也就是说,一个观测值可能被预测为类别 1,但预测为类别1的概率却小于 0.5。

在 scikit-learn 中,预测概率必须在训练模型时生成,我们可以将 SVC 的probability参数设置为 True,模型训练完成后,我们可以使用 predict_proba输出每个类别的估计概率。

# Load libraries  
from sklearn.svm import SVC 
from sklearn import datasets 
from sklearn.preprocessing import StandardScaler 
import numpy as np  # Load data  
iris = datasets.load_iris() 
features = iris.data 
target = iris.target  # Standardize features  
scaler = StandardScaler() 
features_standardized = scaler.fit_transform(features)  # Create support vector classifier object  
svc = SVC(kernel="linear", probability=True, random_state=0)  # Train classifier  
model = svc.fit(features_standardized, target)  # Create new observation  
new_observation = [[.1, .2, .3, .4]]  # View predicted probabilities  
model.predict_proba(new_observation)  

3. 识别支持向量

支持向量机之所以得名,是因为超平面是由相对较少的观测数据决定的,这些观测数据被称为支持向量。

直观地说,超平面就是由这些支持向量所"承载 ",因此,这些支持向量对我们的模型非常重要。

如果我们从数据中移除一个不属于支持向量的观测值,模型不会发生变化;但如果我们移除一个支持向量,超平面就不会有最大边界。

因此有时需要确定哪些观测值是决策超平面的支持向量。

在我们基于鸢尾花数据集训练出SVC后,scikit-learn提供了许多用于识别支持向量的选项,可以使用support_vectors_来输出模型中的支持向量:

# Load libraries  
from sklearn.svm import SVC 
from sklearn import datasets 
from sklearn.preprocessing import StandardScaler 
import numpy as np  # Load data with only two classes 
iris = datasets.load_iris() 
features = iris.data[:100,:] 
target = iris.target[:100]  # Standardize features  
scaler = StandardScaler() 
features_standardized = scaler.fit_transform(features)  # Create support vector classifier object 
svc = SVC(kernel="linear", random_state=0)  # Train classifier  
model = svc.fit(features_standardized, target)# View support vectors 
model.support_vectors_

结果有四个支持向量:

array([[-0.5810659 ,  0.42196824, -0.80497402, -0.50860702],[-1.52079513, -1.67737625, -1.08231219, -0.86427627],[-0.89430898, -1.4674418 ,  0.30437864,  0.38056609],[-0.5810659 , -1.25750735,  0.09637501,  0.55840072]])

另外,也可以使用support_查看支持向量的索引:

model.support_  

运行后可得到上述四个支持向量的索引:

array([23, 41, 57, 98])

最后,可以使用n_support_来查找属于每个分类的支持向量的数量:

model.n_support_ 

结果为:

array([2, 2])

4. 不平衡问题

不平衡问题指的是在对样本进行分类过程中,需要更加重视某些类或某些单个样本的情况。

在支持向量机中,C是一个超参数,决定了对错误分类观测值的惩罚,处理不平衡类别的一种方法是按类别对C进行加权:

C k = C × w j C_{k}=C\times w_{j} Ck=C×wj

其中,C是对错误分类的惩罚,wj是与类别j的频率成反比的权重,Ck 是类别k的C值。

一般的想法是增加对错误分类少数类别的惩罚,以防止它们被多数类别 “淹没”。

在 scikit-learn 中,当使用 SVC 时,我们可以通过设置class_weight="balanced"自动设置Ck的值,平衡参数自动对类进行权重,使得:

w j = n k n j w_j=\frac{n}{kn_j} wj=knjn

其中,wj是j类的权重,n是观测值的数量,nj是j类中观测值的数量,k是类的总数。

例如:

# Load libraries  
from sklearn.svm import SVC 
from sklearn import datasets 
from sklearn.preprocessing import StandardScaler 
import numpy as np# Load data with only two classes 
iris = datasets.load_iris() 
features = iris.data[:100,:] 
target = iris.target[:100]  # Make class highly imbalanced by removing first 40 observations 
features = features[40:,:] 
target = target[40:]  # Create target vector indicating if class 0, otherwise 1 
target = np.where((target == 0), 0, 1)  # Standardize features  
scaler = StandardScaler() 
features_standardized = scaler.fit_transform(features)  # Create support vector classifier  
svc = SVC(kernel="linear", class_weight="balanced", C=1.0, random_state=0)  # Train classifier  
model = svc.fit(features_standardized, target)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ 特殊类设计

目录 0.前言 1.设计一个不能被拷贝的类 1.1C98实现 1.2C11实现 2.设计一个只能在堆上创建对象的类 3.设计一个只能在栈上创建对象的类 4.设计一个不能被继承的类 4.1C98实现 4.2C11实现 5.设计只能创建一个对象的类&#xff08;单例模式&#xff09; 5.1设计模式简介 5.2单例模…

Jupyter nbextensions安装与使用

这里写自定义目录标题 Jupyter nbextensions安装与使用安装7以下版本&#xff0c;安装插件包推荐使用的插件 Jupyter nbextensions安装与使用 目前&#xff0c;jupyter版本升级到了7以上版本&#xff0c;导致其界面非常难看&#xff0c;因此&#xff0c;为了重回之前的使用界面…

buuctf-crypto

前言 查找资料的时候,意外翻出之前刷的一些ctf题目,算是简单记录一下,当然因为常用typeo去写md文件,所以其中有很多当时记录的图片都失效了,可惜了 题目1:一眼就解密 ZmxhZ3tUSEVfRkxBR19PRl9USElTX1NUUklOR30 base64解密 flag:flag{THE_FLAG_OF_THIS_STRING} 题目2:MD5 …

全球化浪潮下的数据库革新:嘉里物流 TiDB 实践价值的设想

导读 本文来自 TiDB 社区武汉站——嘉里物流架构团队负责人肖飞老师的演讲《嘉里物流 & TiDB 在全球化业务场景中应用设想》。本次分享探讨了嘉里物流在全球化扩展中&#xff0c;将如何通过 TiDB 的强大功能应对海量数据挑战&#xff0c;优化技术架构&#xff0c;并提升决…

【Linux】详解自定义Shell管道 | 构建简易进程池

目录 续&#xff1a;通信 4 种情况 应用场景 1. 自定义 shell 管道 1. 包含头文件 2. 解析命令函数 详细步骤 3. 执行命令函数 4. 主函数 总结 2. 使用管道实现一个简易版本的进程池 代码结构 代码实现 channel.hpp tasks.hpp main.cc 子进程读取任务&#xff…

十九、虚拟机VMware Workstation(CentOSDebian)的安装

目录 &#x1f33b;&#x1f33b; 一、安装 VMware Workstation1.1 安装 VMware Workstation1.2 虚拟机上安装 CentOS1.3 虚拟机安装 Debian 二、配置Debian方便第三方工具远程连接2.1 配置debian2.2 安装远程SSH工具并连接 一、安装 VMware Workstation 官网下载 本地资源库…

你好! Git——企业级开发模型

企业级开发模型&#xff08;6&#xff09; 一、删除远程分支&#xff0c;git branch -a &#xff08;查看所有本地分支与远程分支&#xff09;还能看到已经删除的分支&#xff0c;怎么解决&#xff1f;二、企业级开发流程2.1 企业级开发流程2.2 系统开发环境 三、Git分支设计模…

RabbitMQ面试题汇总

RabbitMQ面试题 一、RabbitMQ基础1. 什么是RabbitMQ&#xff0c;它的基本架构是怎样的&#xff1f;2. RabbitMQ支持哪些协议&#xff1f;3. 说一下AMQP协议&#xff1f;4. 为什么要使用RabbitMQ&#xff1f;5. MQ的应用场景有哪些&#xff1f;6. 解耦、异步、削峰是什么&#x…

购物系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;商品分类管理&#xff0c;商品信息管理&#xff0c;特价商品管理&#xff0c;用户管理&#xff0c;留言板管理&#xff0c;订单管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&…

uni-app总结

1. <u-form-item label"报废人" ><u--input v-model"model.remark" border"bottom" placeholder"请输入"></u--input> </u-form-item> border"bottom" 报废日期 为了

后端Web开发之Maven

1.java项目构建工具maven介绍 Maven是apache旗下的一个开源项目。Apache软件基金会&#xff0c;成立于1999年7月&#xff0c;是目前世界上最大的最受欢迎的开源&#xff08;源代码开放&#xff09;软件基金会也是一一个专门为支持开源项目而生的非盈利性组织。 apache开源项目…

PDO在CANopen协议同步传输和异步传输

PDO&#xff08;过程数据对象&#xff09;在CANopen协议中有两种主要的传输方式&#xff1a;同步传输和异步传输。这两种方式决定了PDO数据的传输时机和条件。下面分别举例说明这两种传输方式&#xff1a; 1. 同步传输 (Synchronous Transmission) 概念&#xff1a; 在同步传输…

3GPP 4G 5G 主要协议

4G LTE的协议主要是36 series 5G NR的协议主要是38 series

RustScan:开源端口扫描器

RustScan 是一款开源端口扫描器&#xff0c;专为速度和多功能性而设计。 它结合了时尚的界面和随时间推移而适应和改进的能力。 借助 RustScan 的自适应学习功能&#xff0c;该工具不断优化其性能&#xff0c;使其成为最高效的端口扫描器。 在几秒钟内发现开放端口&#xff…

解决端口号被占用问题

第一种&#xff1a; 最简单有效的方法&#xff0c;重启一下电脑&#xff0c;占用此端口的程序就会释放端口。 第二种&#xff1a; 使用命令找到占用端口的程序&#xff0c;把它关闭。 1、打开运行窗口输入&#xff1a;CMD &#xff0c;进入命令窗口。 2、输入&#xff1a;n…

Candance Allegro 入门教程笔记:如何绘制原理图和原理图库?

文章目录 一、用 Capture CIS 17.4 绘制原理图库 Cadence Allegro QQ交流学习裙&#xff1a;173416628 1、凡亿教育的Candance Allegro 17.4基础教程 2、小哥Cadence Allegro 132讲 技巧视频 3、小哥Cadence Allegro 两层板 基础视频 4、小哥Cadence Allegro 四层板 提高视频…

23.10 Django 事务的使用

1. 事务 事务(Transaction): 是一种将多个数据库操作组合成一个单一工作单元的机制. 如果事务中的所有操作都成功完成, 则这些更改将永久保存到数据库中. 如果事务中的某个操作失败, 则整个事务将回滚到事务开始前的状态, 所有的更改都不会被保存到数据库中. 这对于保持数据的…

3.串口(UART)

串口理论部分可看51部分&#xff1a;链接 数据帧 帧头(2字节&#xff0c;例如AA、BB) 数据长度&#xff08;2字节&#xff09; 数据 CRC16校验&#xff08;2字节&#xff09; 帧尾&#xff08;2字节&#xff09; 代码编写 串口一发送命令控制LED灯(PB5、PE5) LED灯、串口、…

【书生·浦语大模型实战营】第三期 入门岛作业

入门岛作业 Linux闯关任务&#xff1a;完成 SSH 连接与端口映射并运行 hello_world.py。配置vscode作业内容 可选任务1&#xff1a;将Linux基础命令在开发机上完成一遍作业内容 可选任务 2&#xff1a;使用 VSCODE 远程连接开发机并创建一个conda环境作业内容 可选任务 3&#…

Selenium + Python 自动化测试10(unittest概念)

我们的目标是&#xff1a;按照这一套资料学习下来&#xff0c;大家可以独立完成自动化测试的任务。 上几篇我们讨论了元素的定位方法、操作方法以及一些特殊元素的操作。 在实际的测试项目组中每个模块会写多条案例&#xff0c;如第一条用例那里我们的登录。登录的话就可以有多…