机器学习——支持向量机

目录

前言

支持向量机的背景

理论知识

线性可分支持向量机

最大间隔超平面

最大化间隔的计算 

对偶问题

等式约束

不等式约束的KKT条件

拉格朗日乘子法:

软间隔与正则化

损失函数

 具体实现

垃圾邮件分类(SVM)

数据集准备

代码实现

运行结果

总结


前言

支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;SVM还包括核技巧,这使它成为实质上的非线性分类器。SVM的的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。SVM的的学习算法就是求解凸二次规划的最优化算法。

支持向量机的背景

支持向量机(Support Vector Machine)是Cortes和Vapnik于1995年首先提出的,它在解决小样本、非线性及高维模式识别中表现出许多特有的优势,并能够推广应用到函数拟合等其他机器学习问题中。支持向量机方法是建立在统计学习理论的VC 维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度,Accuracy)和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折衷,以期获得最好的推广能力(或称泛化能力)。

理论知识

线性可分支持向量机

给定训练样本集D=(x1,y1),(x2,y2),⋯,(xm,ym),其中yi∈{−1,+1}, 分类学习最基本的想法就是基于训练集D在样本空间中找到一个划分超平面,将不同类别的样本分开。

机器学习——支持向量机_第1张图片

问题:将训练样本分开的超平面可能有很多, 哪一个好呢?

机器学习——支持向量机_第2张图片

-应选择”正中间”, 容忍性好, 鲁棒性高, 泛化能力最强.
SVM:选择最大化决策边界的边缘

最大间隔超平面

从二维扩展到多维空间中时,将 D0 和 D1完全正确地划分开的 w^{T}x+b=0就成了一个超平面。

机器学习——支持向量机_第3张图片

支持向量:样本中距离超平面最近的一些点,这些点叫做支持向量。

为了使这个超平面更具鲁棒性,我们会去找最佳超平面,以最大间隔把两类样本分开的超平面,也称之为最大间隔超平面。

  • 两类样本分别分割在该超平面的两侧;
  • 两侧距离超平面最近的样本点到超平面的距离被最大化了。

最大化间隔的计算 

令 x+和 x− 位于决策边界上,标签分别为正、负的两个样本,考虑 x+ 到分
类线的距离为:

机器学习——支持向量机_第4张图片
因此,分类间隔为:
机器学习——支持向量机_第5张图片

最大化间隔: 寻找参数w和b , 使得下述公式最大

机器学习——支持向量机_第6张图片

对偶问题

等式约束

给定一个目标函数 f : Rn→R,希望找到x∈Rn,在满足约束条件g(x)=0的前提下,使得f(x)有最小值。该约束优化问题记为:

机器学习——支持向量机_第7张图片

可建立拉格朗日函数:

其中 λ 称为拉格朗日乘数。因此,可将原本的约束优化问题转换成等价的无约束优化问题:

分别对待求解参数求偏导,可得:机器学习——支持向量机_第8张图片

一般联立方程组可以得到相应的解。

不等式约束的KKT条件

将约束等式 g(x)=0 推广为不等式 g(x)≤0。这个约束优化问题可改为:

机器学习——支持向量机_第9张图片

同理,其拉格朗日函数为:

其约束范围为不等式,因此可等价转化成Karush-Kuhn-Tucker (KKT)条件:

机器学习——支持向量机_第10张图片

在此基础上,通过优化方式(如二次规划或SMO)求解其最优解。

拉格朗日乘子法:

– 第一步:引入拉格朗日乘子a_{i} ≥ 0得到拉格朗日函数:

机器学习——支持向量机_第11张图片

– 第二步:令L(w,b,a)对w和b的偏导为零:

机器学习——支持向量机_第12张图片

– 第三步:w, b回代到第一步:

机器学习——支持向量机_第13张图片

-Q: 若不存在一个能正确划分两类样本的超平面, 怎么办?
-A: 将样本从原始空间映射到一个更高维的特征空间, 使得样本在这个特征空间内线性可分

机器学习——支持向量机_第14张图片

