前言

随着微信的迅速发展,工作和生活中的交流也更多依赖于此,但是由于邮件的正式性和规范性,其仍然不可被取代。但是不管是企业内部工作邮箱,还是个人邮箱,总是收到各种各样的垃圾邮件,包括商家的广告、打折促销信息、澳门博彩邮件、理财推广信息等等,不管如何进行垃圾邮件分类,总有漏网之鱼。最重要的是,不同用户对于垃圾邮件的定义并不一致。

而且大部分用户网络安全意识比较一般,万一误点垃圾邮件上钩,或者因为垃圾邮件淹没了工作中的关键信件,则会给个人或者企业造成损失。

垃圾邮件识别一直以来都是痛点难点,虽然方法无非是基于贝叶斯学习或者是概率统计还是深度学习的方法,但是由于业务场景的多样化,垃圾邮件花样实在太多了,所以传统垃圾邮件拦截器总是有点跟不上。

因此打算针对同一数据集,逐步尝试各种方法,来进行垃圾邮件的识别分类——希望假以时日,这种定制化的垃圾邮件识别工具能大幅提升用户的邮箱使用体验。

一、整体思路

总的来说,一封邮件可以分为发送人、接收人、抄送人、主题、时间、内容等要素,所以很自然的可以认为主要通过上述要素中的发送方、主题以及内容来进行垃圾邮件判断。

因此我们依次对上述要素进行分析:

  • 垃圾邮件内容分类(通过提取垃圾邮件内容进行判断)

    • 中文垃圾邮件分类
    • 英文垃圾邮件分类
  • 垃圾邮件标题分类
  • 垃圾邮件发送方分类

最终,我们可以根据这三个维度进行综合评判,从而实现垃圾邮件的准确分类。本文将根据邮件内容进行垃圾邮件分类。

二、中文邮件内容分类实现步骤

1.数据集介绍

TREC 2006 Spam Track Public Corpora首先我们选择TREC 2006 Spam Track Public Corpora这一个公开的垃圾邮件语料库。该语料库由国际文本检索会议提供,分为英文数据集(trec06p)和中文数据集(trec06c),其中所含的邮件均来源于真实邮件保留了邮件的原有格式和内容。

文件目录形式:delay和full分别是一种垃圾邮件过滤器的过滤机制,full目录下,是理想的邮件分类结果,我们可以视为研究的标签。

trec06c

└───data
│   │   000
│   │   001
│   │   ...
│   └───215
└───delay
│   │   index
└───full
│   │   index

2.数据加载

2.1 从eml格式中提取邮件要素并且存储成csv

由于目前数据集是存储成邮件的形式,并且通过索引进行垃圾邮件标注,所以我们先提取每一封邮件的发件人、收件人、抄送人、主题、发送时间、内容以及是否垃圾邮件标签。

mailTable=pd.DataFrame(columns=('Sender','Receiver','CarbonCopy','Subject','Date','Body','isSpam'))
# path='trec06p/full/../data/000/004'
# emlContent= emlAnayalyse(path)
# print(emlContent)
f = open('trec06c/full/index', 'r')
csvfile=open('mailChinese.csv','w',newline='',encoding='utf-8')
writer=csv.writer(csvfile)
for line in f:str_list = line.split(" ")print(str_list[1])# 设置垃圾邮件的标签为0if str_list[0] == 'spam':label = '0'# 设置正常邮件标签为1elif str_list[0] == 'ham':label = '1'emlContent= emlAnayalyse('trec06c/full/' + str(str_list[1].split("\n")[0]))if emlContent is not None:writer.writerow([emlContent[0],emlContent[1],emlContent[2],emlContent[3],emlContent[4],emlContent[5],label])

其中emlAnayalyze函数利用flanker库中的mime,可以将邮件中的发件人、收件人、抄送人、主题、发送时间、内容等要素提取出来,具体可以参考我的这篇文章python几行代码实现邮件解析_Yunlord的博客-CSDN博客_flanker 邮件解析,然后存成csv,方便后续邮件分析。

