机器学习概论(1):识别垃圾邮件

机器学习概论作业一 Naïve Bayes classifier
中文邮件数据集来自https://plg.uwaterloo.ca/~gvcormac/treccorpus06/

实验目的

  • 实现一个Naïve Bayes classifier,并在真实的测试集上测试
  • 了解(1)如何在真实数据集上实现机器学习算法(2)如何评估模型(3)如何分析结果

实现方法

约定

符号 含义
S 垃圾邮件
H 非垃圾邮件
w(或wi) 单词
P(S) 邮件是垃圾邮件的概率(在这里是先验概率)
P(H) 邮件不是垃圾邮件的概率(在这里是先验概率)
P(S|w1w2...wn) 邮件包含w1,w2,...,wn时,是垃圾邮件的概率
P(H|w1w2...wn) 邮件包含w1,w2,...,wn时,不是垃圾邮件的概率
P(w1w2...wn|S) 一封垃圾邮件包含w1,w2,...,wn的概率
P(H|w1w2...wn) 一封非垃圾邮件包含w1,w2,...,wn的概率
参数 含义
DIVIDER_P 如果P(S|w1w2...wn) > DIVIDER_P则认为是垃圾邮件
SPAM_P P(S),邮件是垃圾邮件的概率(在这里是先验概率)
HAM_P P(H),也即1-P(S),邮件是非垃圾邮件的概率(在这里是先验概率)
MAX_NUM 为了降低计算复杂度,在计算垃圾邮件的后验概率时,仅选取MAX_NUM个出现最多的词参与计算
ALPHA Smoothing参数

概述

根据朴素贝叶斯方法,我们知道,

在识别垃圾邮件这个问题中x就是单词,y代表垃圾邮件或非垃圾邮件。那么,我们可以把原始公式改写成,

利用这个公式,我们就可以得到一封含有w1,w2,...,wn这些单词的邮件是垃圾邮件的概率是多少。
如果假设每个单词的出现相互独立,那么上式可以进一步化简为便于运算的形式,

为了防止P(wi|S)=0的情况出现,将使用线性平滑,即

其中,M为单词数。

基本步骤

  • 处理数据集:数据集提供了64620条邮件,邮件中包含了邮件头(收发件人等信息)和内容。在助教提供的文件中,已经将邮件进行了分词。我们需要做的是将这些邮件分为训练集和测试集两个集合,采取的方法为每次随机从数据集中选取p%的数据作为训练集,其他为测试集。
  • 训练模型:根据分词结果,统计每个词 (1)在多少封垃圾邮件中出现,(2)在多少封非垃圾邮件中出现。将这两个数字分别除以垃圾邮件的总数和非垃圾邮件的总数,即可得到P(w_i|S)P(w_i|H)。另外,从数据集中还可以求出P(S)P(H)
  • 测试模型:现在,我们已经得到了右式的全部参数值。对于用于测试的邮件,首先提取这个邮件中的每一个词w_i,带入上式,即可求得P(S|w_1,w_2,...,w_n)P(H|w_1,w_2,...,w_n)。如果P(S|w_1,w_2,...,w_n) > P(H|w_1,w_2,...,w_n)则认为是垃圾邮件。

针对特殊情况的“优化”

Note:之所以加引号,是因为绝大多数还不如原始的情况好,不过不失为一种尝试。

  • 识别教育邮箱:将.edu作为一个词加入到概率的计算中。
  • 加入邮件Header中的分词内容:在以上的实验中,只提取了邮件内容的分词结果。考虑到邮件的Header中也会有有用的feature(比如发信方,时间,标题),因此可以将Header中的分词内容加入计算。
  • 去除标点:句号和逗号等标点符号是出现频率很高但是对垃圾邮件识别没有什么用处的符号,可以在测试集和训练集的分词结果去除。(但是同时也保留了一些正常情况下很少有人用到的符号,比如五角星符号等)
  • 仅使用高频词:由于用于测试的邮件可能很长,有很多词,可能给计算造成负担,尤其时会导致精度不够。因此,可以在测试集上计算概率时,仅使用频率最高的一部分词(比如频率最高的15个)。

实验结果

评价指标

  • Accuracy
真实类别 预测正类 预测反类
正类(垃圾邮件) TP FN
反类(非垃圾邮件) FP TN
  • Precision
  • Recall
  • F1

测试结果

(测试集占全部数据的50%)

