贝叶斯垃圾邮件分类器
利用朴素贝叶斯算法,在给定训练数据上,训练一个垃圾分类器。有关朴素贝叶斯的基本思想,可以参见另一篇博客:https://zyj-nova.github.io/2020/02/09/%E6%9C%B4%E7%B4%A0%E8%B4%9D%E5%8F%B6%E6%96%AF%EF%BC%88Naive%20Bayes%EF%BC%89/
0 数据集获取
链接:https://pan.baidu.com/s/1P3Jg67nerg63GVbCkc1YJg ,提取码:576u 。
数据集为英文语料,分为训练集和测试集。训练集包含351封垃圾邮件(文件名标有“spmsg”)、351封正常邮件;测试集包含130封正常邮件和130封垃圾邮件。
1 特征提取
由于每一封邮件都不是数值型的特征,因此我们需要把他们编码。首先需要构建一个字典,统计所有邮件中单词出现的频率,同时删除字典中的非字母字符、长度为1的字符,之后取前3000个出现频率最高的作为最终的字典。
1 | n_dim = 3000 |
构建完字典以后,就可以对每一封邮件进行编码了。特征向量的每一个分量即邮件中出现的对应词频。例如邮件“do over,do again”可以被编码为$[0,0,…,2,…,1,…,1]$。每一个分量都代表对应的词频。
1 | # 将每个邮件转化为词频向量 |
2 计算概率
$P(word|y =spam) = P(word, spam) / P(spam)$,$P(word, spam)$即每个单词在垃圾邮件中出现的频数,$P(spam)$即垃圾邮件中所有单词的词频总和。正常邮件同理,得到概率矩阵。
1 | # 统计垃圾邮件中的所有词频和,以及各个词的频数 |
为了避免概率矩阵中出现0的情况,使得计算概率时出现乘0,最后让权重矩阵每个分量加一个非常小的扰动
1 | sigma = 1e-8 |
3 模型预测与评估
1 | pred_labels = [] |
注意:在计算概率的时候用到了一个trick,由于非常小的数不断连乘最后会趋于0,因此利用取对数的方法将乘法化为加法(极大似然估计就是这么干的)。同时取对数时不可以为0,上面加的非常小的扰动是很有必要的。
模型在测试集上的准确率、召回率、f1_score如下:
1 | recall_score : 0.9923076923076923 |