2.2 从csv中提取邮件内容进行分类

def get_data(path):'''获取数据:return: 文本数据,对应的labels'''maildf = pd.read_csv(path,header=None, names=['Sender','Receiver','“CarbonCopy','Subject','Date','Body','isSpam'])filteredmaildf=maildf[maildf['Body'].notnull()]corpus=filteredmaildf['Body']labels=filteredmaildf['isSpam']corpus=list(corpus)labels=list(labels)return corpus, labels

通过get_data函数读取csv格式数据,并且提取出内容不为空的数据,和对应的标签。

可以看到一共有40348个数据。

from sklearn.model_selection import train_test_split
# 对数据进行划分
train_corpus, test_corpus, train_labels, test_labels = train_test_split(corpus, labels,test_size=0.3, random_state=0)

然后通过 sklearn.model_selection库中的train_test_split函数划分训练集、验证集。

# 进行归一化
norm_train_corpus = normalize_corpus(train_corpus)
norm_test_corpus = normalize_corpus(test_corpus)

然后通过normalize_corpus函数对数据进行预处理。

def textParse(text):listOfTokens=jieba.lcut(text)newList=[re.sub(r'\W*','',s) for s in listOfTokens]filtered_text=[tok for tok in newList if len(tok)>0]return filtered_textdef remove_stopwords(tokens):filtered_tokens = [token for token in tokens if token not in stopword_list]filtered_text = ' '.join(filtered_tokens)return filtered_textdef normalize_corpus(corpus, tokenize=False):normalized_corpus = []for text in corpus:filtered_text = textParse(filtered_text)filtered_text = remove_stopwords(filtered_text)normalized_corpus.append(filtered_text)return normalized_corpus

里面包括textParse、remove_stopwords这两个数据预处理操作。

textParse函数先通过jieba进行分词,然后去除无用字符。

remove_stopwords函数先是加载stop_words.txt停用词表,然后去除停用词。

从而实现数据预处理。

2.3 构建词向量

# 词袋模型特征
bow_vectorizer, bow_train_features = bow_extractor(norm_train_corpus)
bow_test_features = bow_vectorizer.transform(norm_test_corpus)# tfidf 特征
tfidf_vectorizer, tfidf_train_features = tfidf_extractor(norm_train_corpus)
tfidf_test_features = tfidf_vectorizer.transform(norm_test_corpus)

其中bow_extractor,tfidf_extractor两个函数分别将训练集转化为词袋模型特征和tfidf特征。

from sklearn.feature_extraction.text import CountVectorizerdef bow_extractor(corpus, ngram_range=(1, 1)):vectorizer = CountVectorizer(min_df=1, ngram_range=ngram_range)features = vectorizer.fit_transform(corpus)return vectorizer, featuresfrom sklearn.feature_extraction.text import TfidfTransformerdef tfidf_transformer(bow_matrix):transformer = TfidfTransformer(norm='l2',smooth_idf=True,use_idf=True)tfidf_matrix = transformer.fit_transform(bow_matrix)return transformer, tfidf_matrixfrom sklearn.feature_extraction.text import TfidfVectorizerdef tfidf_extractor(corpus, ngram_range=(1, 1)):vectorizer = TfidfVectorizer(min_df=1,norm='l2',smooth_idf=True,use_idf=True,ngram_range=ngram_range)features = vectorizer.fit_transform(corpus)return vectorizer, features

2.4 训练模型以及评估

对如上两种不同的向量表示法,分别训练贝叶斯分类器、逻辑回归分类器、支持向量机分类器,从而验证效果。

