SVM垃圾短信分类
一、概述
短信作为一种重要的交流手段,在人们的日常生活中正发挥越来越重要的作用。伴随着短信的广泛使用,垃圾短信也严重困扰着人们的生活。因此研究高效实用的垃圾短信分类方法很有必要。
垃圾短信通常包含广告、诈骗、色情、诅咒等内容,具有较为显著的特征。对垃圾短信分类问题的研究是垃圾短信过滤的必要基础。国内外在研究垃圾短信分类问题时,常用的分类算法主要包括三大类。一类是基于概率和信息理论的分类算法, 如朴素贝叶斯算法(Naive Bayes), 最大熵算法(MaximumEntropy)等; 另一类是基于TFIDF权值计算方法的分类算法, 这类算法包括Rocchio算法, TFIDF算法, k近邻算法(k Nearest Neighbors)等; 第三类是基于知识学习的分类算法, 如决策树(Decision Tree), 人工神经网络(Artificial Neural Networks), 支持向量机(Support Vector Machine),逻辑斯蒂回归模型(Logistic regression)等算法。 本文主要介绍基于 SVM 的分类方法。本文主要介绍基于SVM的垃圾短信分类方法。
支持向量机(Support Vector Machine,简称SVM,也叫做支撑向量机)方法是1995年Vipnik在解决模式识别(Pattern Recognition)问题时引入的一种经验学习方法。这种方法定义在向量空间中,问题的核心在于寻找一个最佳解决方案,将线性可分割空间中的点用一个决策面划分为两部分。 SVM方法的决策面是一个使用结构风险最小化(Structural Risk Minimization, SRM准则)原理构造的超平面。SVM方法是建立在统计学习理论的VC维理论和结构风险最小化原理基础上的,提供了一个与问题维数无关的刻画函数复杂性的方法,它引入高维特征空间,将输入空间的非线性决策边界转化为高维特征空间的线性决策边界,利用线性函数的对偶核,解决了数值优化的二次规划求解问题,根据有限的样本信息在模型的复杂性和学习能力之间寻求最佳折衷,以获得最好的推广能力,在解决小样本学习、非线性及高维模式识别问题中表现较好,在两类分类问题上效果最佳。
二、 SVM
2.1 算法介绍
支持向量机(support vector machines,SVM)是一种二类分类模型。它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;支持向量机还包括核技巧,这使它成为实质上的非线性分类器。支持向量机的学习策略就是间隔最大化,可形式化为一个求解凸二次规划(convex quadratic programming,不怕,附录有解释)的问题,也等价于正则化的合页损失函数(后面也有解释)的最小化问题。支持向量机的学习算法是求解凸二次规划的最优化算法。
支持向量机学习方法包含构建由简至繁的模型:线性可分支持向量机(linear support vector machine in linearly separable case)、线性支持向量机(linear support vector machine)及非线性支持向量机(non-linear support vector machine)。简单模型是复杂模型的基础,也是复杂模型的特殊情况。当训练数据线性可分时,通过硬间隔最大化(hard margin maximization),学习一个线性的分类器,即线性可 分支持向量机,又称为硬间隔支持向量机;当训练数据近似线性可分时,通过软间隔最大化(soft margin maximization),也学习一个线性的分类器,即线性支持向量机,又称为软间隔支持向量机;当训练数据线性不可分时,通过使用核技巧 (kernel trick)及软间隔最大化,学习非线性支持向量机。
考虑一个二类分类问题。假设输入空间与特征空间为两个不同的空间。输入空间为欧氏空间或离散集合,特征空间为欧氏空间或希尔伯特空间。线性可分支持向量机、线性支持向量机假设这两个空间的元素一一对应,并将输入空间中的输入映射为特征空间中的特征向量。非线性支持向量机利用一个从输入空间到特 征空间的非线性映射将输入映射为特征向量。所以,输入都由输入空间转换到特征空间,支持向量机的学习是在特征空间进行的。
假设给定一个特征空间上的训练数据集:
T=(x1,y1),(x2,y2),...,(xN,yN)
其中,
x1∈Rn,
yi=1.−1,
i=1,2,3,...,N。其中
x1是第
i个特征分量,也称为实例,yi为
xi的类标记,正负时分别称
xi为正例或负例;样本点
(xi,yi)称为样本点,再假设训练数据集是线性可分的。
学习的目标是在特征空间中找到一个分离超平面,能将实例分到不同的类。分离超平面对应于方程法向量方程w∗x+b=0,它由法向量w和截距b决定,可用(w,b)来表示。分离超平面将特征空间划分为两部分,一部分是正类,一部分是负类。法向量指向的一侧为正类,另一侧为负类。
一般地,当训练数据集线性可分时,存在无穷个分离超平面可将两类数据正确分开。感知机利用误分类最小的策略,求得分离超平面,不过这时的解有无穷多个。线性可分支持向量机利用间隔最大化求最优分离超平面,这时,解是唯一的。
对解线性分类问题,线性分类支持向量机是一种非常有效的方法。但是,有时分类问题是非线性的,这时可以使用非线性支持向量机.非线性支持向量机,其主要特点是利用核技巧(kernel trick)。为此,我们给出常用的核函数。
核函数:
- 线性核函数
k(x,xi)=x·xi
线性核,主要用于线性可分的情况,我们可以看到特征空间到输入空间的维度是一样的,其参数少速度快,对于线性可分数据,其分类效果很理想,因此我们通常首先尝试用线性核函数来做分类,看看效果如何,如果不行再换别的 - 多项式核函数
κ(x,xi)=((x·xi)+1)d
多项式核函数可以实现将低维的输入空间映射到高纬的特征空间,但是多项式核函数的参数多,当多项式的阶数比较高的时候,核矩阵的元素值将趋于无穷大或者无穷小,计算复杂度会大到无法计算。 - 高斯(RBF)核函数
κ(x,xi)=exp(−|x−xi|2σ2)
κ(x,xi)=exp(−||x−xi||2δ2)
高斯径向基函数是一种局部性强的核函数,其可以将一个样本映射到一个更高维的空间内,该核函数是应用最广的一个,无论大样本还是小样本都有比较好的性能,而且其相对于多项式核函数参数要少,因此大多数情况下在不知道用什么核函数的时候,优先使用高斯核函数。 - sigmoid核函数
κ(x,xi)=tanh(η<x,xi>+θ)
采用sigmoid核函数,支持向量机实现的就是一种多层神经网络。
2.2 实验过程
数据集读取和存储
原始短信数据共有数100万条,训练集80万,测试集20万。第一步需要从存储信息的原始txt文档中,分割出文本域和标签域。作为content和label分别存入对应的json文件中。对于测试集,我们只需将文本域提取出来作为content存储到相应的json文件中。
特征提取
我们使用jieba对数据进行分词,使用之前需要对一些非规范数据进行,如对电话号码xxx,特殊字符&“】等进行统一转换。对一些反复出现的无意义词汇,如‘的’等当用词进行筛选。
jieba分词的样式规范
输入:
# encoding=utf-8
import jieba
seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list)) # 全模式
seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list)) # 精确模式
seg_list = jieba.cut("他来到了网易杭研大厦") # 默认是精确模式
print(", ".join(seg_list))
seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所") # 搜索引擎模式
print(", ".join(seg_list))
输出:
【全模式】: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学
【精确模式】: 我/ 来到/ 北京/ 清华大学
【新词识别】:他, 来到, 了, 网易, 杭研, 大厦
【搜索引擎模式】: 小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所
这里我们采用了TF-IDF方式来构建词向量,对TfidfVectorizer(min-df, max-df)中min−df和max−df选取不同的参数,得到的特征矩阵的维度是不同的。注意,词向量中的元素是通过TF-IDF方式生成的,因此每个元素转换成了float型。因为整个训练集的词向量数量庞大,为了便于后续处理可以先将其存储为csr型的稀疏矩阵到mtx文件中,便于后续模型训练和验证。
数据标准化
存储的词向量矩阵和对应标签文件中包含了所需的训练集数据和测试集数据,因此在模型训练前首先需要将数据集进行分割,这里将数据取出后进行一定比例的随机分割。
从分割后的训练集和测试集中取出的数据,通常都是高度稀疏的向量形式,即使是以csr稀疏矩阵的形式进行存储,在实际运算过程中也是转为高维向量的形式在进行计算。因此无论从节省时间,空间,还是减少数据噪声,提高分类精度的角度,降维过程都必不可少。在数据稀疏时,通常采用的降维方式包括了PCA(主成分分析法),Random projections(稀疏随机投影)和Feature agglomeration(特征聚类)。这是网上常见的降维方法,但是我们在采用PCA进行降维时,python直接爆内存,可能是80万测试数据太大啦!我们只用10万条数据进行测试,采用PCA降到1000维后,进行SVM分类训练,发现降维的效率比不降维慢了太多,个人觉得可能是矩阵的结构发生了变化,未降维之前矩阵是稀疏矩阵,降维后变得相对稠密?故最终我们在进行实验时,并没有降维这一过程。
SVM分类器训练
scikit-learn中有着完备的关于SVM的算法,这里我们将其封装成一个训练器类,便于训练,调参,交叉验证以及在测试集上的评估。SVM根据其核函数的不同,可以分为各种不同类型,我们选取了四个核函数进行实验,分别为:线性核函数(linear),RBF核函数(rbf),多项式核函数(poly),sigmoid核函数(sigmoid)。
- 对于线性核函数,我们采用默认的参数。
- 对于多项式核函数,有三个参数。-d用来设置多项式核函数的最高此项次数,也就是公式中的d,默认值是3。-g用来设置核函数中的gamma参数设置,也就是公式中的第一个r(gamma),默认值是1/k(k是类别数)。-r用来设置核函数中的coef0,也就是公式中的第二个r,默认值是0。
- 对于RBF核函数,有一个参数。-g用来设置核函数中的gamma参数设置,也就是公式中的第一个r(gamma),默认值是1/k(k是类别数)。
- 对于sigmoid核函数,有两个参数。-g用来设置核函数中的gamma参数设置,也就是公式中的第一个r(gamma),默认值是1/k(k是类别数)。-r用来设置核函数中的coef0,也就是公式中的第二个r,默认值是0。
对于非线性核函数(rbf,poly,sigmoid),不同的参数取值会得到不同的实验结果,甚至还会造成模型的过拟合等情况。我们通过GridSearchCV方式来自动搜索最优参数。
2.3 实验结果及分析
训练集评估
选择不同的核函数对模型进行训练了,通过模型对训练数据分类的精度(precision),召回率(recall), F度量(f1-score)来对模型进行初步评估。
- 线性SVM分类器
linear | precision | recall | f1-score | support |
0 | 0.99 | 1.00 | 0.99 | 648031 |
1 | 0.98 | 0.93 | 0.95 | 71969 |
- 多项式SVM分类器
poly | precision | recall | f1-score | support |
0 | 0.99 | 1.00 | 1.00 | 648031 |
1 | 0.98 | 0.93 | 0.96 | 71969 |
- RBF_SVM分类器
rbf | precision | recall | f1-score | support |
0 | 0.99 | 1.00 | 1.00 | 648031 |
1 | 0.98 | 0.93 | 0.95 | 71969 |
- sigmoid_SVM
sigmoid | precision | recall | f1-score | support |
0 | 0.99 | 1.00 | 1.00 | 648031 |
1 | 0.98 | 0.93 | 0.95 | 71969 |
上面四个表给出了线性、多项式、RBF、sigmoid四个不同核函数SVM分类器在训练数据上表现的评价。因为垃圾短信类型分布的不平衡性,总体的评分本身没有多大的意义,因为将短信全部分为正常短信也能获得0.9以上的平均precision,recall和f1-score(前两者的调和平均数)。这里我们主要关注的是1类型(垃圾短信类型)的precision,只有将垃圾短信正确的分类出来,模型本身才有意义,而不是将本身正常的短信划分为正常,可以看出1类型的precision表现还不错。整体的表现还是令人满意的,且非线性核函数的表现优于线性核函数,但差异不大。
交差验证
训练数据较少的情况下,可以用 N折交差验证来一定程度的反映模型的准确性,同时可以做一个平均的度量,使得评价更佳稳定。这里交差验证的评价方式选择的是f1-score,当然也可以选择评价指标。
Cross-validation | 1 | 2 | 3 | 4 | 5 | Accuracy |
linear | 0.97305256 | 0.97245767 | 0.97257168 | 0.97261764 | 0 .97185628 | 0.97 (+/- 0.00) |
poly | 0.97461334 | 0.97384342 | 0.97403408 | 0.97392092 | 0.97328418 | 0.97 (+/- 0.00) |
rbf | 0.97446389 | 0.97354872 | 0.97381555 | 0.97362995 | 0.97307297 | 0.97 (+/- 0.00) |
sigmoid | 0.97303184 | 0.97245767 | 0.97256814 | 0.97255806 | 0.97183562 | 0.97 (+/- 0.00) |
通过观察交差验证的表现,我们可以看出模型的实际效果还是不错的,因为交差验证所采用的数据集相当于是独立于模型的,真实地模拟了现实中的数据。各个核函数SVM分类器的表现差异不大。
验证集评估
在得到最终训练模型后,我们终于可以用来检验测试数据了。之前我们分割了大约1/10的数据作为测试集,现在将它们导入模型中进行类别预测。不同的核函数模型在验证集上分类的精度(precision),召回率(recall), F度量(f1-score)的表现如下:
- 线性SVM分类器
linear | precision | recall | f1-score | support |
0 | 0.99 | 1.00 | 0.99 | 71969 |
1 | 1 | 0.98 | 0.93 | 8031 |
- 多项式SVM分类器
poly | precision | recall | f1-score | support |
0 | 0.99 | 1.00 | 1.00 | 71969 |
1 | 1 | 0.98 | 0.93 | 8031 |
- RBF_SVM分类器
rbf | precision | recall | f1-score | support |
0 | 0.99 | 1.00 | 1.00 | 71969 |
1 | 1 | 0.98 | 0.93 | 8031 |
- sigmoid_SVM分类器
sigmoid | precision | recall | f1-score | support |
0 | 0.99 | 1.00 | 0.99 | 71969 |
1 | 1 | 0.98 | 0.93 | 8031 |
为了更好的说明不同核函数的表现,我们引入混淆矩阵。
可以清楚的看到,正类样本中有一个被错分,负类样本中有两个被错分。即906个正常短信中有19个被错分为垃圾短信,94个垃圾短信中有17个被错分为正常短信。在只使用了10000多个样本数据的情况下,这样的分类精度还是可以接受的。
linear | poly | rbf | sigmoid | ||||
71785 | 184 | 71801 | 168 | 71789 | 180 | 71785 | 184 |
560 | 7471 | 526 | 7505 | 526 | 7505 | 560 | 7471 |
从上表中可以清楚的看到,对于线性SVM分类器,71969个正常短信中有184个被错分为垃圾短信,8031个垃圾短信中有560个被错分为正常短信。同理可以对核函数为poly,rbf,sigmoid函数的分类器进行分析。通过分析可以明显的看到,这样的分类精度是完全可以接受的。
三、总结
在实验的过程中,发现SVM效率极低,后续准备换个其他的算法,当然啦,这是不可能的!这只是《网络数据挖掘》的大作业而已,也不是我的研究方向,我还是很心疼自己的,斜眼笑!