一文搞懂支持向量机(SVM)
支持向量机(Support Vector Machine, SVM)是机器学习中经典且强大的分类算法之一,尤其在中小规模数据集上表现优异。它的核心思想非常直观:找到一个最优的“分界线”(或“分界面”),让两类数据尽可能被清晰地分开,并且分界线到两边数据的距离尽量大。
本文将从原理、数学直觉、核函数到实际使用,系统地介绍 SVM。
1. SVM 的核心思想
假设我们有两类数据点(正类和负类),分布在二维平面上。SVM 要做的事情是:
- 找到一条直线(在高维空间中是超平面),把两类点分开;
- 这条直线不仅要能分开数据,还要让它到最近数据点的距离(间隔,Margin)尽可能大。
这条最优分界线就叫做最大间隔超平面(Maximum Margin Hyperplane),而距离超平面最近的那些点,被称为支持向量(Support Vectors)。它们决定了超平面的位置,其他点则对最终模型影响不大。
直观理解:支持向量就像“支撑”起这条分界线的关键点,去掉它们,分界线就会移动。
2. 线性可分情况下的 SVM
当数据是线性可分时(可以用一条直线完美分开),SVM 的目标可以写成一个优化问题:
[
\min_{\mathbf{w}, b} \frac{1}{2} |\mathbf{w}|^2
]
约束条件为:
[
y_i (\mathbf{w} \cdot \mathbf{x}_i + b) \geq 1, \quad \forall i
]
其中:
- (\mathbf{w}) 是超平面的法向量;
- (b) 是偏置;
- (y_i \in {+1, -1}) 是样本标签;
- (\mathbf{x}_i) 是样本特征。
(\frac{1}{2}|\mathbf{w}|^2) 越小,间隔 (\frac{2}{|\mathbf{w}|}) 就越大。
3. 软间隔(Soft Margin)——处理噪声和异常点
现实数据往往不是完美线性可分的。为此,SVM 引入了松弛变量 (\xi_i \geq 0),允许部分点被分错或落在间隔内。优化目标变为:
[
\min_{\mathbf{w}, b, \xi} \frac{1}{2} |\mathbf{w}|^2 + C \sum_{i=1}^{n} \xi_i
]
参数 (C) 是惩罚系数:
- (C) 很大:模型更倾向于把所有点都分对(容易过拟合);
- (C) 较小:允许更多错误,模型更平滑(更抗噪声)。
这就是实际使用中最常见的软间隔 SVM。
4. 核函数(Kernel Trick)——处理非线性问题
当数据在原始空间线性不可分时,SVM 可以通过核技巧把数据映射到高维空间,使其变得线性可分,而无需显式计算高维坐标。
常用核函数:
| 核函数 | 公式 | 适用场景 |
|---|---|---|
| 线性核 | (K(\mathbf{x}, \mathbf{z}) = \mathbf{x} \cdot \mathbf{z}) | 特征已经很高维、线性可分 |
| 多项式核 | (K(\mathbf{x}, \mathbf{z}) = (\gamma \mathbf{x}\cdot\mathbf{z} + r)^d) | 有一定非线性关系 |
| RBF(高斯)核 | (K(\mathbf{x}, \mathbf{z}) = \exp(-\gamma |\mathbf{x}-\mathbf{z}|^2)) | 最常用,适合大多数非线性问题 |
| Sigmoid 核 | (K(\mathbf{x}, \mathbf{z}) = \tanh(\gamma \mathbf{x}\cdot\mathbf{z} + r)) | 类似神经网络 |
RBF 核几乎是默认选择,参数 (\gamma) 控制单个样本的影响范围:
- (\gamma) 大:模型更复杂,容易过拟合;
- (\gamma) 小:模型更平滑。
5. SVM 的优缺点
优点:
- 在中小规模数据集上效果好,泛化能力强;
- 只依赖支持向量,对高维数据友好;
- 可通过核函数处理非线性问题;
- 理论基础扎实(结构风险最小化)。
缺点:
- 对大规模数据集训练较慢(尤其是核方法);
- 对参数 (C) 和 (\gamma) 较敏感,需要调参;
- 原生主要做二分类(多分类需用 One-vs-Rest 或 One-vs-One);
- 对缺失值和噪声较敏感(需预处理)。
6. 实际代码示例(scikit-learn)
下面是一个使用 RBF 核的 SVM 分类示例:
from sklearn.svm import SVC
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
# 生成示例数据
X, y = make_classification(n_samples=1000, n_features=20, n_informative=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 特征标准化(SVM 对尺度敏感,必须做)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 训练 SVM
clf = SVC(kernel='rbf', C=1.0, gamma='scale')
clf.fit(X_train, y_train)
# 预测与评估
y_pred = clf.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.4f}")
print(f"支持向量数量: {clf.n_support_}")
- 点赞
- 收藏
- 关注作者
评论(0)