共计 2651 个字符,预计需要花费 7 分钟才能阅读完成。
为什么需要非线性 SVM?
支持向量机(SVM)作为经典的分类算法,在处理线性可分数据时表现优异。但现实世界的数据往往是线性不可分的——比如螺旋分布的数据点,或者环形分布的分类问题。这时候线性 SVM 就无能为力了。

非线性 SVM 通过引入核技巧(kernel trick),能够将原始特征空间映射到更高维的空间,从而找到一个超平面来实现分类。这种方法的精妙之处在于:我们不需要实际计算高维空间中的坐标,只需要定义一个核函数来计算样本在高维空间的内积。这使得非线性 SVM 既能处理复杂数据分布,又保持了计算效率。
核技巧的几何直观理解
核技巧的核心思想可以用一个简单类比理解:想象你在纸上画的两个圆圈,它们重叠在一起无法用直线分开。但如果把这张纸揉成一团(相当于把二维空间映射到三维空间),突然之间这两个圆圈就可能被一个平面分开了。
最常用的 RBF 核(径向基函数核)定义为:
$$K(x_i, x_j) = \exp\left(-\frac{||x_i – x_j||^2}{2\sigma^2}\right) = \exp(-\gamma ||x_i – x_j||^2)$$
其中:
- $\sigma$ 控制核函数的宽度
- $\gamma = \frac{1}{2\sigma^2}$ 是 sklearn 中的参数
这个核函数有一个很好的性质:当两个样本距离越近时,核函数值越接近 1;距离越远则越接近 0。通过调节 $\gamma$,我们可以控制决策边界的弯曲程度。
Python 实战:从数据到决策边界
下面我们用一个完整的例子演示如何使用 sklearn 实现非线性 SVM 分类。
# 导入必要库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
# 生成非线性可分数据
X, y = make_moons(n_samples=200, noise=0.1, random_state=42)
# 数据标准化(对 RBF 核很重要)scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 训练 SVM 模型
model = SVC(kernel='rbf', C=1.0, gamma=0.1)
model.fit(X_scaled, y)
# 可视化决策边界
def plot_decision_boundary(model, X, y):
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, 0.01),
np.arange(y_min, y_max, 0.01))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('SVM Decision Boundary')
plot_decision_boundary(model, X_scaled, y)
plt.show()
这段代码做了几件重要的事情:
- 使用
make_moons生成非线性可分数据集 - 对数据进行标准化处理(这对 RBF 核至关重要)
- 创建并训练 RBF 核 SVM 模型
- 可视化决策边界
参数调优与过拟合控制
SVM 有两个关键超参数需要调节:
- C:惩罚系数,控制分类错误的容忍度
- gamma:RBF 核的 $\gamma$ 参数,控制决策边界的弯曲程度
我们可以使用网格搜索来寻找最优参数组合:
from sklearn.model_selection import GridSearchCV
param_grid = {'C': [0.1, 1, 10, 100],
'gamma': [0.01, 0.1, 1, 10]
}
grid_search = GridSearchCV(SVC(kernel='rbf'), param_grid, cv=5)
grid_search.fit(X_scaled, y)
print("Best parameters:", grid_search.best_params_)
print("Best cross-validation score:", grid_search.best_score_)
过大的 gamma 会导致过拟合——模型会完美分类训练数据,但对新数据泛化能力差。这表现为决策边界非常扭曲,围绕每个数据点形成小 ” 岛屿 ”。
避坑指南
样本不均衡问题
当类别样本数量差异很大时,可以设置 class_weight='balanced' 让 SVM 自动调整类别权重:
model = SVC(kernel='rbf', class_weight='balanced')
特征缩放的重要性
RBF 核基于样本间距离工作,因此不同特征尺度差异大会导致距离计算被大尺度特征主导。务必使用 StandardScaler 或MinMaxScaler进行标准化。
大数据集处理
SVM 训练复杂度约为 $O(n^2)$ 到 $O(n^3)$,对于超过 10 万样本的数据集:
- 使用
LinearSVC近似 - 或者设置
SVC(kernel='rbf', cache_size=1000)增大缓存
思考题与进阶
- 如何根据数据分布选择核函数?
- 多项式核适合特征间存在明显交互作用的情况
-
RBF 核适合样本形成局部聚集的情况
-
交叉验证评估示例:
from sklearn.model_selection import cross_val_score
scores = cross_val_score(SVC(kernel='rbf', C=10, gamma=0.1),
X_scaled, y, cv=5)
print("Cross-validation scores:", scores)
print("Average accuracy:", np.mean(scores))
通过这篇文章,你应该已经掌握了非线性 SVM 的核心概念和实践技巧。建议尝试不同的数据集,调整参数观察决策边界变化,这是理解 SVM 行为的最佳方式。
