支持向量机,通常称为SVM,是一类简单而强大的机器学习算法,用于分类和回归任务。在本讨论中,我们将着重介绍支持向量机在分类问题中的应用。
我们将从分类和分离超平面的基础知识开始讲起。然后逐步介绍最大间隔分类器,逐步构建支持向量机和该算法的scikit-learn实现。
分类问题和分离超平面
分类是一个有监督学习问题,其中我们有带有标签的数据点,机器学习算法的目标是预测新数据点的标签。
为简单起见,让我们来看一个具有两个类别(A类和B类)的二分类问题。我们需要找到一个分离这两个类别的超平面。
从数学上讲,超平面是一个维数比环境空间小一的子空间。也就是说,如果环境空间是一条线,那么超平面就是一个点。如果环境空间是一个二维平面,那么超平面就是一条线,依此类推。
因此,当我们有一个分隔两个类别的超平面时,属于A类的数据点位于超平面的一侧,属于B类的数据点位于另一侧。
因此,在一维空间中,分离超平面是一个点:
在二维空间中,分离A类和B类的超平面是一条线:
在三维空间中,分离超平面是一个平面:
同样地,在N维空间中,分离超平面将是一个(N-1)维子空间。
如果你仔细观察,对于二维空间的例子,以下每个都是分隔A类和B类的有效超平面:
那么我们如何决定哪个超平面是最优的呢?这就是最大间隔分类器的作用。
最大间隔分类器
最优超平面是分离两个类别并最大化它们之间间隔的超平面。而一个按照这种方式工作的分类器称为最大间隔分类器。
硬间隔和软间隔
我们考虑了一个超级简化的例子,其中类别完全可分,最大间隔分类器是一个很好的选择。
但是如果你的数据点分布如此呢?这些类别仍然可以通过一个超平面完全分离,并且最大化间隔的超平面看起来是这样的:
但是你看到这种方法的问题了吗?嗯,它仍然实现了类别分离。然而,这是一个高方差模型,也许试图很好地拟合A类的点。
但请注意,间隔没有任何错误分类的数据点。这样的分类器称为硬间隔分类器。
相反,看看这个分类器。这样的分类器会表现得更好吗?这是一个方差较低的模型,对于A类和B类的点都能很好地进行分类。
线性支持向量分类器 | 作者提供的图片
注意,我们在边缘内部有一个被错误分类的数据点。这样的分类器允许最小的误分类,被称为软边界分类器。
支持向量分类器
我们拥有的软边界分类器是一个线性支持向量分类器。这些点可以由一条直线(或线性方程)分开。如果你一直在跟随到现在,你应该很清楚什么是支持向量以及为什么称为支持向量。
每个数据点都是特征空间中的一个向量。最靠近分隔超平面的数据点被称为支持向量,因为它们支持或帮助分类。
有趣的是,如果你移除一个或多个不是支持向量的数据点,分隔超平面不会改变。但是,如果你移除一个或多个支持向量,超平面就会改变。
到目前为止的例子中,数据点是线性可分的。所以我们可以使用最小的误差拟合一个软边界分类器。但是如果数据点分布如下呢?
非线性可分数据 | 作者提供的图片
在这个例子中,数据点是非线性可分的。即使我们有一个允许误分类的软边界分类器,我们也无法找到一个能在这两个类上取得良好性能的直线(分隔超平面)。
那么现在我们该怎么办呢?
支持向量机和核技巧
这里是我们要做的总结:
- 问题:数据点在原始特征空间中不是线性可分的。
- 解决方案:将数据点投影到一个更高维度的空间中,使得它们是线性可分的。
但是将数据点投影到更高维度的特征空间需要将数据点从原始特征空间映射到更高维度的空间。
这种重新计算会带来相当大的开销,特别是当我们要投影到的空间比原始特征空间的维度高得多时。这就是核技巧发挥作用的地方。
数学上,支持向量分类器可以用以下方程表示 [1]:
这里, 是一个常数,
表示我们对相应于支持点的索引集合进行求和。
是点
和
之间的内积。任意两个向量 a 和 b 的内积由以下公式给出:
核函数 K(.) 允许将线性支持向量分类器推广到非线性情况。我们将内积替换为核函数:
核函数考虑了非线性性质。并且允许在原始特征空间中对数据点进行计算,而无需在更高维度的空间中重新计算。
对于线性支持向量分类器,核函数简单地是内积,其形式如下:
Scikit-Learn中的支持向量机
现在我们理解了支持向量机背后的直觉,让我们使用scikit-learn库来编写一个快速的示例。
scikit-learn库中的svm模块提供了LinearSVC、SVC和NuSVC等类的实现。这些类可以用于二元和多类分类。Scikit-learn的扩展文档列出了支持的核函数。
我们将使用内置的wine数据集。这是一个分类问题,其中使用wine的特征来预测输出标签,该标签是三个类别之一:0、1或2。这是一个小数据集,约有178条记录和13个特征。
在这里,我们只关注:
- 加载和预处理数据
- 将分类器拟合到数据集
步骤1 – 导入必要的库并加载数据集
首先,让我们加载scikit-learn的datasets模块中可用的wine数据集:
from sklearn.datasets import load_wine
# 加载wine数据集
wine = load_wine()
X = wine.data
y = wine.target
步骤2 – 将数据集拆分为训练集和测试集
让我们将数据集拆分为训练集和测试集。在这里,我们使用80:20的拆分比例,其中80%的数据点用于训练集,20%的数据点用于测试集:
from sklearn.model_selection import train_test_split
# 将数据集拆分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=10)
步骤3 – 预处理数据集
接下来,我们对数据集进行预处理。我们使用StandardScaler
将数据点转换为具有零均值和单位方差的分布:
# 数据预处理
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
请记住,不要在测试数据集上使用fit_transform
,因为这会导致数据泄漏的微妙问题。
步骤4 – 实例化SVM分类器并将其拟合到训练数据
我们将在此示例中使用SVC
。我们实例化一个SVC对象svm
,并将其拟合到训练数据:
from sklearn.svm import SVC
# 创建SVM分类器
svm = SVC()
# 将SVM分类器拟合到训练数据
svm.fit(X_train_scaled, y_train)
步骤5 – 预测测试样本的标签
要预测测试数据的类别标签,我们可以在svm
对象上调用predict
方法:
# 预测测试集的标签
y_pred = svm.predict(X_test_scaled)
步骤6 – 评估模型的准确性
为了总结讨论,我们只计算准确率。但是,我们也可以得到更详细的分类报告和混淆矩阵。
from sklearn.metrics import accuracy_score
# 计算模型的准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"{accuracy=:.2f}")
输出 >>> accuracy=0.97
以下是完整代码:
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
# 加载葡萄酒数据集
wine = load_wine()
X = wine.data
y = wine.target
# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=10)
# 数据预处理
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 创建一个支持向量机分类器
svm = SVC()
# 将支持向量机分类器拟合到训练数据
svm.fit(X_train_scaled, y_train)
# 预测测试集的标签
y_pred = svm.predict(X_test_scaled)
# 计算模型的准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"{accuracy=:.2f}")
我们有一个简单的支持向量分类器。您可以调整超参数以提高支持向量分类器的性能。常用的调整超参数包括正则化常数C和gamma值。
结论
希望您对支持向量机的入门指南有所帮助。我们涵盖了足够的直觉和概念来理解支持向量机的工作原理。如果您对深入了解感兴趣,可以查看下面链接的参考资料。继续学习吧!
参考资料
[1] 支持向量机章节,《统计学习导论(ISLR)》
[2] 核机器章节,《机器学习导论》
[3] 支持向量机,scikit-learn文档 Bala Priya C 是来自印度的开发者和技术作家。她喜欢在数学、编程、数据科学和内容创作的交叉点工作。她感兴趣和擅长的领域包括DevOps、数据科学和自然语言处理。她喜欢阅读、写作、编码和咖啡!目前,她正在通过撰写教程、指南、观点文章等,与开发者社区共享她的知识和学习经验。