观文听傑

返回

上一篇的 XGBoost 通过许多轴对齐分裂逐步修正预测。树模型能表达复杂边界,但边界由大量局部规则拼成;当特征是高维稀疏向量,或者我们希望得到一条全局、稳定的分界面时,线性模型仍然很有价值。

逻辑回归会用交叉熵学习一条线性边界。不过只要求把训练样本分对时,通常存在许多可行直线。哪一条更不怕测量误差和样本轻微移动?

支持向量机(Support Vector Machine,SVM)的选择是:让分界面离两类中最近的训练样本尽可能远。 本文只讲透最大间隔、软间隔和合页损失这条主线;核技巧留到下一篇。

01 只找到一条分界线为什么不够?#

二分类线性模型先计算决策分数:

f(x)=wx+bf(x)=w^\top x+b
  • xRDx\in\mathbb{R}^{D}:一个 DD 维样本;
  • wRDw\in\mathbb{R}^{D}:边界的法向量;
  • bRb\in\mathbb{R}:截距;
  • f(x)Rf(x)\in\mathbb{R}:有符号决策分数;
  • 标签改写成 y{1,+1}y\in\{-1,+1\},预测为 sign(f(x))\operatorname{sign}(f(x))

边界是 wx+b=0w^\top x+b=0。二维中,下面三条线都能分对训练点,但中间那条给两类留下了更大的缓冲带:

x₂
▲       +     +
│          +          wᵀx+b = +1
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│  ═══════════════════════════  wᵀx+b = 0
│  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  wᵀx+b = -1
│       ○       ○
│    ○
└────────────────────────────► x₁
        最近的 + / ○ 决定缓冲带宽度
text

若边界紧贴某个训练点,这个点的特征只要有一点测量误差就会越界。最大间隔(Maximum Margin)不是直接保证未来正确,而是加入一种几何归纳偏置:在训练数据允许的范围内,选择最有余量的边界。

02 函数间隔为什么必须归一化?#

一个样本的有符号函数间隔是:

mi=yi(wxi+b)m_i=y_i(w^\top x_i+b)

分对时 mi>0m_i>0,分错时 mi<0m_i<0。但把 w,bw,b 同时乘以 10,边界位置完全不变,mim_i 却会放大 10 倍。因此不能只靠增大参数制造“更大间隔”。

点到超平面的几何距离为:

di=wxi+bw2d_i=\frac{|w^\top x_i+b|}{\|w\|_2}

对分对的样本,可写成:

γi=yi(wxi+b)w2\gamma_i=\frac{y_i(w^\top x_i+b)}{\|w\|_2}

固定缩放,使离边界最近的样本满足 yi(wxi+b)=1y_i(w^\top x_i+b)=1,两条间隔边界就是:

wx+b=+1,wx+b=1w^\top x+b=+1,\qquad w^\top x+b=-1

每一侧到中央边界的距离是 1/w21/\|w\|_2,完整间隔宽度为:

2w2\frac{2}{\|w\|_2}

所以最大化间隔等价于最小化 w2\|w\|_2

03 硬间隔 SVM 怎样写成优化问题?#

线性可分时,硬间隔支持向量机(Hard-margin SVM)求解:

minw,b 12w22\min_{w,b}\ \frac12\|w\|_2^2

满足每个训练样本:

yi(wxi+b)1,i=1,,Ny_i(w^\top x_i+b)\ge1,\qquad i=1,\ldots,N

这两个部分各司其职:

部分约束了什么几何意义
12w2\frac12\|w\|^2目标尽量小间隔尽量宽
yif(xi)1y_if(x_i)\ge1所有样本在正确一侧不允许进入间隔或分错

刚好满足等号 yif(xi)=1y_if(x_i)=1 的点叫支持向量(Support Vector)。它们像撑住两侧间隔的支点;离边界更远的样本约束有余量,轻微移动通常不会改变最优边界。

全部训练样本 X [N,D] + y [N]
          │ 求解带约束优化

       w [D], b []

          ├── 最近样本:support vectors [S,D]

X_query [Q,D] ─► X_query @ w + b ─► scores [Q]
                                      │ sign

                                  labels [Q]
text

04 一维例子:为什么只有两个点“撑住”边界?#

考虑:

x: [-2, -1, 1, 2]
y: [-1, -1,+1,+1]
text

w=1,b=0w=1,b=0,四个函数间隔为:

yi(wxi+b)=[2,1,1,2]y_i(wx_i+b)=[2,1,1,2]

所有约束都满足。x=1x=-1x=1x=1 恰好位于 f(x)=1f(x)=-1f(x)=+1f(x)=+1,是支持向量;x=2x=-2x=2x=2 更远。

边界在 x=0x=0,完整间隔宽度为:

2w=2\frac{2}{|w|}=2