from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import SGDClassifier
from sklearn.linear_model import LogisticRegression
mnb = MultinomialNB()
svm = SGDClassifier(loss='hinge', n_iter_no_change=100)
lr = LogisticRegression()# 基于词袋模型的多项朴素贝叶斯
print("基于词袋模型特征的贝叶斯分类器")
mnb_bow_predictions = train_predict_evaluate_model(classifier=mnb,train_features=bow_train_features,train_labels=train_labels,test_features=bow_test_features,test_labels=test_labels)# 基于词袋模型特征的逻辑回归
print("基于词袋模型特征的逻辑回归")
lr_bow_predictions = train_predict_evaluate_model(classifier=lr,train_features=bow_train_features,train_labels=train_labels,test_features=bow_test_features,test_labels=test_labels)# 基于词袋模型的支持向量机方法
print("基于词袋模型的支持向量机")
svm_bow_predictions = train_predict_evaluate_model(classifier=svm,train_features=bow_train_features,train_labels=train_labels,test_features=bow_test_features,test_labels=test_labels)
joblib.dump(svm, 'svm_bow.pkl')# 基于tfidf的多项式朴素贝叶斯模型
print("基于tfidf的贝叶斯模型")
mnb_tfidf_predictions = train_predict_evaluate_model(classifier=mnb,train_features=tfidf_train_features,train_labels=train_labels,test_features=tfidf_test_features,test_labels=test_labels)
# 基于tfidf的逻辑回归模型
print("基于tfidf的逻辑回归模型")
lr_tfidf_predictions=train_predict_evaluate_model(classifier=lr,train_features=tfidf_train_features,train_labels=train_labels,test_features=tfidf_test_features,test_labels=test_labels)# 基于tfidf的支持向量机模型
print("基于tfidf的支持向量机模型")
svm_tfidf_predictions = train_predict_evaluate_model(classifier=svm,train_features=tfidf_train_features,train_labels=train_labels,test_features=tfidf_test_features,test_labels=test_labels)

输出结果如下所示

总结

通过针对邮件内容,并且转化为两种不同的词向量进行不同模型的训练,从而得到基于tfidf的支持向量机模型效果最好,可以达到98%的准确率。

想要一起从小白到大神,学习自然语言处理的朋友们可以点击下方链接或者订阅我的自然语言处理从小白到精通专栏,里面涉及到的工程部署以及完整代码实践全部免费赠送。


参考:

使用PaddleNLP识别垃圾邮件(一):准确率98.5%的垃圾邮件分类器 - 飞桨AI Studio - 人工智能学习与实训社区