方法 Accuracy(%) Precision(%) Recall(%) F1(%)
无“优化” 98.44 98.16 99.51 98.83
识别教育邮箱 98.43 98.11 99.32 98.92
加入邮件Header中的分词内容 99.73 99.80 99.79 99.80
去除标点 98.43 98.26 99.38 98.82
仅使用高频词 96.57 95.77 99.22 97.46
最优 99.73 99.80 99.79 99.80
  • 识别教育邮箱
    结果无明显提高。
    处理数据集可以发现,发送方邮件地址为教育邮箱的邮件里,垃圾邮件有85封,而非垃圾邮件有13173封。可见,教育邮箱发送的邮件为非垃圾邮件的可能性更大。
    但是考虑到 (1)线性平滑之后P(w|S)P(w|H)的表达式中,分母比分子大很多,这导致即使垃圾邮件和非垃圾邮件的数目差别很大,但P(w|S)P(w|H)差别并不大 (2)教育邮箱只是作为一个词加入计算的,而邮件本身的词数很多,因此一个词的加入对结果的影响有限, 因此结果并没有明显提高。
    (事实上,如果把教育邮箱发送的邮件完全当做非垃圾邮件会导致准确率提高,但是可以看到,教育邮箱发送的邮件里是有垃圾邮件的,因此不能这样粗暴的下结论。)

  • 加入邮件Header中的分词内容
    结果有明显提高。
    分析训练集中的数据,可以看到在邮件的Header中存在很多有用的信息,这些有用的信息存在在Subject、邮件地址、时间等字段中。以以下的词为例,这些词在Header中大量存在,而在邮件内容中几乎不会出现,但是这些词在垃圾邮件和非垃圾邮件中出现的频率相差很大,因此是分辨垃圾邮件的重要词语。

    词语 垃圾邮件content中出现次数 非垃圾邮件content中出现次数 垃圾邮件header+content出现次数 非垃圾邮件header+content出现次数 在header中的字段
    spam-gw.ccert.edu.cn 0 0 21397 10913 To
    5.50.4133.2400 0 0 1377 0 X-Mailer
    text/plain;charset="GB2312" 0 0 11356 0 Content-Type
    Sun 0 0 3319 1566 Date
    =?gb2312?B?0rXO8aOht6LGsbT6v6qjoQ==?= 0 0 106 0 Subject
  • 去除标点
    结果无明显提高。
    去除的标点集为[' ', '、', ',', '。', '(', ')', '*', '!', '/', '【', '】', ':', '<', '>', '[', ']', '‘', '’', '“', '”', '(', ')', '?', ',', '.', '!', ':']。这些标点都非常常见,因此在垃圾邮件和非垃圾邮件中出现的频率差不多,对于分辨垃圾邮件和非垃圾邮件没有太大的影响。

  • 仅使用高频词
    结果变差。
    仅使用高频词会存在以下两种问题:

    • 高频词不具有代表性,在垃圾邮件和非垃圾邮件中出现频率相当,无法有效用于分辨垃圾邮件。以以下几个词为例,这些词均为测试集中的高频词(出现次数超过1000次),但在训练集中,在垃圾邮件中出现的次数和在非垃圾邮件出现的次数相差不大(小于20)。

      词语 在测试集中出现次数 在训练集的垃圾邮件中出现次数 在训练集的非垃圾邮件的出现次数
      找到 1309 622 604
      7427 3697 3692
      老师 1177 565 569
      对于 1491 710 725
    • 未被考虑的低频词具有代表性,可以帮助有效的分辨垃圾邮件,但没有纳入计算。以以下几个词为例,这些词均为测试集中的低频词(出现次数小于20次),但在训练集中,在垃圾邮件中出现的次数和在非垃圾邮件出现的次数相差比较大(大于35)且主要出现在垃圾邮件中。

      词语 在测试集中出现次数 在训练集的垃圾邮件中出现次数 在训练集的非垃圾邮件的出现次数
      形象设计 19 36 0
      13728276055 18 40 0
      7978018 18 40 0
      szhly268 17 39 0
      80982608 18 40 0
      13538747037 18 40 0
      包袋 11 36 0

参数比较

  • Smoothing参数α:采用无“优化”的方法,测试集50%

    α Accuracy(%) Precision(%) Recall(%) F1(%)
    0.005 98.57 98.33 99.54 98.23
    0.01 98.44 98.16 99.51 98.83
    0.05 98.06 97.42 99.72 98.56
    0.1 97.61 96.75 99.76 98.23

    α取值太大会导致正确率下降,我认为原因是α过大时,计算P(w|S)P(w|H)时分母远大于分子,导致计算对分子大小也即该词在垃圾邮件和非垃圾邮件中的出现次数不敏感,因此准确率下降。

  • 测试集大小:采用无“优化”的方法

    测试集比例 Accuracy(%) Precision(%) Recall(%) F1(%)
    0.05 97.38 96.71 99.44 98.05
    0.25 98.26 97.89 99.51 98.70
    0.5 98.44 98.16 99.51 98.83
    0.95 98.58 98.37 99.48 98.92

    测试集越大,准确率越高。这是因为测试集越大,概率的估计越接近真实值,因此得到的估计值也更准确。
    另外,在测试集较小时准确率提高比较快,测试集较大时准确率提高比较慢。

实验总结

针对本次实验过程,做以下几点总结:

  • 实验中遇到的最严重的问题是,在获得测试集答案时,如果把所有词的频率乘在一起,结果会超出精度,这样会导致计算出的为垃圾邮件的概率和不为垃圾邮件的概率均为0,从而无法比较。有效的解决方法是将乘法改为取log后加法。
  • 应该先实现基本方法,再逐一累加可能的改进策略。我在一开始就添加了很多新feature,但是最后发现结果甚至不如裸Naive Bayes的效果好。

参考资料

  • http://www.ruanyifeng.com/blog/2011/08/bayesian_inference_part_two.html
  • https://blog.csdn.net/pipisorry/article/details/52574156

你可能感兴趣的:(机器学习概论(1):识别垃圾邮件)