如果把远点从 ±2\pm2 改成 ±20\pm20,最近的两个点不变,最优边界也不变。这是“支持向量”名称最直接的含义:最终解主要由靠近边界的困难样本支撑,而不是由每个远处样本平均决定。

交互手算:把正类最近点从 1 移到 3

最近负类仍是 1-1,最近正类变成 33。对称的最大间隔边界移动到 x=1x=1,两侧支持向量到边界的距离都是 2,完整间隔变为 4。远处点只要没有成为新的最近点,就不会撑住边界。

05 一个异常点为何让硬间隔失效?#

真实数据常有重叠和错标。若在上例加入一个负类点 x=0.2x=0.2,就无法用原来的宽间隔把所有点都放到正确区域;更极端时,两类完全交错,硬间隔问题没有可行解。

软间隔支持向量机(Soft-margin SVM)为每个样本加入松弛变量(Slack Variable)ξi0\xi_i\ge0

minw,b,ξ 12w22+Ci=1Nξi\min_{w,b,\xi}\ \frac12\|w\|_2^2+C\sum_{i=1}^{N}\xi_i

约束改成:

yi(wxi+b)1ξiy_i(w^\top x_i+b)\ge1-\xi_i

松弛量可以直接读成违反间隔的程度:

mi=yif(xi)m_i=y_if(x_i)最小 ξi\xi_i状态
mi>1m_i>10正确且在间隔外
mi=1m_i=10位于间隔边界,支持向量
0<mi<10<m_i<11mi1-m_i分对但进入间隔
mi0m_i\le01mi11-m_i\ge1分错或恰在决策边界

C>0C>0 是违反间隔的价格:大 CC 更努力减少训练违规,可能得到窄而曲折的边界;小 CC 更愿意容忍违规,以换取更小的 w\|w\| 和更宽的间隔。

06 合页损失把约束变成可优化目标#

对固定 w,bw,b,最小松弛量就是合页损失(Hinge Loss):

Lhinge(y,f)=max(0,1yf)L_{hinge}(y,f)=\max(0,1-yf)

软间隔目标可写成:

J(w,b)=12w22+Ci=1Nmax(0,1yif(xi))J(w,b)=\frac12\|w\|_2^2+C\sum_{i=1}^{N}\max(0,1-y_i f(x_i))
hinge loss

│\
│ \
│  \
│   \__________
└───────────────► margin m = y f(x)
0        1

m < 1:仍有线性梯度
m > 1:损失为 0,不再推动远处样本
text

这与逻辑回归的交叉熵很不一样。交叉熵会继续奖励更高的正确置信度;标准合页损失在样本越过 m=1m=1 后变成 0。SVM 因而把优化重点放在间隔内和边界附近的点。

手算 C 如何改变选择#

仍用五个样本:

x = [-2,-1,0.2,1,2]
y = [-1,-1, -1,+1,+1]
text

比较两个无截距候选模型:

候选12w2\frac12w^2合页损失之和C=1C=1 的目标C=0.1C=0.1 的目标
A:w=1w=10.5001.2001.7000.620
B:w=0.5w=0.50.1252.1002.2250.335

C=1C=1 时,A 用更大权重换来较少违规;C=0.1C=0.1 时,B 的更宽间隔更值得,哪怕更多样本进入间隔。真实训练不是只在两个候选间选择,但权衡完全相同。

07 不依赖黑盒:用 PyTorch 写出线性软间隔#

下面直接优化“权重平方 + 平均合页损失”。为了让偏置不被正则化,显式拆出 weightbias

关键调试量不是只有准确率:

with torch.no_grad():
    margin = y * (X @ weight + bias)
    print('weight norm:', weight.norm().item())
    print('minimum margin:', margin.min().item())
    print('inside margin:', (margin <= 1.0).sum().item())
    print('misclassified:', (margin <= 0.0).sum().item())
python

本文代码对合页损失取均值,而经典 CC-SVM 常写成求和。因此这里的 C=1 不等于任意库中的同名数值;比较实验必须固定样本数、缩放方式和目标约定。

08 用 scikit-learn 1.9 正确落地#

若希望直接检查支持向量,可用 SVC(kernel='linear')。SVM 对尺度不具不变性,标准化必须放进 Pipeline,避免交叉验证泄漏:

注意 support_vectors_ 位于标准化后的空间,因为 SVC 接收的是 Pipeline 上一步输出。原始训练样本索引可用 support_ 回到 X_train

当样本很多且只需要线性边界,LinearSVC 通常更可扩展:

from sklearn.svm import LinearSVC

linear_pipeline = make_pipeline(
    StandardScaler(),
    LinearSVC(
        C=1.0,
        loss='hinge',
        penalty='l2',
        dual='auto',
        max_iter=10_000,
        random_state=42,
    ),
)
linear_pipeline.fit(X_train, y_train)
python

