支持向量机(SVM)基础

一、SVM 是什么?

支持向量机(Support Vector Machine, SVM) 是一种监督学习算法,主要用于分类(也可用于回归,称为 SVR)。其核心思想是:

在特征空间中找到一个最优的超平面(decision boundary),使得不同类别的样本被尽可能清晰地分开,并且分类边界到最近样本点的距离(即“间隔”)最大化。

SVM 属于判别模型,追求结构风险最小化(而非经验风险最小化),具有良好的泛化能力。

二、几何直观:最大间隔分类器

2.1 线性可分情况

假设我们有两类数据(+1 和 -1),且线性可分。存在无数个超平面可以将它们分开:

  • 但 SVM 选择间隔(margin)最大的那个超平面。
  • 间隔:两个平行支持超平面之间的距离。
  • 支持向量(Support Vectors):距离决策边界最近的那些样本点,它们“支撑”了边界。
关键思想:最大间隔 ⇒ 更强的泛化能力,对噪声更鲁棒。

三、数学建模与优化推导

3.1 决策函数

设输入样本为 $\mathbf{x} \in \mathbb{R}^d$,决策超平面为:

$$ \mathbf{w}^\top \mathbf{x} + b = 0 $$

其中:

  • $\mathbf{w}$:法向量(决定方向)
  • $b$:偏置(决定位置)

分类规则:

$$ f(\mathbf{x}) = \operatorname{sign}(\mathbf{w}^\top \mathbf{x} + b) $$

💡 注:KaTeX 支持 \operatorname{sign},比 \text{sign} 更规范。

3.2 间隔(Margin)的定义

点 $\mathbf{x}_i$ 到超平面的距离为:

$$ \text{distance} = \frac{|\mathbf{w}^\top \mathbf{x}_i + b|}{\lVert \mathbf{w} \rVert} $$

对于正确分类的样本(标签 $y_i \in \{+1, -1\}$),有:

$$ y_i (\mathbf{w}^\top \mathbf{x}_i + b) \geq 1 $$

此时,函数间隔为 $y_i (\mathbf{w}^\top \mathbf{x}_i + b)$,几何间隔为 $\dfrac{y_i (\mathbf{w}^\top \mathbf{x}_i + b)}{\lVert \mathbf{w} \rVert}$。

目标:最大化最小几何间隔 ⇒ 等价于 最小化 $\lVert \mathbf{w} \rVert$


3.3 原始优化问题(Primal Form)

线性可分条件下,SVM 的优化问题为:

$$ \begin{array}{ll} \min_{\mathbf{w}, b} & \dfrac{1}{2} \lVert \mathbf{w} \rVert^2 \\ \text{subject to} & y_i (\mathbf{w}^\top \mathbf{x}_i + b) \geq 1, \quad \forall i = 1, \dots, n \end{array} $$

💡 为什么是 $\dfrac{1}{2} \lVert \mathbf{w} \rVert^2$?
为了求导方便(平方可导),且最小化 $\lVert \mathbf{w} \rVert$ 与最小化 $\lVert \mathbf{w} \rVert^2$ 等价。

这是一个凸二次规划(QP)问题,有唯一全局最优解。

四、对偶问题(Dual Form)与拉格朗日乘子法

4.1 引入拉格朗日函数

对每个约束引入拉格朗日乘子 $\alpha_i \geq 0$,构造拉格朗日函数:

$$ \mathcal{L}(\mathbf{w}, b, \boldsymbol{\alpha}) = \frac{1}{2} \lVert \mathbf{w} \rVert^2 - \sum_{i=1}^n \alpha_i \left[ y_i (\mathbf{w}^\top \mathbf{x}_i + b) - 1 \right] $$


4.2 求极小(对 $\mathbf{w}, b$)

令偏导为 0:

$$ \frac{\partial \mathcal{L}}{\partial \mathbf{w}} = 0 \quad \Rightarrow \quad \mathbf{w} = \sum_{i=1}^n \alpha_i y_i \mathbf{x}_i $$

$$ \frac{\partial \mathcal{L}}{\partial b} = 0 \quad \Rightarrow \quad \sum_{i=1}^n \alpha_i y_i = 0 $$

代入原式,得到对偶问题

$$ \begin{array}{ll} \max_{\boldsymbol{\alpha}} & \displaystyle \sum_{i=1}^n \alpha_i - \frac{1}{2} \sum_{i=1}^n \sum_{j=1}^n \alpha_i \alpha_j y_i y_j \, \mathbf{x}_i^\top \mathbf{x}_j \\ \text{subject to} & \alpha_i \geq 0, \quad \forall i \\ & \displaystyle \sum_{i=1}^n \alpha_i y_i = 0 \end{array} $$

4.3 KKT 条件与支持向量

根据 KKT 条件,最优解满足:

