支持向量机介绍与示例

支持向量机是一种做分类的模型。它要找的是一条把两类样本尽量分开的分界线,并且让这条线两侧留出的空白带尽量宽。落在空白带边缘上的那些点叫支持向量,分界线只由它们决定,离得更远的点不影响这条线。

分界线写成

w⋅x+b=0

w 是法向量,b 是截距。预测时看这个值的正负:大于 0 为一类,小于 0 为另一类。空白带的宽度是 2/∥w∥。所以训练时是在「分对所有点」的前提下,把 ∥w∥ 尽量变小。

用四个点就能把这件事看完。负类是 (1,1)、(1,2),正类是 (3,1)、(3,2)。左右两列之间最宽的空白在 x=2。对应的参数是 w=(1,0)、b=−2,判别式是

f(x,y)=x−2

代入检查:

  • (1,1):1−2=−1,判为负类,并且刚好贴在空白带边上,是支持向量。
  • (3,2):3−2=1,判为正类,也是支持向量。
  • 再加一个更远的负类点 (0,1.5):0−2=−2。它在带的外面,删掉它,分界线仍然是 x=2。

两边空白的总宽度是 2/∥w∥=2,和 x=1到 x=3 的距离一致。

实际数据常常混在一起,硬要完全分开会把空白挤得很窄。软间隔允许少量点越过边界或进到空白里,用惩罚系数 C控制:C大更强调分对,C 小更强调空白要宽。

还有一类数据用直线根本分不开,比如内圈是一类、外圈是另一类,或者异或:(0,0)、(1,1)一类,(0,1)、(1,0) 另一类。核函数先把点变到更高维,在那边用平面分开,算的时候却只需要两点的核值,不用真的写出高维坐标。常用的有线性核、多项式核和高斯核(RBF)。高斯核能围出弯曲的边界。

复制代码
def predict(x, y):
    score = x - 2          # w=(1, 0), b=-2
    return 1 if score > 0 else -1

print(predict(1, 1))       # -1
print(predict(3, 2))       # 1
print(predict(0, 1.5))     # -1,离边界更远,不是支持向量

它适合样本不算特别大、特征已经提取好、又希望边界清楚的分类问题。常见用途有:

  • 文本分类:垃圾邮件、情感、主题。词袋特征又高又稀疏,线性支持向量机很合适。
  • 图像里的传统检测:行人检测里,用 HOG 特征加上支持向量机,是深度学习普及前的常用做法。
  • 生物信息:基因表达、蛋白质是否属于某一类,样本往往只有几十到几百个。
  • 中小规模表格数据:欺诈、故障、合格/不合格。特征维数中等、类别大致可分时,效果稳定。
  • 异常检测:单类支持向量机只用正常样本学一个边界,落在外面的视为异常。

例子:文本分类用支持向量机,关键是先把一篇文字变成高维稀疏向量,再用一条线性分界来判类别。我用几条短文本把这个向量和判别过程走一遍。

文本分类用支持向量机,是先把一篇文章变成一组数字,再找一条最宽的分界线来区分类别。垃圾邮件、评论正负面、工单类型,都是这条流程。

一篇文字怎么变成向量

模型不能直接读句子,只能读数字。常用做法是词袋:先定一张词表,每个词占一维,文章里出现了该词就记次数,没出现就记 0。

用四篇已经标好的短文本做例子。词表按这个顺序:优惠、中奖、点击、会议、项目。

文本 标签 向量
优惠 中奖 垃圾 +1 (1, 1, 0, 0, 0)
优惠 点击 垃圾 +1 (1, 0, 1, 0, 0)
会议 项目 正常 -1 (0, 0, 0, 1, 1)
明天 会议 正常 -1 (0, 0, 0, 1, 0)

「明天」不在词表里,这一维直接丢掉。一篇文章通常只有几个词是 1,其余全是 0,所以向量又长又稀疏。线性支持向量机正好适合这种数据:分界是加权求和,计算只碰到那些非 0 的词。

对应的判别式可以写成

f(x)=1⋅x优惠+1⋅x中奖+1⋅x点击−1⋅x会议−1⋅x项目

