一、SVM的介绍

  支持向量机(support vector machines,SVM)是一种二分类模型,它将实例的特征向量映射为空间中的一些点,SVM 的目的就是想要画出一条线,以 “最好地” 区分这两类点,以至如果以后有了新的点,这条线也能做出很好的分类。SVM 适合中小型数据样本、非线性、高维的分类问题。

  SVM 最早是由 Vladimir N. Vapnik 和 Alexey Ya. Chervonenkis 在1963年提出,目前的版本(soft margin)是由 Corinna Cortes 和 Vapnik 在1993年提出,并在1995年发表。深度学习(2012)出现之前,SVM 被认为机器学习中近十几年来最成功,表现最好的算法。

二、算法原理
  1. 超平面(Hyperplane)

    • 在二维空间中,超平面是一条直线;在三维空间中是一个平面;在更高维空间中,则是一个维度比特征空间少一维的线性子空间。
    • 超平面的数学表达式为:

其中,w 是超平面的法向量,决定了超平面的方向;b 是截距,决定了超平面的位置     

      2. 支持向量(Support Vectors)

  1. 距离超平面最近的那些数据点,决定了超平面的位置,被称为 “支持向量”。
  2. 超平面与支持向量之间的距离称为间隔(Margin),间隔越大,分类器的泛化能力越强。

      3. 最大间隔超平面

        支持向量机的目标是找到一个超平面,使得两个类别之间的间隔最大化。这个间隔被称为“间隔”,它是两个类别中距离超平面最近的数据点到超平面的距离之和。

     4.硬间隔分类和软间隔分类

        若严格地规定所有的样本点都不在“缓冲区”,都正确的在两边,称为硬间隔分类; 但是在一般情况下,不易实现,这里有两个问题:
第一,它只对线性可分的数据起作用。第二,有异常值的干扰。

        为了避免这些问题,可使用软间隔分类:在保持“缓冲区”尽可能大和避免间隔违规之间找到一个良好的平衡,在sklearn中的SVM类,可以使用超参数 C(惩罚系数),控制了模型的复杂度和容错能力。较小的C值会导致容错能力较高(即更宽的缓冲区),可能会产生更多的错误分类(即间隔违规);较大的C值会导致容错能力较低,可能会产生更少的错误分类。

        5.核函数

核函数是特征转换函数,它可以将数据映射到高维特征空间中,从而更好地处理非线性关系。
核函数的作用是通过计算两个样本之间的相似度(内积)来替代显式地进行特征映射,从而避免了高维空间的计算开销。

在SVM中,核函数的选择非常重要,它决定了模型能够学习的函数空间。常见的核函数包括:

线性核函数(Linear Kernel):最简单的核函数,它在原始特征空间中直接计算内积,适用于线性可分的情况。K(X,y) = (X^T) * y

多项式核函数(Polynomial Kernel):通过多项式函数将数据映射到高维空间,可以处理一定程度的非线性关系。(可拟合出复杂的分割超平面,但可选参数太多,阶数高后计算困难,不稳定) K(X,y) = ( (X^T) * y + c ) ^ d , 其中 c 为常数,d 为多项式的阶数。

高斯核函数(Gaussian Kernel):也称为径向基函数(Radial Basis Function,RBF),通过高斯分布将数据映射到无穷维的特征空间,可以处理更复杂的非线性关系。形式为 K(x,y) = exp( -|| x-y || ^2 / (2 σ ^2) ) 。
|| x - y || 表示向量 x 和 y 之间的欧氏距离,即它们各个维度差值的平方和的平方根。
σ 是高斯核函数的参数,控制了样本之间相似度的衰减速度。σ 越小,样本之间的相似度下降得越快;σ 越大,样本之间的相似度下降得越慢。

sigmoid核函数(Sigmoid Kernel):通过sigmoid函数将数据映射到高维空间,适用于二分类问题。 σ(x) = 1 / (1 + exp(-x))

        6.算法与核函数的选择

假设特征数为N,训练数据集的样本个数为W,可按如下规则选择算法:

若N相对W较大,使用逻辑回归或线性核函数的SVM算法