$$ \alpha_i \left[ y_i (\mathbf{w}^\top \mathbf{x}_i + b) - 1 \right] = 0 $$

这意味着:

  • 若 $\alpha_i > 0$,则 $y_i (\mathbf{w}^\top \mathbf{x}_i + b) = 1$ → 该样本是支持向量
  • 若 $\alpha_i = 0$,则样本不在边界上,对决策无影响
SVM 的稀疏性:最终模型仅由少数支持向量决定!

4.4 决策函数(对偶形式)

将 $\mathbf{w} = \sum \alpha_i y_i \mathbf{x}_i$ 代入,得到:

$$ f(\mathbf{x}) = \operatorname{sign} \left( \sum_{i=1}^n \alpha_i y_i \, \mathbf{x}_i^\top \mathbf{x} + b \right) $$

注意:只有支持向量的 $\alpha_i > 0$,其余为 0。

五、软间隔 SVM(Soft Margin)——处理线性不可分

现实中数据往往线性不可分或含噪声。引入松弛变量(slack variables) $\xi_i \geq 0$:

$$ y_i (\mathbf{w}^\top \mathbf{x}_i + b) \geq 1 - \xi_i $$

优化目标变为:

$$ \begin{array}{ll} \min_{\mathbf{w}, b, \boldsymbol{\xi}} & \dfrac{1}{2} \lVert \mathbf{w} \rVert^2 + C \sum_{i=1}^n \xi_i \\ \text{subject to} & y_i (\mathbf{w}^\top \mathbf{x}_i + b) \geq 1 - \xi_i \\ & \xi_i \geq 0 \end{array} $$

  • $C$:正则化参数,控制间隔最大化分类错误容忍度的权衡

    • $C \to \infty$:硬间隔(不允许错误)
    • $C \to 0$:允许更多错误,间隔更大

对偶问题变为:

$$ 0 \leq \alpha_i \leq C, \quad \sum_{i=1}^n \alpha_i y_i = 0 $$

六、核技巧(Kernel Trick)——处理非线性问题

SVM 的强大之处在于可通过核函数将数据映射到高维空间,实现非线性分类,而无需显式计算高维坐标

6.1 映射思想

设映射 $\phi: \mathbb{R}^d \to \mathcal{H}$(高维特征空间),则决策函数为:

$$ f(\mathbf{x}) = \operatorname{sign} \left( \sum_{i=1}^n \alpha_i y_i \, \phi(\mathbf{x}_i)^\top \phi(\mathbf{x}) + b \right) $$

但计算 $\phi(\mathbf{x}_i)^\top \phi(\mathbf{x})$ 可能非常昂贵。

6.2 核函数定义

核函数 $K(\mathbf{x}_i, \mathbf{x}_j) = \phi(\mathbf{x}_i)^\top \phi(\mathbf{x}_j)$

只要 $K$ 是正定核(Mercer 核),就存在对应的 $\phi$。

6.3 常用核函数

核函数公式适用场景
线性核$K(\mathbf{x}, \mathbf{y}) = \mathbf{x}^\top \mathbf{y}$线性可分
多项式核$K(\mathbf{x}, \mathbf{y}) = (\gamma \mathbf{x}^\top \mathbf{y} + r)^d$特征交互
RBF(高斯)核$K(\mathbf{x}, \mathbf{y}) = \exp(-\gamma \lVert \mathbf{x} - \mathbf{y} \rVert^2)$最常用,适合非线性
Sigmoid 核$K(\mathbf{x}, \mathbf{y}) = \tanh(\gamma \mathbf{x}^\top \mathbf{y} + r)$类神经网络
RBF 核优势:能拟合任意复杂边界,但需调参($\gamma, C$)

七、SVM 用于回归(SVR)

支持向量回归(SVR)的目标是:找到一个函数 $f(\mathbf{x})$,使得尽可能多的样本落在宽度为 $2\epsilon$ 的“管子”内

优化问题:

$$ \min_{\mathbf{w}, b, \boldsymbol{\xi}, \boldsymbol{\xi}^*} \frac{1}{2} \lVert \mathbf{w} \rVert^2 + C \sum_{i=1}^n (\xi_i + \xi_i^*) $$

subject to

$$ \begin{cases} y_i - (\mathbf{w}^\top \mathbf{x}_i + b) \leq \epsilon + \xi_i \\ (\mathbf{w}^\top \mathbf{x}_i + b) - y_i \leq \epsilon + \xi_i^* \\ \xi_i, \xi_i^* \geq 0 \end{cases} $$

同样可使用核技巧。

八、SVM 的优缺点

✅ 优点

  • 在高维空间表现优异(如文本分类)
  • 内存效率高(仅存储支持向量)
  • 通过核函数可处理非线性问题
  • 泛化能力强(结构风险最小化)
  • 对过拟合有一定抵抗力(尤其在高维低样本时)