f>0 判垃圾,f<0 判正常。

  • 「优惠 中奖」:1+1=2,垃圾。这两个词把分数顶到空白带边缘,是支持向量。
  • 「会议 项目」:−1−1=−2,正常。
  • 新来的「点击 优惠」:1+1=2,垃圾。训练时没见过这句组合,但两个词都在垃圾文本里出现过。
  • 「优惠 会议」:1−1=0,落在分界上。业务上可以交给人工,或看哪边的代价更大再定。

真正训练时,这些权重不是手写的,而是由「分对样本,并且空白带尽量宽」算出来的。软间隔里的 C 用来容忍个别标错或很难分的句子。

实际还要做的几步

分词。 中文先切成词,再用词做特征。英文一般转小写、去掉标点。HTML 标签、链接、重复空格先清掉。

用 TF-IDF 代替裸次数。 「的」「了」几乎每篇都有,区分力弱,权重压低;「中奖」「发票」只在少数文章里出现,权重提高。公式是词频乘以 log⁡(文章总数/包含该词的文章数)。连在一起的两个词也常作为特征,例如「免费 领取」,单看「免费」或「领取」都不如这一个组合像广告。

训练和预测用同一套词表。 训练时记下词表和每个词的 IDF。预测时按这张表把新文章变成向量,没见过的词忽略,再计算 f(x)。

from sklearn.feature_extraction.text import TfidfVectorizer

from sklearn.svm import LinearSVC

from sklearn.pipeline import Pipeline

docs = "优惠 中奖", "优惠 点击", "会议 项目", "明天 会议"

y = 1, 1, -1, -1

clf = Pipeline([

("tfidf", TfidfVectorizer(token_pattern=r"(?u)\b\w+\b", ngram_range=(1, 2))),

("svm", LinearSVC(C=1.0)),

])

clf.fit(docs, y)

print(clf.predict("点击 优惠")) # 1

print(clf.decision_function("点击 优惠")) # 离分界越远,越有把握

LinearSVC 是线性核。文本维数已经很高,一般用线性核;高斯核又慢,也容易过拟合。数据量大时,可以用 SGDClassifier(loss="hinge"),它是同一个间隔目标的在线训练版本。

类别多于两个时,比如新闻要分成体育、财经、科技,就训练多条「这一类 vs 其余类」的分界,预测时取得分最高的那一类。

上线时怎么判断好不好

看混淆矩阵,不要只看准确率。垃圾邮件里正常邮件被拦(误报)通常比漏掉一封广告更严重,所以要单独看正常类的精确率和召回率。类别差很多时,给少的那一类加大 class_weight="balanced"。

词表用训练集拟合。测试文案里的新词不要提前写进词表,否则评估会偏高。CC 用验证集选:太大时会把个别句子记死,太小时两类又分不开。

相关推荐
怕浪猫1 小时前
2028编程圈很火的10个Skills
算法·面试·github
别动我齐刘海3 小时前
Linux 系统调试学习1
linux·运维·服务器·c++·学习·机器学习·机器人
szxinmai主板定制专家5 小时前
储能EMS + 协调控制器实战:RK3568/3576/3588+FPGA+AI 故障录波与诊断
人工智能·深度学习·机器学习·fpga开发·rk3588·rk3576·协调控制器
努力努力再努力wz5 小时前
【机器学习入门系列】从随机事件到正态分布:一文梳理概率论的核心知识
人工智能·机器学习·概率论
Nil2086 小时前
leetcode 198打家劫舍
算法·leetcode·职场和发展
Shaoshing6 小时前
前缀和与差分
java·数据结构·算法·前缀和·差分
loulanyue_7 小时前
构建房产认知决策智能:Harness底座与AI自进化的技术实践——读贝壳首席算法科学家尹俊希2026云栖专场演讲
人工智能·算法
碧海银沙音频科技研究院7 小时前
基于炬芯ATS录音卡BLE控制协议
人工智能·嵌入式硬件·算法·语音识别
高洁017 小时前
AI赋能产业升级与中美未来经济赛道博弈
人工智能·python·深度学习·机器学习·transformer