虽然有些分类在二维平面上不可分,如上图的亦或关系,这时候我们可以考虑采用升维的方法,使得它在高纬可分,那么我们要如何经行升维操作呢,我们可以联想到我们从一维的点到二维的线我们是用一个函数关系对应起来,那么从二维到三维甚至更高维度,我们是不是也可以用一个函数来对应变换呢,答案是肯定的,这个函数就是我们说的核函数。我们看一下下面这幅图,我们利用核函数把它从二维变到三位这时候它就可分了。

机器学习——支持向量机_第15张图片

具体的操作如下:

变换:x\rightarrow \phi (x)

例如:ax_{1}^{2}+bx_{2}^{2}+cx_{1}x_{2}=1

映射:\Rightarrow w_{1}+w_{2}z_{2}+w_{3}z_{3}+b=0

\phi :R^{2}\rightarrow R^{3},(x_{a},x_{2})\leftrightarrow (z_{1},z_{2},z_{3}):=(x_{1}^{2},\sqrt{2}x_{1}x_{2},x_{2}^{2})

机器学习——支持向量机_第16张图片

基本想法:不显式地构造核映射, 而是设计核函数.

Mercer定理(充分非必要):只要对称函数值所对应的核矩阵半正定, 则该函数可作为核函数.

常用的核函数:

机器学习——支持向量机_第17张图片

软间隔与正则化

-Q:实际应用中,很难选择合适的核函数,使样本在特征空间中线性可分; 此外,线性可分的结果也很难断定是否是由过拟合造成的.
-A:引入“软间隔”的概念, 允许SVM在一些样本上不满足约束.

机器学习——支持向量机_第18张图片

损失函数

基本思路:最大化间隔的同时, 让不满足约束的样本应尽可能少.

其中C>0为惩罚参数;l_{0/1}是”0/1损失函数”

机器学习——支持向量机_第19张图片

存在问题:0/1损失函数非凸、非连续, 不易优化!

这时候我们的处理方法是:替代损失

机器学习——支持向量机_第20张图片

替代损失函数数学性质较好, 一般是0/1损失函数的上界

 具体实现

垃圾邮件分类(SVM)

数据集准备

使用数据集:

机器学习——支持向量机_第21张图片

样例邮件emailSample1.txt:

机器学习——支持向量机_第22张图片

单词表vocab.txt

机器学习——支持向量机_第23张图片

spamSample2.txt

代码实现

导入库

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.io as scio
from sklearn import svm 
import re #处理正则表达式的模块
import nltk #自然语言处理工具包

 邮件预处理

#查看样例邮件
f = open('emailSample1.txt', 'r').read()
print(f)

def processEmail(email):
    email = email.lower() #转化为小写
    email = re.sub('<[^<>]+>', ' ', email) #移除所有HTML标签
    email = re.sub('(http|https)://[^\s]*', 'httpaddr', email) #将所有的URL替换为'httpaddr'
    email = re.sub('[^\s]+@[^\s]+', 'emailaddr', email) #将所有的地址替换为'emailaddr'
    email = re.sub('\d+', 'number', email) #将所有数字替换为'number'
    email = re.sub('[$]+', 'dollar', email) #将所有美元符号($)替换为'dollar'
    
    #将所有单词还原为词根//移除所有非文字类型,空格调整
    stemmer = nltk.stem.PorterStemmer() #使用Porter算法
    tokens = re.split('[ @$/#.-:&*+=\[\]?!()\{\},\'\">_<;%]', email) #把邮件分割成单个的字符串,[]里面为各种分隔符
    tokenlist = []
    for token in tokens:
        token = re.sub('[^a-zA-Z0-9]', '', token) #去掉任何非字母数字字符
        try: #porterStemmer有时会出现问题,因此用try
            token = stemmer.stem(token) #词根
        except:
            token = ''
        if len(token) < 1: 
            continue #字符串长度小于1的不添加到tokenlist里
        tokenlist.append(token)
    
    return tokenlist

#查看处理后的样例
processed_f = processEmail(f)
for i in processed_f:
    print(i, end=' ')

#得到单词表,序号为索引号+1
vocab_list = np.loadtxt('vocab.txt', dtype='str', usecols=1)
#得到词汇表中的序号
def word_indices(processed_f, vocab_list):
    indices = []
    for i in range(len(processed_f)):
        for j in range(len(vocab_list)):
            if processed_f[i]!=vocab_list[j]:
                continue
            indices.append(j+1)
    return indices