❌ 缺点

  • 不适合大规模数据集(训练复杂度 $O(n^2) \sim O(n^3)$)
  • 噪声和异常值敏感(尤其在小 $C$ 时)
  • 不直接提供概率输出(需通过 Platt scaling 校准)
  • 调参较复杂($C, \gamma, \text{kernel}$)
  • 难以解释(黑盒模型)

九、实际应用与调参建议

9.1 典型应用场景

  • 文本分类(垃圾邮件检测、情感分析)
  • 图像识别(手写数字识别)
  • 生物信息学(基因分类)
  • 小样本高维数据

9.2 调参建议(使用 sklearn)

from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV

param_grid = {
    'C': [0.1, 1, 10, 100],
    'gamma': ['scale', 'auto', 0.001, 0.01, 0.1, 1],
    'kernel': ['rbf', 'linear']
}

grid = GridSearchCV(SVC(), param_grid, cv=5)
grid.fit(X_train, y_train)
  • 默认使用 RBF 核
  • 先标准化数据(SVM 对特征尺度敏感!)

    from sklearn.preprocessing import StandardScaler
    scaler = StandardScaler()
    X_train = scaler.fit_transform(X_train)

十、总结:SVM 的核心思想图谱

最大间隔 → 凸优化 → 对偶问题 → 支持向量 → 核技巧 → 非线性分类
          ↑
      软间隔(C参数)
📌 一句话记住 SVM
“找一个最宽的马路,把两类人分开,只靠站在路边的几个人(支持向量)来定义马路边界。”

附录 详细对比

【以下是对 支持向量机(SVM)Python 代码示例、可视化图解,以及与 逻辑回归(Logistic Regression)详细对比

一、Python 代码示例(使用 scikit-learn

我们将使用一个简单的 2D 人工数据集 来演示 SVM 的分类效果,并对比不同核函数和参数。

1.1 导入库 & 生成数据

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

# 生成非线性可分的 2D 数据(月亮形)
X, y = datasets.make_moons(n_samples=200, noise=0.2, random_state=42)

# 标准化(SVM 对尺度敏感!)
scaler = StandardScaler()
X = scaler.fit_transform(X)

# 划分训练/测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

1.2 训练 SVM(不同核)

# 创建多个 SVM 模型
models = {
    "Linear SVM": SVC(kernel='linear', C=1),
    "RBF SVM (C=1)": SVC(kernel='rbf', C=1, gamma='scale'),
    "RBF SVM (C=100)": SVC(kernel='rbf', C=100, gamma='scale'),
    "Poly SVM": SVC(kernel='poly', degree=3, C=1)
}

# 训练并预测
for name, model in models.items():
    model.fit(X_train, y_train)
    acc = model.score(X_test, y_test)
    print(f"{name} 测试准确率: {acc:.3f}")

输出示例

Linear SVM 测试准确率: 0.833
RBF SVM (C=1) 测试准确率: 0.917
RBF SVM (C=100) 测试准确率: 0.933
Poly SVM 测试准确率: 0.900
观察:RBF 核在非线性数据上显著优于线性核;高 C 更拟合训练数据(可能过拟合)。

1.3 可视化决策边界

def plot_decision_boundary(model, X, y, title):
    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.3, cmap=plt.cm.coolwarm)
    scatter = plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.coolwarm, edgecolors='k')
    plt.title(title)
    plt.xlabel('Feature 1')
    plt.ylabel('Feature 2')
    return scatter

# 可视化多个模型
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes = axes.ravel()

for idx, (name, model) in enumerate(models.items()):
    model.fit(X_train, y_train)
    plt.sca(axes[idx])
    plot_decision_boundary(model, X, y, name)
    # 标出支持向量(仅 SVM 有)
    if hasattr(model, 'support_vectors_'):
        plt.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1],
                    s=100, facecolors='none', edgecolors='black', linewidth=1.5, label='Support Vectors')
        plt.legend()

plt.tight_layout()
plt.show()

🔍 可视化图解说明:

模型决策边界特点支持向量
Linear SVM直线分割,无法很好拟合月亮形少量点在边界附近
RBF SVM (C=1)光滑曲线,泛化好支持向量适中
RBF SVM (C=100)边界更复杂,贴近训练点(可能过拟合)支持向量更多
Poly SVM多项式曲线,有一定拟合能力支持向量较多

📌 关键观察

  • 支持向量 是那些被黑色圆圈标出的点,它们决定了决策边界。
  • C 越大,边界越“贴合”数据,间隔越小 → 更容易过拟合。

二、SVM vs 逻辑回归(Logistic Regression)详细对比

