机器学习:支持向量机
上述将数据集分割开来的直线称为分割超平面(separating hyperplane)。上图中,由于数据点都在二维平面上,所以分割超平面只是一条直线。如果,所给数据集是三维的,此时用来分隔数据的就是一个平面。以此类推,当给定的数据集是N维数据时,其分割对象就是N-1维的。该对象被称为。
一、支持向量机:原理概述
1.1 引言
支持向量机(Support Vector Machine,SVM)是一种用于分类和回归分析的机器学习算法。SVM的基本原理是在特征空间中找到一个最佳的超平面,使得不同类别的样本点可以被最好地分开,并且这个超平面距离最近的训练数据点的间隔最大。这个间隔被称为“边际”,而距离超平面最近的那些点被称为“支持向量”。
以下图片来自b站up主FunInCode的关于支持向量机的视频,
1.2 关键概念介绍
上述将数据集分割开来的直线称为分割超平面(separating hyperplane)。上图中,由于数据点都在二维平面上,所以分割超平面只是一条直线。如果,所给数据集是三维的,此时用来分隔数据的就是一个平面。以此类推,当给定的数据集是N维数据时,其分割对象就是N-1维的。该对象被称为超平面(hyperplane),也就是分类的决策边界。
并且,数据集中样本点到分割面的距离被称为间隔(margin)。
其中,离分割面(分割超平面)最近的那些点就是“支持向量”。
1.2.1 软间隔和硬间隔
-
硬间隔(Hard Margin): 硬间隔SVM是指在完全线性可分的情况下,寻找一个超平面,使得所有训练样本都正确分类,并且任何训练样本点到超平面的距离至少为1。这种情况下的SVM模型被称为硬间隔SVM,因为它不允许任何训练样本违反间隔约束。
-
软间隔(Soft Margin): 软间隔SVM则是考虑到实际情况下,数据可能不是完全线性可分的,或者存在噪声。软间隔允许某些样本点违反间隔约束,通过引入一个“松弛变量”(slack variable)来允许这些违规。软间隔SVM的目标是最小化一个由两部分组成的函数:一个是超平面的范数,另一个是违反间隔的样本数量的总和。
对于数据集分类问题来说,往往都存在一些个别样本点出现异常,并不满足分类规则,此时使用软间隔SVM就会有一定的容错率,目的是在间隔距离和错误之间找到一个平衡。
以下是针对二维分类问题下的软间隔、硬间隔示例图:(图片仍是从B站up主FunInCode的支持向量机中的视频获取)
1.2.2 核技巧(Kernel Trick)
为什么要引入核函数呢? 因为在SVM中,有时候很难找出一条线或一个超平面来分割数据集,这时候我们就需要升维(把无法线性分割的样本映射到高纬度空间,在高维空间实现分割)。
1.2.2.1 升维转换函数
首先,我们要先通过合适的维度转换函数,对低维的数据升维;然后,在高维度下求解SVM模型,找到对应的分割超平面。当有新数据需要进行分类与测试,可以先对其做升维转换操作,再根据高维度下的决策边界超平面做出判断。
升维转换函数是将原始特征空间中的数据通过一个明确的非线性映射 𝜙(⋅)转换到一个更高维的空间中,以便在这个高维空间中找到一个可以线性分隔数据的超平面。这种转换通常是为了处理在原始特征空间中无法线性分隔的数据。
优点:
- 明确性:升维转换函数提供了一个明确的映射,可以清楚地知道数据是如何被转换的。
- 可控性:可以通过选择或设计映射函数来控制转换过程。
缺点:
- 计算复杂度高:高维空间中的计算通常非常复杂,可能会导致维数灾难。
- 存储需求大:需要存储转换后的高维特征向量,这可能会占用大量内存。
1.2.2.2 核函数
核函数是特征转换函数,它可以将数据映射到高维特征空间中,从而更好地处理非线性关系。核函数的作用是通过计算两个样本之间的相似度(内积)来替代显式地进行特征映射,从而避免了高维空间的计算开销。
通过选择适当的核函数,如线性核、多项式核、径向基函数(RBF)核等,我们可以隐式地进行升维转换,而无需担心高维空间中的维数灾难问题。
优点:
避免维数灾难:不需要显式地计算和存储高维特征向量,从而避免了维数灾难。
计算效率高:核函数通常可以高效地计算内积,特别是在使用某些优化的核函数时。
灵活性:可以尝试不同的核函数来找到最适合数据的转换。
缺点:
模型解释性差:由于核函数隐式地进行转换,因此很难解释模型是如何做出决策的。
过拟合风险:选择不适当的核函数或参数可能会导致模型过拟合。
1.3 核函数的应用原理和计算方法
核函数在SVM中的应用是基于“核技巧”(Kernel Trick),它允许我们在不显式地计算升维转换后的高维特征向量的情况下,直接计算高维空间中的内积。
1.3.1 原理
假设我们有一个非线性映射 ,它将原始特征空间中的数据点 x 映射到高维特征空间中的
。在SVM中,我们关心的是在高维空间中数据点之间的内积,即
。核函数
定义为这个内积的函数,公式如下所示:
。
1.3.2 计算方法
核函数的计算方法取决于所选的核函数类型。常见的核函数包括:
- 线性核:
- 多项式核:
- 径向基函数(RBF)核:
,其中
和
是第i和j个样本点的特征向量。
- sigmoid核:
在实际应用中,我们选择一个合适的核函数,并用它来计算训练数据集中任意两个数据点之间的核函数值。这些值被用于对偶问题的求解,从而确定最优的超平面。
二、 支持向量机算法实现(步骤+代码)
通常情况下,当标签值是离散型变量时,我们将问题视为分类问题,而当标签值是连续性变量时,我们将问题视为回归问题。在支持向量机(SVM)算法中,SVC用于分类,SVR用来做回归。
2.1 SVC(分类)简单实现
以Python库中自带的鸢尾花数据集为例,进行支持向量机算法在分类问题中的简单实现。
2.1.1 获取和处理数据集
2.1.1.1 获取数据集
从Python的sklearn库中调取鸢尾花数据集(iris数据集),并获取该数据集的特征和类别标签(目标值);
# 加载iris数据集
from sklearn.datasets import load_iris
iris = load_iris()
x = iris.data
y = iris.target
2.1.1.2 数据预处理
因为鸢尾花数据集有四个特征,所以为了方便可视化,要将数据集进行降维处理,并对数据集划分为训练集和测试集,以便于后续模型构建和训练。
# 使用PCA进行降维
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
x_pca = pca.fit_transform(x)
#数据的划分
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x_pca,y,random_state=42)
#标准化
from sklearn import preprocessing
scaler = preprocessing.StandardScaler().fit(x_train)
#保证train数据与test数据是在统一的距离标准下进行的标准化
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)
2.1.2 构建模型
从Python的sklearm库中直接调用SVC函数创建SVM在分类问题上的SVC模型;
# 构建SVC模型
import numpy as np
from sklearn.svm import SVC
best_clf = SVC(degree= 1,C= 1,gamma= 0.133,kernel="poly")
2.1.3 训练模型
使用训练集对模型进行训练,通过最大化间隔来找到最优的超平面。
best_clf.fit(x_train,y_train)
2.1.4 预测数据
用训练好的SVC模型对测试集样本的目标值进行预测:
# 使用最佳模型进行预测
y_pred = best_clf.predict(x_test)
2.1.5 结果可视化
接下来我们将会调用matplotlib库中的pyplot函数实现数据散点图和该数据集决策边界可视化:
import matplotlib.pyplot as plt
2.1.5.1 数据散点图可视化
# 绘制散点图
sc = plt.scatter(x_test[:, 0], x_test[:, 1], c=y_pred)
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.title('SVM Classification - Predicted Classes')
handles, labels = sc.legend_elements()
plt.legend(handles, labels)
plt.show()
数据散点图可视化结果展示:
2.1.5.2 决策边界可视化
# 绘制决策边界图
h = 0.02 # 步长
x_min, x_max = x_test[:, 0].min() - 1, x_test[:, 0].max() + 1
y_min, y_max = x_test[:, 1].min() - 1, x_test[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
Z = best_clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.8)
plt.scatter(x_test[:, 0], x_test[:, 1], c=y_pred)
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.title('SVM Classification - Decision Boundary')
plt.show()
决策边界可视化结果展示:
三、完整代码展示
SVM在鸢尾花数据集分类上的完整代码展示(SVC):
# 加载iris数据集
from sklearn.datasets import load_iris
iris = load_iris()
x = iris.data
y = iris.target
# 使用PCA进行降维
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
x_pca = pca.fit_transform(x)
#数据的划分
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x_pca,y,random_state=42)
#标准化
from sklearn import preprocessing
scaler = preprocessing.StandardScaler().fit(x_train)
#保证train数据与test数据是在统一的距离标准下进行的标准化
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)
# 构建SVC模型
import numpy as np
from sklearn.svm import SVC
best_clf = SVC(degree= 1,C= 1,gamma= 0.133,kernel="poly")
best_clf.fit(x_train,y_train)
# 使用最佳模型进行预测
y_pred = best_clf.predict(x_test)
import matplotlib.pyplot as plt
# 绘制散点图
sc = plt.scatter(x_test[:, 0], x_test[:, 1], c=y_pred)
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.title('SVM Classification - Predicted Classes')
handles, labels = sc.legend_elements()
plt.legend(handles, labels)
plt.show()
# 绘制决策边界图
h = 0.02 # 步长
x_min, x_max = x_test[:, 0].min() - 1, x_test[:, 0].max() + 1
y_min, y_max = x_test[:, 1].min() - 1, x_test[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
Z = best_clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.8)
plt.scatter(x_test[:, 0], x_test[:, 1], c=y_pred)
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.title('SVM Classification - Decision Boundary')
plt.show()
更多推荐
所有评论(0)