scikit-learn 1.9 中,LinearSVC 默认损失其实是 squared_hinge;上面显式设为 hinge 才与本文公式一致。它由 liblinear 实现,规模通常优于 SVC(kernel='linear'),但不提供 support_;二者的损失默认值和截距正则化也不同,不能期待逐点完全相同。

09 工程中最常见的错误与调试路径#

  1. 没有缩放特征。 若收入数值是年龄的几千倍,w\|w\| 与几何距离会被单位扭曲。只在训练折拟合 StandardScaler
  2. 把分数当概率。 SVM 原生输出间隔分数,不在 [0,1][0,1]。需要概率时应在独立交叉验证框架中校准,而不是手动 Sigmoid。
  3. 误解 CC 更在乎训练违规,小 C 正则更强;画验证曲线并同时记录支持向量比例。
  4. LinearSVCsupport_ 它不保存 libsvm 意义下的支持向量;需要这些属性时用 SVC(kernel='linear')
  5. 标签仍是 0/1 却手写 yf(x)yf(x) 数学推导要求 y{1,+1}y\in\{-1,+1\};代码里先显式映射并断言。
  6. 只加大 max_iter 出现收敛警告时先检查尺度、重复特征、异常值和 tol,再提高迭代上限。
  7. 类别失衡只看准确率。 检查每类召回率和间隔分布;class_weight='balanced' 会按类别缩放有效 CC,仍需验证。

最小不变量:

assert X_train.ndim == 2 and y_train.ndim == 1
assert X_train.shape[0] == y_train.shape[0]
assert np.isfinite(X_train).all()
assert scores.shape == (X_val.shape[0],)
assert np.isfinite(scores).all()
print('best C:', search.best_params_['svc__C'])
print('support ratio:', len(svc.support_) / len(X_train))
python

支持向量比例非常高,可能说明类别重叠严重、特征噪声大、C 选择不合适,或线性边界根本不匹配;它不是一个单独的质量指标。

10 它什么时候失败?与逻辑回归有什么不同?#

方法训练目标远离边界的正确样本原生概率线性边界
线性 SVM权重范数 + 合页损失超过间隔后损失为 0
逻辑回归L2 等正则 + 对数损失仍有很小损失是,但仍需校准检查
感知机错分样本触发更新分对后不管间隔
决策树不纯度贪心分裂不适用叶频率轴对齐分段

线性 SVM 会在以下场景失效或失去优势:

  • 原始空间边界明显弯曲,例如同心圆;
  • 标签严重重叠或错标,支持向量过多,边界对困难点敏感;
  • 业务必须直接得到可靠概率,却没有足够校准数据;
  • 数据分布漂移使旧支持向量不再代表新边界;
  • 特征量纲、缺失值或线上预处理与训练不一致。

最大间隔提升的是特定假设空间下的稳健性,不会修复数据泄漏、错误标签或缺失特征。

11 今天真正需要记住什么?#

  1. 线性 SVM 在所有可行边界中选择几何间隔最大的一个;间隔宽度由 2/w22/\|w\|_2 给出。
  2. 支持向量位于间隔边界内或附近,它们支撑最优解;远处样本越过间隔后不再产生合页损失。
  3. 软间隔用松弛变量容忍重叠与噪声,C 在小权重和少违规之间权衡。
  4. 合页损失 max(0,1yf)\max(0,1-yf) 让“分对但太靠近边界”的样本仍参与训练。
  5. SVM 必须重视尺度、数据划分和分数语义;decision_function 不是概率。

12 思考题与小练习#

练习 1:判断三个点的状态

yif(xi)y_if(x_i) 分别为 1.4、0.6、-0.2。对应合页损失是 0、0.4、1.2;第一个在间隔外,第二个分对但进入间隔,第三个分错。

练习 2:从参数得到几何宽度

w=[3,4]w=[3,4],则 w2=5\|w\|_2=5。中央边界到任一间隔面的距离是 1/51/5,完整间隔宽度是 2/5=0.42/5=0.4。把 w,bw,b 同时乘 2 不改变边界,却不再满足本文固定的规范化约束。

练习 3:画 C 的验证曲线

在 Pipeline 中比较 C=10^{-3},...,10^3,记录训练/验证平衡准确率、w\|w\| 和支持向量比例。解释为何训练分数通常随 C 增大而改善,验证分数却可能先升后降。

相关工作#

13 下一篇预告#

线性软间隔能容忍少量重叠,却仍只能画一条超平面。下一篇将把点积替换成核函数,手算 RBF 相似度如何让支持向量拼出弯曲边界,并看清 gammaC 为什么必须联合选择。

能分开数据的直线有很多,SVM 为什么选择最大间隔?
https://zwjcode.cn/blog/svm-maximum-margin-soft-margin
作者
发布于 2026年8月24日
版权协议 CC BY-NC-SA 4.0
评论加载似乎遇到了问题,请尝试刷新页面。