垃圾邮件识别(一):用机器学习做中文邮件内容分类相关推荐

  1. 如何用Python和BERT做中文文本二元分类?| 程序员硬核评测

    点击上方↑↑↑蓝字关注我们~ 「2019 Python开发者日」全日程揭晓,请扫码咨询 ↑↑↑ 作者 | 王树义 来源 | 王树芝兰(ID:nkwangshuyi) 兴奋 去年, Google 的 B ...

  2. python垃圾邮件识别_【Python】垃圾邮件识别

    下载W3Cschool手机App,0基础随时随地学编程 导语 利用简单的机器学习算法实现垃圾邮件识别. 让我们愉快地开始吧~ 相关文件 密码: qa49 数据集源于网络,侵歉删. 开发工具 Pytho ...

  3. utf—8在苹果手机上乱码_【研究】解决iPhone中文邮件乱码的四种方法

    转载自FTidea.com 众所周知,由于iPhone目前在MobileMail中尚不支持除UTF-8之外的其它编码,而大部分国内中文邮件采用GB2312编码,造成中文邮件大多在iPhone上显示乱码 ...

  4. 如何用 Python 和循环神经网络(RNN)做中文文本分类?

    本文为你展示,如何使用 fasttext 词嵌入预训练模型和循环神经网络(RNN), 在 Keras 深度学习框架上对中文评论信息进行情感分类. 疑问 回顾一下,之前咱们讲了很多关于中文文本分类的内容 ...

  5. python垃圾邮件识别_Python贝叶斯推理垃圾邮件分类

    针对贝叶斯垃圾邮件分类,阮一峰大神在多年前曾经写过一篇博客文章,他写的有些观点看起来很简单明了,不过我有点不是很理解其推导过程,虽然最后的结果等价,但是我还是觉得他的那套简单推导,感觉不太容易理解,可 ...

  6. python垃圾邮件识别_Python 手写朴素贝叶斯分类器检测垃圾邮件/短信

    自己从头手写一下这些经典的算法,不调用 sklearn 等 API,调一调参数,蛮有收获和启发. 数据集 概要:5572 条短信,13% 的 spam. 选择这个数据集的原因:短信的文本预处理要比 e ...

  7. 垃圾邮件识别-朴素贝叶斯算法

    1.数据集 垃圾邮件识别使用的数据集为Enron-Spam数据集,该数据集是目前在电子邮件相关研究中使用最多的公开数据集,其邮件数据是安然公司(Enron Corporation, 原是世界上最大的综 ...

  8. pythonocr训练模型_cnocr: cnocr是用来做中文OCR的Python 3包。cnocr自带了训练好的识别模型,安装后即可直接使用...

    English README. cnocr 使用交流QQ群 欢迎扫码加入QQ交流群: Release Notes Update 2020.04.21: 发布 cnocr V1.1.0 V1.1.0对代 ...

  9. 基于朴素贝叶斯的垃圾邮件识别

    在网上看到很多用朴素贝叶斯算法来实现垃圾邮件分类的,有直接调用库的,也有自己写的.出于对贝叶斯算法的复习,我也想用贝叶斯算法写写邮件识别,做一个简单的识别系统. 一.开发环境 Python3.6,邮件 ...

  10. 全网顶尖,毫不夸张的说这份斯坦福大学机器学习教程中文笔记,能让你机器学习从入门到精通

    人工智能 人工智能,无疑是现在最火的概念,从AlphaGo打败李世石后,全世界掀起了一股人工智能的浪潮.我们在生活中的各个角落,都能感受到一个崭新的奇点时代即将来临 人工智能充气鞋垫 人工智能马桶 ( ...

最新文章

  1. 双边滤波算法的简易实现bilateralFilter
  2. linux查看内存、CPU占用资源最多的进程
  3. Android夜间模式的几种实现
  4. 4.day11_包和权限修饰符-1
  5. 基础命令之cd,mkdir,cp,ls
  6. Spring中的异步和事务性事件侦听器
  7. java单例模式的实现方法_JAVA单例模式的几种实现方法
  8. java 线程 spring_java中spring里实现多线程
  9. 五一高铁票难抢?用RPA机器人试试!
  10. 大一C语言大作业ip合法性,c语言实现判断ip地址是否合法
  11. 关于一些java命令作用
  12. 社区计算机考试内容,社区工作人员计算机考试大纲
  13. ★★★HEU_KMS_Activator_v7.5 (附详细说明文档)
  14. 数字积分法直线插补c语言,5.数字积分法直线插补.pdf
  15. Bootstrap小图标
  16. 用matlab实现“太阳-地球-月亮运行示意图”动画
  17. RocketMQ Message相关命令【实战笔记】
  18. Package com.myapp signatures do not match the previously installed version
  19. React Native的Navigator详解
  20. 第一章:1-03、试从多个方面比较电路交换、报文交换和分组交换的主要优缺点。...

热门文章

  1. 如何优雅的选择字体(font-family) 1
  2. 测试手机功耗软件,借助软件测试手机基本峰值功耗
  3. 如何用一个例子彻底解释白盒测试中语句覆盖、判定覆盖、条件覆盖、条件判定覆盖、条件组合覆盖?
  4. 新闻发布系统设计说明书
  5. 51单片机开发板介绍
  6. 计算机应用程序设计师,2018年上半年软件设计师真题+答案解析上午选择+下午案例完整版(全国计算机软考).pdf...
  7. 数学分析教程(科大)——6.1笔记+习题
  8. 2020-2022 抗疫营销案例合集(共17份)
  9. 【金融人士工具大全】整理不易,且珍惜
  10. System Repair Engineer (SREng)介绍