Spam-Classification
通过组员对题目和实验第一部分详细的讲解,我们对支持向量机是如何工作的以及如何使用支持向量机中的高斯核有了一个直观的认识,在第二部分中,我们要使用支持向量机解决一个实际的问题,垃圾邮件过滤,我们使用支持向量机构建垃圾邮件过滤器,也就是用数据训练一个分类器以分类电子邮件是否是垃圾邮件,垃圾邮件分类结果为1,非垃圾邮件分类结果为0
其中邮件数据集来源于阿帕奇的SpamAssassin公共语料库
本实验主要分为以下几个部分
邮件处理
在开始编程之前,我们首先需要建立模型。
对于垃圾邮件和正常邮件,应该怎样区分呢,通常来说,垃圾邮件中大概率会出现网址、数字、金额等信息,这是有别于正常邮件的地方,很自然的我们会想把这些信息作为特征提取出来,以便更好的实现邮件过滤。
那么下一步要做的就是考虑这些特征如何提取了,或许很多邮件中都会包含类似的数据,但是几乎每一封电子邮件中都是不同的。因此我们的思路是把这些数据简单的进行分类。打个比方,遇到一封邮件,如果出现了网址信息,我们并不关心他给出的网址是什么,我们知道在这一封邮件中出现了URL,那么根据经验,这封邮件是垃圾邮件的可能就比较大。
- 这样做的效果是让垃圾分类器根据是否存在任何URL而不是某个特定的URL来做出分类决策,以提高垃圾邮件分类器的性能。
那么具体如何实现呢,我们的思路是将这些值规范化,以便将各种各样的网址都视为相同的,所有的数字也视为相同的。
处理主要分为预处理和标准化两部分
我们之前说的将这些值规范化在预处理中进行,第二步的标准化的意思就是把预处理后的邮件文本信息和一个数组建立映射关系,其实说成字典会更好理解以下,用单词在字典中的位置作为特征值提取出来
预处理
1 | email_contents = lower(email_contents); |
- 邮件字母小写化,将整个电子邮件转换成小写,忽略大写的好处是能够更好的分辨单词
- 除去HTML标签,将所有HTML标签将从电子邮件中删除。许多电子邮件通常带有HTML格式,这些标签数据对我们的分类并没有帮助
- 规范化邮件地址,将所有的邮件地址替换为 emailaddr
- 规范化数字,将所有数字替换为 number
- 规范化金额,以美元$为例,将所有金额替换为 dollar
- 删除非单词符号和标点符号
- 单词词根化,就是把每个单词简化为词根形式,比如include、includes、included,都用include替换
标准化
在对电子邮件进行预处理之后,我们对其进行标准化,把每封电子邮件转换成一个单词索引矩阵,在这个过程中,我们选择了最经常出现的单词作为我们考虑的词汇表,实验所给的词汇表有1899个单词。
至于为什么不把出现次数比较少的单词纳入字典中,这不仅仅是他们的加入对模型的帮助不大,在训练的过程中,出现次数少的单词只出现在少数的电子邮件中,他们可能会导致模型过拟合我们的数据集。
那么接下来我们要做的就是逐单词遍历预处理后的邮件内容,与我们字典中的数据进行对比,找到就记录到word_indices[]矩阵中
1 | for i = 1:length(vocabList) |
特征提取
经过邮件处理,我们已经把一封邮件转换成了单词索引矩阵的形式,接下来进行特征的提取,在此过程中,我们把字典中给出的这些出现频次较高的数据全都视为特征,也就是说一封邮件的特征有1899个,若第i个单词出现了,那么第i个特征的特征值为1,否则为0
1 | for i = 1:length(word_indices) |
训练SVM
了解了如何提取出一封邮件的特征后,接下来要开始训练支持向量机。在此训练的数据是实验提供的,其中spamTrain.mat提供了4000封邮件的特征及其类型,spamTest.mat中提供了1000封邮件的特征。
训练结束后在训练集上做验证,得到了99.85%的正确率
然后在测试集上做验证,得到了98.9%的正确率
最佳预测词
为了更好的理解垃圾邮件分类器的工作原理,我们可以检查参数,看看分类器认为哪些单词是最能判定一封邮件是垃圾邮件的。
选做-测试自己的邮件
现在我们已经训练了一个垃圾邮件分类器,分类效果到底好不好,还是得自己试试看才知道发( •̀ ω •́ )✧
先试试从coursera收到的关于这门课程的邮件
结果是0,不是垃圾邮件 (没有打脸,Nice)
再试试网飞的推销订阅邮件(毫无疑问是垃圾邮件)
结果为1,是垃圾邮件 (Nice!!!)