若N较小,W中等大小(W为N的十倍左右),可使用高斯核函数的SVM算法

若N较小,W较大(W为N的五十倍以上),可以使用多项式核函数、高斯核函数的SVM算法

总之 ,数据大的问题,选择复杂一些的模型,反之,选择简单模型。

        7.分类与回归的选择

通常情况下,当标签值是离散型变量时,我们将问题视为分类问题,而当标签值是连续性变量时,我们将问题视为回归问题。在支持向量机(SVM)算法中,SVC用于分类,SVR用来做回归

        8.算法步骤

  1. 数据预处理:将数据集划分为训练集和测试集,并进行特征缩放(对数据进行标准化)。

  2. 构建模型:选择合适的核函数和惩罚系数,构建SVM模型。

  3. 训练模型:使用训练集对模型进行训练,通过最大化间隔来找到最优的超平面。

  4. 预测:使用训练好的模型对测试集进行预测。

三、支持向量机的算法实现

使用SVMs建立自己的垃圾邮件过滤器。首先需要将每个邮件x变成一个n维的特征向量,并训练一个分类器来分类给定的电子邮件x是否属于垃圾邮件(y=1)或者非垃圾邮件(y=0)。

数据集:emailSample1.txt, vocab.txt, spamTrain.mat, spamTest.mat

源代码:

email_features.py

import numpy as np

def email_features(word_indices, vocab_size=1899):
    features = np.zeros(vocab_size)
    for idx in word_indices:
        if 1 <= idx <= vocab_size:
            features[idx - 1] = 1
    return features

process_email.py

将一封邮件的原始文本内容,处理成一个词索引列表(用于后续特征向量构建)

import re
from nltk.stem import PorterStemmer

def read_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as f:
        return f.read()

def load_vocab(vocab_path='vocab.txt'):
    vocab = {}
    with open(vocab_path, 'r') as f:
        for line in f:
            index, word = line.strip().split()
            vocab[word] = int(index)
    return vocab

def process_email(file_path):
    content = read_file(file_path)
    content = content.lower()
    content = re.sub(r'<[^<>]+>', ' ', content)
    content = re.sub(r'[0-9]+', 'number', content)
    content = re.sub(r'(http|https)://[^\s]*', 'httpaddr', content)
    content = re.sub(r'[^\s]+@[^\s]+', 'emailaddr', content)
    content = re.sub(r'[$]+', 'dollar', content)
    content = re.sub(r'[^a-zA-Z0-9]', ' ', content)

    words = content.split()
    stemmer = PorterStemmer()
    vocab = load_vocab()
    word_indices = []

    for word in words:
        word = stemmer.stem(word)
        if word in vocab:
            word_indices.append(vocab[word])
    return word_indicesm

main.py

import scipy.io
from sklearn import svm
from sklearn.metrics import accuracy_score
from process_email import process_email
from email_features import email_features

# 加载训练数据
data = scipy.io.loadmat('spamTrain.mat')
X = data['X']
y = data['y'].ravel()

# 训练线性SVM
clf = svm.SVC(C=0.1, kernel='linear')
clf.fit(X, y)

# 在测试集上评估性能
test_data = scipy.io.loadmat('spamTest.mat')
Xtest = test_data['Xtest']
ytest = test_data['ytest'].ravel()

preds = clf.predict(Xtest)
print(f"Test Accuracy: {accuracy_score(ytest, preds) * 100:.2f}%")

# 示例邮件预测
word_indices = process_email('emailSample1.txt')
features = email_features(word_indices)
prediction = clf.predict([features])

print("Prediction for emailSample1.txt:")
print("Spam" if prediction[0] == 1 else "Not Spam")c

测试结果

四、总结

 支持向量机是一种监督学习算法,广泛应用于分类和回归任务。SVM的核心思想是寻找一个超平面,使得两个类别之间的间隔最大化,从而实现良好的分类效果。SVM有分类效果好,鲁棒性较好,泛化能力强,可解释性强,同时也有对大规模训练样本难以实施,核函数选择重要,对非线性问题处理能力有限的局限性。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