什么是支持向量机 SVM ?
支持向量机(SVM)是一种强大的监督学习算法,广泛应用于分类、回归以及异常检测等多种机器学习任务。其核心思想是找到一个最优的决策边界(在二维空间中是一条线,在更高维度是一个超平面),这个决策边界能够以最大间隔将不同类别的数据点分开。
我们以最简单的二分类问题为例进行说明,假设给定一个训练数据集
其中 x 表示特征,y 表示对应的标签, y 的取值为 -1 或 1。我们的目标是找到一个分离超平面,能将实例分到不同的类别。
分离超平面对应的方程为
其中 w 是法向量,b 是截距。分离超平面将特征空间划分为两部分,一部分是正类,另一部分是负类。
一般地,当训练数据集线性可分时,存在无穷个分离超平面可将两类数据正确分开。感知机利用误分类最小的策略,求得分离超平面,不过这时的解有无穷多个。线性可分支持向量机利用间隔最大化求最优分离超平面,这时,解是唯一的。这里的间隔是指分离超平面到最近的训练样本点(支持向量)的距离。SVM的目标是最大化这个间隔,使得模型对未见样本的泛化能力最强。
如下图所示,黑色实线为超平面 (hyperplane) ,在虚线 \(H_1\) 和 虚线 \(H_2\) 上的点即为支持向量 。
在线性可分支持向量机的训练过程中,这一目标通常通过优化以下目标函数来实现:
求得最优解 \(w^*\)、\(b^*\),由此得到分离超平面 $w^ \cdot x + b^ = 0 $,对应的分类决策函数为 \(f(x) = \text{sign}(w^* \cdot x + b^*)\)
下面是一个使用 scikit-learn 库实现 SVM 的一个简单案例。
# Import necessary libraries
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
import numpy as np
# Load a dataset (for example, the Iris dataset)
iris = datasets.load_iris()
X = iris.data[:, :2] # Using only the first two features for simplicity
y = iris.target
# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Create an SVM classifier
svm_classifier = SVC(kernel='linear', C=1.0)
# Train the classifier on the training data
svm_classifier.fit(X_train, y_train)
# Make predictions on the test data
y_pred = svm_classifier.predict(X_test)
# Evaluate the accuracy of the model
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
#Accuracy: 0.9
plt.figure(figsize=(10, 6))
xx, yy = np.meshgrid(np.arange(X[:, 0].min() - 1, X[:, 0].max() + 1, 0.01),
np.arange(X[:, 1].min() - 1, X[:, 1].max() + 1, 0.01))
Z = svm_classifier.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.coolwarm, edgecolors='k')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('Linear SVM Classification')
plt.show()
SVM 中的超平⾯是什么?
在支持向量机(SVM)中,超平面是一个非常重要的概念。它是 SVM 进行数据分类的决策边界。具体来说:
超平面的定义和作用
- 定义:在 n 维空间中,超平面是一个 n-1 维的子空间。例如,在二维空间中,超平面是一条直线;在三维空间中,它是一个平面。
- 作用:在 SVM 中,超平面用来分隔不同的类别。理想情况下,它能够完全分隔两个类别的数据点,即一侧的所有数据点属于一个类别,而另一侧的所有数据点属于另一个类别。
超平面的数学表达
在数学上,超平面可以通过线性方程表示:
其中:
-
\(w\) 是超平面的法向量,决定了超平面的方向。
-
\(x\) 是空间中的任意一点。
- \(b\) 是截距,决定了超平面与原点之间的距离。
超平面与支持向量
在 SVM 中,最优的超平面是那个能够最大化两个类别之间间隔的平面。这个间隔是由距离超平面最近的那些数据点(即支持向量)决定的。超平面尽可能远离所有的支持向量,从而减小分类误差的可能性。
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs
# 创建一个包含2个中心的简单数据集
X, y = make_blobs(n_samples=100, centers=2, random_state=6)
# 创建SVM模型,使用线性核
clf = svm.SVC(kernel='linear')
clf.fit(X, y)
# 绘制数据点
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)
# 绘制决策边界
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# 创建网格以决定颜色
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)
# 绘制决策边界和边界上的间隔
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
linestyles=['--', '-', '--'])
# 标出支持向量
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=100,
linewidth=1, facecolors='none', edgecolors='k')
plt.show()
什么是软间隔和硬间隔?
在支持向量机(SVM)中,软间隔(Soft Margin)和硬间隔(Hard Margin)是处理分类问题时的两种不同方法。它们主要涉及如何处理不完全线性可分的数据。
硬间隔
在硬间隔SVM中,分类规则是非常严格的。这种方法试图找到一个超平面,它可以完全准确地分开所有的训练数据,即所有的数据点都正确地位于超平面的正确一侧。
它具有如下特点。
- 非常严格,不允许任何数据点位于错误的一侧。
- 适用于完全或几乎完全线性可分的数据集。
- 容易受到异常值(outliers)的影响,可能导致模型过拟合。
软间隔
软间隔 SVM 在一定程度上允许一些数据点分类错误。这意味着一些数据点可以位于超平面的错误一侧或者甚至在间隔内。
它具有如下特点。
- 引入了一个 “松弛变量”(slack variable),允许一些数据点违反硬间隔的规则。
- 适用于非线性可分或有噪声的数据集,提高了模型的泛化能力。
- 通过正则化参数(通常表示为C)来控制间隔的大小和允许的误差数量。
比较
- 应用场景:硬间隔适用于明显线性可分且没有异常值的数据集。软间隔更适合实际应用,因为它可以处理不完全线性可分的数据。
- 过拟合与泛化:硬间隔可能会导致过拟合,特别是在有异常值的情况下。软间隔通过允许一定程度的误差,提高了模型对新数据的泛化能力。
- 正则化参数(C):在软间隔 SVM中,C值的选择至关重要。较小的C值允许更多的分类误差,使模型更加平滑。较大的 C 值强调每个数据点的正确分类,可能导致模型变得更严格。
总结来说,硬间隔和软间隔的选择取决于数据集的特性和具体的应用需求。软间隔通常更实用,特别是在处理复杂和实际的数据集时。
线性可分 SVM 算法的优化过程?
线性可分支持向量机(SVM)算法是一种在特征空间中寻找最优分割超平面的机器学习方法,用于将两类数据分开。当数据线性可分时,这个算法特别有效。
线性可分SVM算法的优化过程如下所示。
- 目标函数和约束条件
线性可分 SVM 的目标是找到一个能够正确分类所有训练样本的超平面,并使得最近的训练样本(支持向量)到这个超平面的距离最大化。这可以表示为以下优化问题:
-
目标函数:最小化 \(\frac{1}{2} \|\mathbf{w}\|^2\) ,其中 \(w\) 是超平面的法向量
-
约束条件:\(y_i (\mathbf{w} \cdot \mathbf{x}_i + b) \geq 1\)
-
拉格朗日乘子法
为了解决这个约束优化问题,使用拉格朗日乘子法将其转化为一个无约束问题。拉格朗日函数定义为:
\(\(L(\mathbf{w}, b, \boldsymbol{\alpha}) = \frac{1}{2} \|\mathbf{w}\|^2 - \sum_{i=1}^n \alpha_i [y_i (\mathbf{w} \cdot \mathbf{x}_i + b) - 1]\)\)
其中 \(α=(α_1,α_2,...,α_n)\) 是拉格朗日乘子,对于每个样本 \(x_i\) 都有一个 \(α_i\)。
由于引入了拉格朗日函数,我们的优化目标变成:
\(\(\min_{\mathbf{w},b} \max_{\alpha_i \geq 0} L(\mathbf{w}, b, \boldsymbol{\alpha})\)\)
这个拉格朗日函数满足KKT条件,我们可以通过拉格朗日对偶将该问题转化为等价的对偶问题来求解。我们可以先求优化函数对于 \(\mathbf{w}\)和 \(b\) 的极小值。接着再求拉格朗日乘子 \(\boldsymbol{\alpha}\) 的极大值。
\(\(\max_{\alpha_i \geq 0} \min_{\mathbf{w},b} L(\mathbf{w}, b, \boldsymbol{\alpha})\)\)
- 求解对偶问题
对于拉格朗日函数 \(L(\mathbf{w}, b, \boldsymbol{\alpha})\),首先对 \(w\) 和 \(b\) 求偏导并置零,得到
$$ \nabla_{\mathbf{w}} L = 0 \Rightarrow \mathbf{w} = \sum_{i=1}^n \alpha_i y_i \mathbf{x}_i $$
$$\frac{\partial L}{\partial b} = 0 \Rightarrow \sum_{i=1}^n \alpha_i y_i = 0 $$
然后将这些结果代回拉格朗日函数,得到对偶问题,它只依赖于 \(α\)
\(\(\max_{\boldsymbol{\alpha}} W(\boldsymbol{\alpha}) = \sum_{i=1}^n \alpha_i - \frac{1}{2} \sum_{i,j=1}^n y_i y_j \alpha_i \alpha_j (\mathbf{x}_i \cdot \mathbf{x}_j)\)\)
去掉负号,即可转化为等价的极小化问题。
\(\(\begin{equation} \begin{aligned} & \min_{\boldsymbol{\alpha}} \frac{1}{2} \sum_{i=1}^m \sum_{j=1}^m \alpha_i \alpha_j y_i y_j (\mathbf{x}_i^T \mathbf{x}_j) - \sum_{i=1}^m \alpha_i \\ & \text{s.t.} \quad \sum_{i=1}^m \alpha_i y_i = 0 \\ & \alpha_i \geq 0 \quad i = 1, 2, \ldots, m \end{aligned} \end{equation}\)\)
- 优化算法
使用优化算法(如序列最小最优化SMO)来求解 α。一旦获得了 α 的最优值,就可以计算出超平面的法向量 w 和偏置项 b。
-
确定超平面和支持向量
-
超平面:由 w 和 b 定义,形式为 \(w \dot x+b=0\)
-
支持向量:对应于 $α_i>0 $的训练样本。这些样本位于决策边界的最近处,并决定了超平面的位置。
-
分类新样本
一旦确定了超平面,新样本 x 可以通过计算 \(\text{sign}(\mathbf{w} \cdot \mathbf{x} + b)\) 来分类。
https://zhuanlan.zhihu.com/p/36332083
为什么SVM要引入核函数?
支持向量机(SVM)引入核函数的主要原因是为了处理那些在原始特征空间中线性不可分的数据。通过使⽤核函数(Kernel Function)来将数据映射到⼀个⾼维特征空间,使得数据在这个⾼维空间中变得线性可分。
它主要分为以下几种。
- 线性核 (Linear Kernel)
- 公式:\(K(\mathbf{x}, \mathbf{x'}) = \mathbf{x}^T \mathbf{x'}\)
- 作用:线性核实际上不会映射到高维空间,它保持数据在原始空间不变,适用于线性可分的数据集。
- 多项式核 (Polynomial Kernel)
- 公式:\(K(\mathbf{x}, \mathbf{x'}) = (\gamma \mathbf{x}^T \mathbf{x'} + r)^d\)
- 参数:\(\gamma\) 是缩放系数,\(r\) 是偏移项,\(d\) 是多项式的度。
- 作用:多项式核可以学习特征的高阶组合,适用于数据中存在复杂关系的情况,可以实现非线性分类。
- 高斯径向基 (Radial Basis Function, RBF) 核/高斯核
- 公式:\(K(\mathbf{x}, \mathbf{x'}) = \exp(-\gamma \|\mathbf{x} - \mathbf{x'}\|^2)\)
- 参数:\(\gamma\) 是缩放系数,控制了高斯核的宽度。
- 作用:RBF 核可以映射出无限维的特征空间,适用于各种非线性关系。它特别适用于没有先验知识时的情况,因为它可以处理复杂多变的数据关系。
- Sigmoid核
- 公式:\(K(\mathbf{x}, \mathbf{x'}) = \tanh(\gamma \mathbf{x}^T \mathbf{x'} + r)\)
- 参数:\(\gamma\) 是缩放系数,\(r\) 是偏移项。
- 作用:Sigmoid 核函数模拟了神经元的激活函数。在某些情况下,它可以作为一种非线性的特征转换器。
SVM 如何处理多分类问题?
支持向量机(SVM)原本是为二分类问题设计的,但可以通过一些策略来处理多分类问题。主要有两种方法:一对多(One-vs-All, OvA)方法和一对一(One-vs-One, OvO)方法。
- 一对多(One-vs-All, OvA)
在这种方法中,为每个类别训练一个 SVM 分类器。每个分类器将一个类别与所有其他类别区分开来。如果有N个类别,则需要训练N个不同的SVM分类器。在分类新样本时,所有的分类器都会被评估,最终选择置信度(或距离边界最远)最高的类别作为预测类别。
- 一对一(One-vs-One, OvO)
在这种方法中,为每一对类别训练一个 SVM 分类器。如果有N个类别,那么会有N*(N-1)/2 个分类器。每个分类器只在一对类别间做决策。对于一个新的样本,每个分类器都会做出预测,然后采用投票机制,被预测最多次的类别将被选为最终类别。
下面是一个使用 scikit-learn 实现一对多的示例代码。
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.multiclass import OneVsRestClassifier
from sklearn import svm
X, y = datasets.make_classification(n_samples=60, n_features=2, n_classes=3,
n_clusters_per_class=1, n_redundant=0, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
ova_svm = OneVsRestClassifier(svm.SVC(kernel='linear'))
ova_svm.fit(X_train, y_train)
accuracy_ova = ova_svm.score(X_test, y_test)
print("Accuracy (One-vs-Rest):", accuracy_ova)
def plot_decision_boundary(model, X, y):
h = 0.02 # 步⻓
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', s=30)
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.title("Decision Boundary")
plt.show()
plot_decision_boundary(ovo_svm, X_test, y_test)
如何利用 SVM 进行回归分析?
支持向量机(SVM)虽然最初是为分类问题设计的,但它也可以用于回归分析,这种方法称为支持向量回归(SVR)。SVR的基本思想是找到一个函数,这个函数在给定的数据点的最大容忍度(ε)内尽可能地接近所有数据点,同时尽量保持函数的平滑性。
SVR的关键特性和步骤如下:
- ε-不敏感损失函数(ε-insensitive loss function)
这是 SVR 的核心特性之一。如果预测值与实际值之间的差异小于或等于 ε,则认为预测是正确的,即不产生任何损失。
- 选择核函数
如同 SVM 分类,SVR 也可以通过不同的核函数来处理非线性问题。常用的核函数包括线性核、多项式核、径向基函数(RBF)核等。
- 优化问题
SVR的目标是最小化一个包括正则化项(通常是权重向量的平方)和损失函数的目标函数。
- 超参数调整
SVR中的主要超参数包括C(惩罚参数),ε(不敏感区间的宽度)和核函数的参数。
下面是一个使用 SVR 进行回归的一个简单案例。
import numpy as np
from sklearn.svm import SVR
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error, r2_score
# 生成示例数据
np.random.seed(0)
X = np.sort(5 * np.random.rand(40, 1), axis=0)
y = np.sin(X).ravel()
# 添加一些噪声到目标(y)
y[::5] += 3 * (0.5 - np.random.rand(8))
# 创建和训练模型
svr_rbf = SVR(kernel='rbf', C=100, gamma=0.1, epsilon=.1)
# 训练模型
svr_rbf.fit(X, y)
# 进行预测
y_rbf = svr_rbf.predict(X)
# 可视化结果
plt.scatter(X, y, color='darkorange', label='data')
plt.plot(X, y_rbf, color='navy', lw=2, label='RBF model')
plt.xlabel('data')
plt.ylabel('target')
plt.title('Support Vector Regression')
plt.legend()
plt.show()
SVM 的优点和缺点是什么?
支持向量机(SVM)作为一种流行的机器学习算法,具有一系列的优点和缺点,这些特性决定了它在特定应用场景中的适用性。
优点
- 有效性:对于高维空间(即特征数量很多的情况),甚至在数据点数量小于特征数量的情况下,SVM 通常都能有效地进行分类。
- 泛化能力强:SVM 尝试找到最优的决策边界,以最大化类别之间的间隔,从而增强模型的泛化能力。
- 灵活性:通过选择不同的核函数,SVM可以用于解决各种类型的数据集,包括非线性数据。
缺点
- 对大数据集效率不高:在大规模数据集上训练 SVM 可能非常耗时,尤其是在选择了复杂核函数时。
- 对缺失数据敏感:SVM对缺失数据较为敏感,需要在训练前进行适当的数据预处理。
SVM与逻辑回归(Logistic Regression)之间的区别和联系。
支持向量机(SVM)和逻辑回归(Logistic Regression)都是常用的分类算法,它们在机器学习领域有着广泛的应用。
相似之处
- 分类问题: SVM 和逻辑回归都是用于监督学习中的分类问题。
- 决策边界: 两者都试图找到一个决策边界来区分不同的类别。
不同之处
- 理论基础:
- SVM: SVM 基于统计学习理论中的结构风险最小化原则。旨在找到一个最优的超平面,使得不同类别之间的间隔(Margin)最大化。
- 逻辑回归: 逻辑回归基于概率论,通过 sigmoid 函数将线性回归的输出映射到 0-1之间,从而进行概率预测。
- 损失函数:
- SVM: 使用铰链损失函数(Hinge Loss),主要关注边缘点(支持向量)。
- 逻辑回归: 使用对数损失函数(Log Loss),考虑所有数据点的预测概率。
- 处理非线性问题的能力:
- SVM: 通过核技巧可以有效处理非线性问题。
- 逻辑回归: 通常用于线性可分的场景,虽然可以通过特征工程处理非线性问题,但不如 SVM 核方法直接。
- 模型复杂度和计算成本:
- SVM: 计算更为复杂,特别是在使用核技巧时。
- 逻辑回归: 计算上更简单,容易实现和调整。