#查看样例序号
f_indices = word_indices(processed_f, vocab_list)
for i in f_indices:
    print(i, end=' ')

特征提取

def emailFeatures(indices):
    features = np.zeros((1899))
    for each in indices:
        features[each-1] = 1 #若indices在对应单词表的位置上词语存在则记为1
    return features
        
sum(emailFeatures(f_indices)) #45

训练SVM

#训练模型
train = scio.loadmat('spamTrain.mat')
train_x = train['X']
train_y = train['y']

clf = svm.SVC(C=0.1, kernel='linear')
clf.fit(train_x, train_y)

#精度
def accuracy(clf, x, y):
    predict_y = clf.predict(x)
    m = y.size
    count = 0
    for i in range(m):
        count = count + np.abs(int(predict_y[i])-int(y[i])) #避免溢出错误得到225
    return 1-float(count/m) 

train_accuracy = accuracy(clf, train_x, train_y) #0.99825
print("Train accuracy:", train_accuracy)

#测试模型
test = scio.loadmat('spamTest.mat')

test_accuracy = accuracy(clf, test['Xtest'], test['ytest']) #0.989
print("Test accuracy:", test_accuracy)

 提取高权重词

#打印权重最高的前15个词,邮件中出现这些词更容易是垃圾邮件
i = (clf.coef_).size-1
while i >1883:
    #返回从小到大排序的索引,然后再打印
    print(vocab_list[np.argsort(clf.coef_).flatten()[i]], end=' ')
    i = i-1

预测邮件(邮件分类) 

t = open('spamSample2.txt', 'r').read()
#预处理
processed_f = processEmail(t) 
f_indices = word_indices(processed_f, vocab_list)
#特征提取
x = np.reshape(emailFeatures(f_indices), (1,1899))
#预测
clf.predict(x)

运行结果

机器学习——支持向量机_第24张图片

由此可以看出我们训练精度和测试精度分别为0.99825和0.989:

精度还是很高的。

然后我们测试的spamSample2.txt被归类为垃圾邮件,分类正确。

机器学习——支持向量机_第25张图片

总结

        在这个实验中,我探索了支持向量机(Support Vector Machine,SVM)算法,并成功地将其应用于垃圾邮件分类任务。我首先学习了线性可分支持向量机的基本原理,其中最关键的概念是最大间隔超平面。通过找到能够将不同类别的样本点分开的超平面,我们能够实现高效的分类。为了解决线性不可分的问题,我们引入了对偶问题和核函数的概念。通过对偶问题,我们可以将原始问题转化为一个更容易求解的形式。同时,核函数的使用使得我们能够将低维空间中线性不可分的问题映射到高维空间中,从而实现了非线性分类。我们还研究了软间隔和正则化的概念,以处理数据中的噪声和异常值。软间隔允许一些样本点落在超平面的错误一侧,从而提高了模型的鲁棒性。正则化则通过引入惩罚项来防止过拟合,从而增强了模型的泛化能力。

        在实际实现中,我们使用了合适的特征提取和预处理技术,将原始邮件数据转化为适合输入SVM模型的特征向量表示。通过调整SVM模型的超参数和选择合适的核函数类型,我们对模型进行了训练和优化。最后,在测试集上评估了我们训练好的SVM模型的性能。我们使用了准确率等指标来衡量模型的分类性能,并通过混淆矩阵来分析模型在不同类别上的表现。通过这个实验,我们深入理解了支持向量机算法的基本原理和关键概念。我们成功地应用SVM算法解决了垃圾邮件分类问题,并获得了较高的分类准确率。这个实验不仅提升了我们对支持向量机的理论理解,还增强了我们在实际应用中使用该算法的能力。

        总体而言,这个实验为我提供了宝贵的经验和见解,使我能够更好地理解和应用支持向量机算法。通过实验的过程,我不仅改进了机器学习和模式识别领域的知识,还培养了解决实际问题的能力。这个实验为我未来的研究和工作奠定了坚实的基础。

你可能感兴趣的:(机器学习,支持向量机,人工智能)