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

news2024/9/21 23:28:16

支持向量机(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.coloradmin.cn/o/1990424.html

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

相关文章

AI在医学领域:使用眼底图像和基线屈光数据来定量预测近视

关键词&#xff1a;深度学习、近视预测、早期干预、屈光数据 儿童近视已经成为一个全球性的重大健康议题。其发病率持续攀升&#xff0c;且有可能演变成严重且不可逆转的状况&#xff0c;这不仅对家庭幸福构成威胁&#xff0c;还带来巨大的经济负担。当前的研究着重指出&#x…

Android Studio新版UI常用设置

新版UI固然好看&#xff0c;但启用后一些常用的功能也被初始化了&#xff0c;下面会说明如何设置一些常用的功能。 一、启用\禁用新版UI Setting -> Appearance & Behavior -> New UI -> Enable new UI 二、展示Git部分的Local Changes窗口 Setting -> Ve…

Leetcode JAVA刷刷站(1)两数之和

一、题目概述 二、思路方向 为了解决这个问题&#xff0c;你可以使用哈希表&#xff08;在Java中通常使用HashMap&#xff09;来存储遍历过的数组元素及其对应的索引。这样&#xff0c;当你遍历数组时&#xff0c;你可以检查target - 当前元素是否已经在哈希表中&#xff0c;如…

SpringBoot(Ⅰ)——HelloWorld和基本打包部署+Pom依赖概述+@SpringBootApplication注解+自动装配原理

前言 如果SSM学的比较好&#xff0c;那么SpringBoot说白了就两件事:约定大于配置和自动装配 SpringBoot不会提供任何的功能拓展&#xff0c;完全依赖我们手动添加 所以SpringBoot的本质是一个依赖脚手架&#xff0c;可以快速集成配置各种依赖 1.1 SpringBoot相关依赖 创建…

SQL注入---时间盲注

目录 1、时间盲注 1.1原理 2、常见函数 2.1延迟函数 2.2相关函数 3、注入流程 3.1判断注入点 3.2测试可注入方式 3.3猜数据库长度 3.4猜数据库名 4、靶场示例&#xff08;less9&#xff09; 4.1判断注入点 4.2猜测数据库长度 4.3猜数据库名 代码&#xff1a; 结…

OpenGL实现3D游戏编程【连载3】——3D空间模型光照初步

1、本节实现的内容 上一节课&#xff0c;我们建立了简单的坐标系&#xff0c;同时也显示了一个正方体&#xff0c;但正方体的颜色为纯红色&#xff0c;好像一个平面物体一样&#xff0c;我们这节课就可以加一些光照&#xff0c;并创建更多的模型&#xff0c;使这些物体变得更加…

nvm 切换、安装 Node.js 版本

nvm下载路径 往下拉找到Assets 下载后&#xff0c;找到nvm-setup.exe双击&#xff0c;一直无脑下一步&#xff0c;即可安装成功。 配置环境变量&#xff08;我的是window11&#xff09; 打开任务栏设置–搜环境变量 配置好后&#xff0c;点确定一层一层关闭 windowR 打开控制…

学习C语言第23天(程序环境和预处理)

1. 程序的翻译环境和执行环境 在ANSIC的任何一种实现中&#xff0c;存在两个不同的环境 第1种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令。 第2种是执行环境&#xff0c;它用于实际执行代码。 2. 详解编译链接 2.1 翻译环境 每个源文件单独经过编…

音视频剪辑库moviepy及其应用

moviepy是一个用于视频编辑的Python库&#xff0c;可以处理视频和音频文件。其常见用途&#xff1a; 视频剪辑和合并&#xff1a;剪辑/将多个视频文件合并成一个视频。 视频转换&#xff1a;将视频转换为不同的格式&#xff0c;比如将MP4文件转换为GIF。 文字和图形叠加&…

arcgis pro批量修改多个矢量的属性

在arcgis pro中&#xff0c;我想批量修改多个矢量的属性值。 比如&#xff1a; 我有两个要素&#xff1a;2021年县级和2022年县级&#xff0c;它们都有“区划码”、“曾用名”、“备注信息”这两个属性。 现在我想使用arcgis pro的脚本功能&#xff0c;使得2021年县级和2022年县…

凯特与戴安娜两位王妃:风采各异 凯特王妃虽未及婆婆影响力但效仿很有成效

最显而易见的也是必须了解的前提:戴安娜王妃是现任凯特王妃已故的婆婆 不过她们是没有见过面的婆媳,戴安娜王妃去世的那年,凯特才15岁!从阶级来看,当时的课题家族应该没有机会见到戴安娜。 凯特还没有像戴安娜一样对世界产生那么多的影响力 在英国王室的璀璨星空中,凯…

AI人工智能为企业带来的优势及应用例子

自2022年知名大型语言模型及其他 AI 产品面世至今&#xff0c;无论商界、政府以至社会各界都逐渐关注人工智能的发展&#xff0c;并纷纷引入 AI 技术&#xff0c;全球正式踏入人工智能的新纪元。根据 Statista 一份有关全球人工智能软件的数据研究&#xff0c;至2025年预测各国…

uni-app中如何使用日期选择器

uni-app中如何使用日期选择器&#xff0c;分别实现日&#xff0c;月&#xff0c;年 日 <picker mode"date" fields"day">是日的内容</picker> 月 <picker mode"date" fields"month">日期选择器</picker> 年…

Java设计模式(桥接模式)

定义 将抽象部分与它的实现部分解耦&#xff0c;使得两者都能够独立变化。 角色 抽象类&#xff08;Abstraction&#xff09;&#xff1a;定义抽象类&#xff0c;并包含一个对实现化对象的引用。 扩充抽象类&#xff08;RefinedAbstraction&#xff09;&#xff1a;是抽象化角…

软件测试工作流程(三)

软件测试的基本流程 测试需求分析阶段 阅读需求&#xff0c;理解需求&#xff0c;主要就是对业务的学习&#xff0c;分析需求点。参与需求评审会议 – 需求规格说明书测试计划阶段 编写测试计划&#xff0c;参考软件需求规格说明书&#xff0c;项目总体计划&#xff0c;内容包括…

OpenNebula-6.9.80中文详细部署安装

目录 OpenNebula介绍 主要特点 应用场景 一. 虚拟机准备 二. 下载安装 1. 导入yum源 2. 数据库配置 3. 安装包 4. 设置配置 数据存放位置 端口介绍 命令介绍 OpenNebula介绍 OpenNebula 是一个开源的云计算平台&#xff0c;主要用于创建和管理虚拟化环境。它被设…

LVS-NAT

概述 LVS&#xff08;Linux Virtual Server&#xff09;是一种常见的负载均衡技术。LVS允许客户端的请求通过负载均衡器&#xff08;Director Server&#xff09;转发到后端多台服务器&#xff08;Real Servers&#xff09;。在NAT模式下&#xff0c;负载均衡器会修改请求报文的…

Sqlilabs靶场报错注入:less1~6

报错注入&#xff1a; less-1&#xff1a;报错后的GET单引号字注入 首先做SQL注入&#xff0c;需要知道注入参数是什么&#xff0c;不是所有的参数都是id&#xff0c;也能是file等等。判断注入点&#xff0c;注入点很重要&#xff0c;如果找不到注入的地方&#xff0c;测试什么…

如何避免项目发布后用户从浏览器WebPack中看到源码

打包前在config->index.js中设置productionSourceMap为false productionSourceMap: false,

【Hive】学习笔记

Hive学习笔记 【一】Hive入门【1】什么是Hive【2】Hive的优缺点&#xff08;1&#xff09;优点&#xff08;2&#xff09;缺点 【3】Hive架构原理&#xff08;1&#xff09;用户接口&#xff1a;Client&#xff08;2&#xff09;元数据&#xff1a;Metastore&#xff08;3&…