维度SVM逻辑回归
目标函数最大化间隔(几何间隔)最大化似然(概率)
损失函数Hinge Loss:
( \max(0, 1 - y(\mathbf{w}^\top \mathbf{x} + b)) )
Log Loss:
( \log(1 + e^{-y(\mathbf{w}^\top \mathbf{x} + b)}) )
输出类别标签(±1)
(可通过 Platt Scaling 输出概率)
直接输出概率 ( P(y=1\mathbf{x}) )
对异常值敏感度较敏感(支持向量可能被异常点拉偏)相对鲁棒(所有点都参与损失计算)
高维表现极佳(如文本分类,n_features >> n_samples)也不错,但可能过拟合
训练速度慢(O(n²~n³)),不适合大数据快(可用 SGD 优化),适合大规模数据
可解释性低(黑盒,尤其用核函数后)高(系数可解释特征重要性)
是否需要特征缩放必须(距离敏感)推荐(加速收敛,影响正则化)
是否天然支持多分类是(One-vs-Rest 或 One-vs-One)是(Softmax 回归)
是否稀疏是(仅支持向量影响模型)否(所有样本都影响参数)

2.1 损失函数对比图

import matplotlib.pyplot as plt

z = np.linspace(-3, 3, 100)
hinge = np.maximum(0, 1 - z)
log_loss = np.log(1 + np.exp(-z))

plt.figure(figsize=(8, 5))
plt.plot(z, hinge, label='Hinge Loss (SVM)', linewidth=2)
plt.plot(z, log_loss, label='Log Loss (Logistic Regression)', linewidth=2)
plt.axvline(1, color='gray', linestyle='--', alpha=0.5, label='Margin boundary (z=1)')
plt.xlabel('z = y * f(x)')
plt.ylabel('Loss')
plt.legend()
plt.title('SVM vs Logistic Regression Loss Functions')
plt.grid(True)
plt.show()
📈 图解说明:
  • 当 ( z \geq 1 )(正确分类且在间隔外),SVM 损失为 0,不再优化 → 体现“只关心支持向量”。
  • 逻辑回归对所有点都有损失,即使分类正确也会继续优化概率。
  • SVM 有“安全间隔”,逻辑回归没有。

2.2 在相同数据上对比 SVM 与逻辑回归

# 训练逻辑回归
lr = LogisticRegression()
lr.fit(X_train, y_train)
lr_acc = lr.score(X_test, y_test)

# 训练 RBF SVM
svm = SVC(kernel='rbf', C=10, gamma='scale', probability=True)  # 启用概率
svm.fit(X_train, y_train)
svm_acc = svm.score(X_test, y_test)

print(f"逻辑回归准确率: {lr_acc:.3f}")
print(f"RBF SVM 准确率: {svm_acc:.3f}")

# 可视化对比
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

# 逻辑回归
plt.sca(ax1)
plot_decision_boundary(lr, X, y, "Logistic Regression")
ax1.set_title(f"Logistic Regression (Acc: {lr_acc:.2f})")

# SVM
plt.sca(ax2)
plot_decision_boundary(svm, X, y, "RBF SVM")
# 标出支持向量
ax2.scatter(svm.support_vectors_[:, 0], svm.support_vectors_[:, 1],
            s=100, facecolors='none', edgecolors='black', linewidth=1.5)
ax2.set_title(f"RBF SVM (Acc: {svm_acc:.2f})")

plt.tight_layout()
plt.show()
💡 结论:
  • 非线性数据上,SVM(RBF)明显优于逻辑回归
  • 逻辑回归只能画出线性边界,而 SVM 可通过核函数拟合复杂形状。

三、何时选择 SVM?何时选择逻辑回归?

场景推荐模型
小/中等数据集(< 10k 样本)✅ SVM
高维稀疏数据(如文本 TF-IDF)✅ SVM(线性核即可)
需要概率输出✅ 逻辑回归(或 SVM + Platt Scaling)
大数据集(> 100k 样本)✅ 逻辑回归 / 随机森林 / 神经网络
需要模型可解释性✅ 逻辑回归
特征维度低,边界复杂✅ SVM(RBF 核)
实时预测要求高✅ 逻辑回归(预测更快)

四、总结

  • SVM 是一个强大的分类器,尤其适合小样本、高维、非线性问题。
  • 核技巧使其能处理复杂边界,但需谨慎调参(C, gamma)。
  • 逻辑回归更简单、更快、可解释,适合线性问题或需要概率的场景。
  • 两者互补:在实际项目中,可先用逻辑回归作为 baseline,再尝试 SVM 提升性能。

📌 实践建议

  1. 永远先标准化数据
  2. GridSearchCV 调参。
  3. 对于文本分类,线性 SVM 往往比 RBF 更快更好
  4. 若数据量大,考虑使用 LinearSVC(基于 liblinear,比 SVC 快)。

添加新评论