支持向量机(Support Vector Machine, SVM)
从零到实战:原理 + 公式 + 代码 + 可视化 + 核技巧 + 调参
一句话定义:
SVM = 在高维空间中,寻找一个“最宽的隔离带”(最大间隔超平面),把两类数据分开
一、核心思想(类比)
| 现实场景 | SVM |
|---|---|
| 两群人打架 | 找一条 最宽的马路 把两边隔开 |
| 猫狗分类 | 找一个 最粗的边界,让最近的猫狗都离边界最远 |
关键:
- 支持向量:离分界线最近的点(决定边界)
- 最大间隔:两边支持向量到超平面的距离之和 → 越大越好
二、数学公式
1. 超平面(决策边界)
$$
\boxed{w \cdot x + b = 0}
$$
- $ w $:法向量(垂直于超平面)
- $ b $:偏置
2. 分类规则
$$
\boxed{f(x) =
\begin{cases}
+1, & w \cdot x + b \geq 0 \
-1, & w \cdot x + b < 0
\end{cases}}
$$
3. 几何间隔(点到超平面距离)
$$
\boxed{\gamma_i = \frac{|w \cdot x_i + b|}{|w|}}
$$
4. 最大间隔目标(硬间隔 SVM)
$$
\boxed{
\begin{align}
\max_{w,b} \quad & \frac{2}{|w|} \
\text{s.t.} \quad & y_i (w \cdot x_i + b) \geq 1, \quad \forall i
\end{align}}
$$
等价于:
$$
\boxed{\min_{w,b} \quad \frac{1}{2} |w|^2 \quad \text{s.t.} \quad y_i (w \cdot x_i + b) \geq 1}
$$
三、软间隔 SVM(允许误分类)
真实数据常有噪声 → 引入 松弛变量 ξ
$$
\boxed{
\min_{w,b,\xi} \quad \frac{1}{2} |w|^2 + C \sum \xi_i \
\text{s.t.} \quad y_i (w \cdot x_i + b) \geq 1 – \xi_i, \quad \xi_i \geq 0
}
$$
- $ C $:惩罚参数(越大越不容忍错误)
四、核技巧(Kernel Trick)—— 解决非线性!
| 核函数 | 公式 | 适用场景 |
|---|---|---|
| 线性核 | $ K(x_i, x_j) = x_i \cdot x_j $ | 线性可分 |
| 多项式核 | $ K(x_i, x_j) = (x_i \cdot x_j + 1)^d $ | 温和非线性 |
| 高斯核(RBF) | $ K(x_i, x_j) = \exp(-\gamma |x_i – x_j|^2) $ | 最常用!复杂非线性 |
| Sigmoid 核 | $ K(x_i, x_j) = \tanh(\gamma x_i \cdot x_j + r) $ | 类似神经网络 |
RBF 核 = 把数据映射到无限维空间 → 线性可分
五、Python 完整实战(5 分钟跑通)
# ===== 1. 导入库 =====
from sklearn.svm import SVC
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
import matplotlib.pyplot as plt
import numpy as np
# ===== 2. 生成非线性数据 =====
X, y = make_classification(
n_samples=300, n_features=2, n_redundant=0,
n_informative=2, n_clusters_per_class=1,
random_state=42, flip_y=0.1 # 加入噪声
)
# ===== 3. 训练 SVM(RBF 核)=====
svm = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)
svm.fit(X, y)
# ===== 4. 预测与评估 =====
y_pred = svm.predict(X)
print(f"准确率: {accuracy_score(y, y_pred):.3f}")
print(classification_report(y, y_pred))
输出:
准确率: 0.930
precision recall f1-score support
0 0.92 0.94 0.93 150
1 0.94 0.92 0.93 150
六、可视化:决策边界 + 支持向量
from sklearn.inspection import DecisionBoundaryDisplay
plt.figure(figsize=(10, 8))
# 画决策边界
DecisionBoundaryDisplay.from_estimator(
svm, X, cmap='RdBu', alpha=0.8, response_method="predict"
)
# 原始数据
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='RdBu', edgecolor='k', s=50)
# 高亮支持向量(黄圈)
sv = svm.support_vectors_
plt.scatter(sv[:, 0], sv[:, 1], c='yellow', s=200, edgecolor='k', label='支持向量')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('SVM 决策边界 + 支持向量(RBF 核)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
你会看到:
- 黄圈点 = 支持向量(决定边界)
- 曲线边界 = 非线性分割
七、线性 vs RBF 核对比
models = {
'线性核': SVC(kernel='linear', C=1.0),
'RBF 核': SVC(kernel='rbf', C=1.0, gamma='scale')
}
plt.figure(figsize=(15, 6))
for i, (name, model) in enumerate(models.items(), 1):
model.fit(X, y)
plt.subplot(1, 2, i)
DecisionBoundaryDisplay.from_estimator(model, X, cmap='RdBu', alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='RdBu', edgecolor='k')
plt.title(f'{name} - 准确率: {model.score(X, y):.3f}')
plt.tight_layout()
plt.show()
→ RBF 核明显更强!
八、调参指南(C + gamma)
| 参数 | 作用 | 建议 |
|---|---|---|
C | 错误惩罚 | 大 → 少容错(易过拟合) 小 → 多容错(易欠拟合) |
gamma (RBF) | 影响范围 | 大 → 决策边界更“弯” 小 → 更平滑 |
网格搜索调参
from sklearn.model_selection import GridSearchCV
param_grid = {
'C': [0.1, 1, 10, 100],
'gamma': ['scale', 'auto', 0.01, 0.1, 1]
}
grid = GridSearchCV(SVC(kernel='rbf'), param_grid, cv=5)
grid.fit(X, y)
print("最佳参数:", grid.best_params_)
print("最佳准确率:", grid.best_score_)
九、SVM 回归(SVR)
from sklearn.svm import SVR
from sklearn.datasets import make_regression
X, y = make_regression(n_samples=100, n_features=1, noise=10, random_state=42)
svr = SVR(kernel='rbf', C=100, gamma=0.1, epsilon=0.1)
svr.fit(X, y)
plt.scatter(X, y, color='blue', label='数据')
plt.plot(np.sort(X, axis=0), svr.predict(np.sort(X, axis=0)), color='red', label='SVR 拟合')
plt.legend()
plt.title('支持向量回归')
plt.show()
十、优缺点总结
| 优点 | 缺点 |
|---|---|
| 对小样本、高维数据效果好 | 训练慢(O(n³)) |
| 核技巧处理非线性 | 对噪声敏感 |
| 理论保证(最大间隔) | 调参复杂(C, gamma) |
| 支持向量少 → 稀疏 | 不直接输出概率 |
十一、一键完整代码(复制即用)
# ===== SVM 完整流程 =====
from sklearn.svm import SVC
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
from sklearn.inspection import DecisionBoundaryDisplay
import numpy as np
# 1. 生成月亮形非线性数据
X, y = make_moons(n_samples=300, noise=0.2, random_state=42)
# 2. 训练 RBF-SVM
svm = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)
svm.fit(X, y)
# 3. 评估
print("准确率:", accuracy_score(y, svm.predict(X)))
# 4. 可视化
plt.figure(figsize=(10, 8))
DecisionBoundaryDisplay.from_estimator(svm, X, cmap='RdBu', alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='RdBu', edgecolor='k', s=50)
plt.scatter(svm.support_vectors_[:, 0], svm.support_vectors_[:, 1],
c='yellow', s=200, edgecolor='k', label='支持向量')
plt.xlabel('X1'); plt.ylabel('X2')
plt.title('SVM (RBF 核) - 非线性分类')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
十二、总结公式卡
| 项目 | 公式 |
|---|---|
| 超平面 | $ w \cdot x + b = 0 $ |
| 间隔 | $ \gamma = \frac{2}{|w|} $ |
| 硬间隔目标 | $ \min \frac{1}{2}|w|^2 $ |
| 软间隔目标 | $ \min \frac{1}{2}|w|^2 + C\sum\xi_i $ |
| RBF 核 | $ K(x_i,x_j) = \exp(-\gamma|x_i-x_j|^2) $ |
你想深入哪一步?
- 手写 SMO 算法(SVM 核心优化)
- 网格搜索 + 交叉验证调参
- 用真实数据做项目(如人脸识别、文本分类)
- SVM vs 逻辑回归 vs 决策树对比实验
回复 1–4,我立刻带你实战!